Каков текущий режим выполнения / уровень исключения и т. д.?
Я новичок в архитектуре ARMv8. У меня на уме следующие основные вопросы:
Как узнать, какой сейчас режим выполнения AArch32 или AArch64? Должен ли я прочитать CPSR или SPSR, чтобы убедиться в этом?
Каков текущий уровень исключения, EL0/1/2/3?
Как только возникает исключение, могу ли я прочитать любой регистр, чтобы определить, нахожусь ли я в обработчике исключений Serror/Synchronous/IRQ/FIQ.
ТИА.
2 ответа
- Инструкции по сборке и их двоичное кодирование совершенно различны для 32 и 64 бит. Таким образом, информация о том, в каком режиме вы находитесь в данный момент, вам / компилятору нужно знать во время компиляции. проверка их во время выполнения не имеет смысла. Для C проверка C++ может быть выполнена во время компиляции (
#ifdef
) через предоставленные компилятором макросы, подобные тем, которые предоставляютсяarmclang
:__aarch64__
для 64 бит,__arm__
для 32 бит - зависит от режима исполнения:
- aarch32:
MRS <Rn>, CPSR
читать текущее состояние в регистр номер n. Затем извлеките биты 3:0, которые содержат текущий режим. - aarch64:
MRS <Xn>, CurrentEL
прочитать текущий EL в регистр номер n
- aarch32:
- краткий ответ: вы не можете. длинный ответ: предполагается, что по структуре кода и состоянию любых пользовательских переменных вы уже знаете, что делаете. то есть, пришли ли вы в позицию кода через обычный код или через исключение.
Код Aarch64 C:
register uint64_t x0 __asm__ ("x0");
__asm__ ("mrs x0, CurrentEL;" : : : "%x0");
printf("EL = %" PRIu64 "\n", x0 >> 2);
код руки C:
register uint32_t r0 __asm__ ("r0");
__asm__ ("mrs r0, CPSR" : : : "%r0");
printf("EL = %" PRIu32 "\n", r0 & 0x1F);
Эти регистры обычно (всегда?) Защищены в пользовательской среде, так что вы должны сделать это из ядра Linux или из чистого примера.
Протестировано на QEMU и gem5 с этой настройкой.