Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what is the current execution mode/exception level, etc?

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.

like image 847
crazzy Avatar asked Aug 03 '15 12:08

crazzy


People also ask

What are Exception levels?

The current level of privilege can only change when the processor takes or returns from an exception. Therefore, these privilege levels are referred to as Exception levels in the Arm architecture. Each Exception level is numbered, and the higher levels of privilege have higher numbers.


2 Answers

  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.
like image 143
Martin Keßler Avatar answered Nov 15 '22 11:11

Martin Keßler


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.

like image 33
Ciro Santilli Avatar answered Nov 15 '22 12:11

Ciro Santilli