Каков текущий режим выполнения / уровень исключения и т. д.?

Я новичок в архитектуре ARMv8. У меня на уме следующие основные вопросы:

  1. Как узнать, какой сейчас режим выполнения AArch32 или AArch64? Должен ли я прочитать CPSR или SPSR, чтобы убедиться в этом?

  2. Каков текущий уровень исключения, EL0/1/2/3?

  3. Как только возникает исключение, могу ли я прочитать любой регистр, чтобы определить, нахожусь ли я в обработчике исключений Serror/Synchronous/IRQ/FIQ.

ТИА.

2 ответа

  1. Инструкции по сборке и их двоичное кодирование совершенно различны для 32 и 64 бит. Таким образом, информация о том, в каком режиме вы находитесь в данный момент, вам / компилятору нужно знать во время компиляции. проверка их во время выполнения не имеет смысла. Для C проверка C++ может быть выполнена во время компиляции (#ifdef) через предоставленные компилятором макросы, подобные тем, которые предоставляются armclang: __aarch64__ для 64 бит, __arm__ для 32 бит
  2. зависит от режима исполнения:
    • aarch32: MRS <Rn>, CPSR читать текущее состояние в регистр номер n. Затем извлеките биты 3:0, которые содержат текущий режим.
    • aarch64: MRS <Xn>, CurrentEL прочитать текущий EL в регистр номер n
  3. краткий ответ: вы не можете. длинный ответ: предполагается, что по структуре кода и состоянию любых пользовательских переменных вы уже знаете, что делаете. то есть, пришли ли вы в позицию кода через обычный код или через исключение.

Код 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 с этой настройкой.

Другие вопросы по тегам