Question

Can someone explain me, how exactly system mode works when we have nested interrupt ?

As per ARM site

ARMv4 and later architectures include a privileged mode called System mode, to overcome this problem. System mode shares the same registers as User mode, it can run tasks that require privileged access, and exceptions no longer overwrite the link register.

So how system mode make use of registers of User mode ?

And upto what hierarchy level nested interrupts can be handled?

Was it helpful?

Solution

Trying to handle nested interrupts in IRQ mode:

  • (USER) You are in user mode, your PC register tells where you are.

  • (USER) You get an interrupt.

  • (IRQ) Core switches to interrupt mode, disables interrupts (mask via cpsr.i) saves PC from user mode to LR in IRQ mode.

  • (IRQ) At this moment you can't get more interrupts because interrupts are disabled.

  • (IRQ) You are in IRQ mode and you do enable interrupts.

  • (IRQ) You call a function to handle related interrupt. After function call LR contains, return address into top level IRQ handler.

  • (IRQ) Another interrupt happens, LR gets overwritten with function handling interrupt. At this moment you can't have a stable state, simply because you can't use LR for your own purposes in IRQ mode and have interrupts enabled to support nested interrupts. You think you may save LR to stack, but that would be open to a race condition which would lead to inifinitive loops.

Handling nested interrupts via System mode:

  • (USER) You are in user mode, your PC register tells where you are.

  • (USER) You get an interrupt.

  • (IRQ) Core switches to interrupt mode, disables interrupts (mask via cpsr.i) saves PC from user mode to LR in IRQ mode.

  • (IRQ) At this moment you can't get more interrupts because interrupts are disabled.

  • (IRQ) You switch to system mode, enable IRQs.

  • (SYSTEM) Another interrupt happens but things work just because you don't race with hardware to keep your LR sane.

Look below to see which registers gets banked in which states.

enter image description here

OTHER TIPS

If you want to handle IRQ nestly, you have to deal with the very low level asm, which is one part of the heart of the OS.

Back to the code. I assume you have some idea of the ARM core registers. The most important thing in nesting IRQ is saving the states the ISR would return to. When IRQ happens, CPU will save the old CPSR to SPSR_irq and old PC to LR_irq and IRQ will be disabled. So, before jumping into the real ISR, you have to push {R0-R12}, LR_irq and SPSR_irq into the stack. Note, the IRQ is disabled right now and nothing would disturb you(unless the FIQ, but FIQ use other set of registers which does not interfere with IRQ registers). After that, you are safe to jump to the real ISR and enable IRQ.

When return from ISR, disable IRQ, and retrieve the SPSR from the stack, then do a LDM {R0-R12,PC}^ will get you back from where the interrupt happened.

P.S. If you only target AAPCS, you can only save {R0-R3, R12} in the entry, as the C function will not clobber {R4-R11}.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top