5
votes

I am new to ARMv8 architecture. I have following basic questions on my mind:

  1. How do I know what is the current execution mode AArch32 or AArch64? Should I read CPSR or SPSR to ascertain this?

  2. What is the current Exception level, EL0/1/2/3?

  3. Once an exception comes, can i read any register to determine whether I am in Serror/Synchronous/IRQ/FIQ exception handler.

TIA.

2
"How do I know what is the current execution mode AArch32 or AArch64?" - I figure if the the code trying to check the mode is compiled for 64-bit, the mode is 64-bit; if it's compiled for 32-bit the mode is 32-bit.JimmyB

2 Answers

8
votes
  1. The assembly instructions and their binary encoding are entirely different for 32 and 64 bit. So the information what mode you are currently in is something that you/ the compiler already needs to know during compilation. checking for them at runtime doesn't make sense. For C, C++ checking can be done at compile time (#ifdef) through compiler provided macros like the ones provided by armclang: __aarch64__ for 64 bit, __arm__ for 32 bit
  2. depends on the execution mode:
    • aarch32: MRS <Rn>, CPSR read the current state into register number n. Then extract bits 3:0 that contain the current mode.
    • aarch64: MRS <Xn>, CurrentEL read the current EL into register number n
  3. short answer: you can't. long answer: the assumption is that by the structure of the code and the state of any user defined variables, you already know what you are doing. i.e. whether you came to a position in code through regular code or through an exception.
2
votes

aarch64 C code:

register uint64_t x0 __asm__ ("x0");
__asm__ ("mrs x0, CurrentEL;" : : : "%x0");
printf("EL = %" PRIu64 "\n", x0 >> 2);

arm C code:

register uint32_t r0 __asm__ ("r0");
__asm__ ("mrs r0, CPSR" : : : "%r0");
printf("EL = %" PRIu32 "\n", r0 & 0x1F);

CurrentEL however is not readable from EL0 as shown on the ARMv8 manual C5.2.1 "CurrentEL, Current Exception Level" section "Accessibility". Trying to run it in Linux userland raises SIGILL. You could catch that signal however I suppose...

CPSR is readable from EL0 however.

Tested on QEMU and gem5 with this setup.