2014-09-26 2 views
2

Я пишу код переключения потоков, в котором ядро ​​выгружает релевантное состояние в память, но фактический переключатель потока происходит полностью в пользовательском режиме.Восстановление состояния Thumb в пользовательском режиме

Это прекрасно работает, за исключением случая, когда точка превенции происходит внутри блока Thumb If-Then (IT). В этом случае я не могу решить, как восстановить ITSTATE (т.е. бит [15:10] и [26:25] CPSR), поскольку эти биты являются пользователями RAZ/WI, и в любом случае это, вероятно, не делает смысл с учетом семантики ITSTATE.

Что (если есть) - это правильный способ восстановить это состояние без попадания в ядро?

Я рассмотрел возможность перематывания и продолжения работы с инструкцией по ИТ, но, не считаясь с тяжелым весом, я не уверен, что это всегда возможно.

EDIT: заинтересованы в ARMv7-A

ответ

1

* Архитектурно, ни один из государственных исполнения битов в CPSR не могут быть считаны или записаны в любом режиме (за исключением бита CPSR.E в привилегированных режимах только, и даже это устарело). Единственный способ изменить их вне нормального исполнения - через SPSR в возврате исключения, который предполагает возврат непосредственно к соответствующей команде внутри IT-блока.

Как вы уже упоминали, перезапуск всего ИТ-блока не является ни практичным, ни безопасным, в основном из-за доступа к памяти - в то время как в большинстве случаев вы, вероятно, могли бы статически анализировать инструкции для изменения любых изменений регистра, любая разделяемая память может означать повторная загрузка возвращает другое значение, или повторное хранилище может повредить другой процесс, который прочитал и изменил исходное значение за это время. Что касается ввода/вывода с отображением памяти, неожиданно повторяющийся любой доступ к может потенциально быть опасным по ряду причин.

Еще одна потенциальная идея - создать JIT новый IT-блок на основе ITSTATE из SPSR и остальных инструкций на обратном адресе, поскольку Thumb-2 означает, что у вас есть LDR PC,..., чтобы вернуться к исходному коду из любого места с неповрежденными регистрами , Тем не менее, даже это все равно сломает ситуацию, если условные инструкции выполняют вычисления, относящиеся к ПК.

* на все, что имеет CPSR и поддерживает Thumb-2, во всяком случае

+0

Помимо памяти, у вас будет отменить любые операции с регистром, поскольку они будут сохранены * mid-IT-блок *. Даже это кажется трудным. Особенно, когда регистр, возможно, был забит * средним IT-блоком *, и вы не знаете, что это было. –

+0

Я не думаю, что сбитые регистры являются проблемой, потому что вам не нужно точно восстанавливать исходное состояние регистра, а скорее любое состояние, которое при применении IT-инструкций создает текущее состояние. – xac

+0

Возможно, в случае доступа к памяти было бы лучше свернуть вперед. В любом случае для этого действительно нужен эмулятор ISA, который не идеален. – xac

0

CPSR автоматически сохраняется в стеке на входе исключения, и он восстановлен из стека на возвращение исключения. Возможно, я не вижу вашей конкретной проблемы, но, как правило, вам нечего делать, чтобы этот контекст переключился на работу - если предположить, что это сделано в исключении, вы просто сохраняете оставшиеся регистры в стеке, переключаете указатель стека, сохраняете оставшиеся регистры и просто возвращаете из исключение ... Я также не знаю, какая именно архитектура вы используете, но вот очень простой контекстный переключатель для ARMv7-M (Cortex-M3/M4): https://github.com/DISTORTEC/distortos/blob/master/source/architecture/ARM/ARMv7-M/ARMv7-M-PendSV_Handler.cpp

+0

Он пытался сделать это из ** пользовательского пространства **. Я думаю, вы говорите об режиме исключения. Интересно, как 'setjmp/longjmp' работает на Cortex-M?Я думаю, вызов функции никогда не может произойти в середине условного блока. Я думаю, что на Cortex-M может работать только совместное планирование. [co-routines in c] (http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html) и [прото-темы] (http://dunkels.com/adam/pt/index. HTML). –

+1

setjmp()/longjmp() работают почти так же, как и исключения, но стекирование/распаковка регистров, выполняемых автоматически в случае исключения, выполняется вручную. Вот код из newlib - https://sourceware.org/git/gitweb.cgi?p=newlib.git;a=blob;f=newlib/libc/machine/arm/setjmp.S;h=a65fbabb9926f64557bea3d3d336bb1843ae6ae2;hb = ebbb290f6e15e71b140a911c0de530453b9f8443 - изменений в CPSR нет. Cortex-M может иметь упреждающее планирование - связанный мной проект является полностью упреждающим планировщиком для такого чипа ( –

+0

Да, мой вопрос был своего рода заявлением. Вам нужно обработать 'CPSR' (или что-то, что Cortex-M называет) для упреждающего планировщика и, следовательно, не может использовать * пользовательский режим *. Для совместного планирования вы можете сделать «setjmp/longjmp» и ограничить переходы контекста на не-IT-блоки и избежать проблемы. –