Home | Projects | Notes > Computer Architecture & Organization > Privileged Mode and Exceptions
Interrupts and exceptions work about the same way as follows:
Interrupts or exception is raised.
During the instruction Fetch the interrupt or exception is checked and processing is started.
Once the Execution starts, it cannot be interrupted. (atomic operation)
Once the interrupt or exception process is complete, execution resumes right where it left off.
Here's what happens during the Fetch without interrupt:
xxxxxxxxxx
1111. [MAR] ← [PC] PC out to Memory Address Register to get ready to
2 fetch the next instruction to be executed.
3
42. [PC] ← [PC] + 4 While fetching the instruction, increment PC by 4
5 so PC points to the next instruction.
6
73. [MBR] ← [[MAR]] Read the instruction from memory and store results
8 into MBR.
9
104. [IR] ← [MBR] Transfer the instruction to the instruction
11 register and start decode process.
Now, here's how the code will look like during the Fetch when interrupt is considered:
xxxxxxxxxx
321----------------------------------------------------------------------------------------
2IF INT = 1 THEN [[SP]] ← [PC] If INT is asserted save the PC out to stack.
3 -------------
4 [MAR] ← [SP] 이 주소에다가
5 [MBR] ← [PC] PC를
6 write write!
7ELSE [MAR] ← [PC] ELSE Get ready to fetch the next instruction.
8----------------------------------------------------------------------------------------
9IF INT = 1 THEN [SP] ← [SP] + 4 If INT is asserted, update the SP to the next
10 free location.
11
12ELSE [PC] ← [PC] + 4 ELSE Point to the next instruction.
13----------------------------------------------------------------------------------------
14IF INT = 1 [PC] ← [INT Handler Starting Address]
15 If INT is asserted, have the PC jump to the
16 address of the interrupt handler.
17
18ELSE [MBR] ← [[MAR]] ELSE Read the instruction from memory and store
19 results into MBR.
20----------------------------------------------------------------------------------------
21IF INT = 1 THEN STATE ← FETCH If INT is asserted, start the fetch process
22 again.
23
24ELSE [IR] ← [MBR] ELSE Transfer the instruction to the instruction
25 (Continue with Instruction register and start decode process.
26 Decode and Execute)
27----------------------------------------------------------------------------------------
28
29[!] Note: Interrupt (INT) is essentially a piece of wire coming into the CPU.
30[!] Note: Once the INT is asserted it must stay on during the entire fetch cycle. That
31is the way a latch is used to capture and hold the interrupt signal. (Otherwise, INT
32line will fluctuate between `0` and `1` depending on the occurring interrupts.)
Interrupts can happen any time, but not checked until Fetch.
Followings are guaranteed so that interrupts are handled without any problems.
xxxxxxxxxx
171INT Handler Starting Address: (entering the 'critical section')
2
3@ Disable all interrupts
4@ Push all resigers (including CPSR a.k.a. CCR) onto the stack
5@ Enable interrupts (optional depending on the interrupt priority)
6@ - This is possible because the previous context have all been saved!
7@ - But unless you need to take care of multiple interrupts, you can disable all
8@ interrupts until the current one is completely handled.
9@ Start all the interrupt processing
10@
11@
12@ End of the interrupt processing
13@ Disable all interrupts
14@ - Because we don't want the register restoring process to be interrupted by other
15@ interrupts.
16@ Pop all registers off the stack
17@ Return back to the program where the interrupt has happened
[31-28] Condition Codes
xxxxxxxxxx
41N : Negative or less than flag
2Z : Zero flag
3C : Carry or borrow or extended flag
4V : Overflow flag
[27- 9] Reserved
[ 8- 0] System Control Bits
xxxxxxxxxx
291IF : Enables or disables IRQ or FIQ interrupts
2T : Thumb mode
3Mode :
4 M[4:0] Mode ARM - Visible State Registers
5 ------ -------------------------- --------------------------------------------
6 b10000 User r0-r14, PC, CPSR
7 (Normal user mode)
8 ------ -------------------------- --------------------------------------------
9 b10001 FIQ r0-r7, r8_fiq-r14_fiq, PC CPSR, SPSR_fiq
10 (Fast Interrupt Request)
11 ------ -------------------------- --------------------------------------------
12 b10010 IRQ r0-r12, r13_irq, r14_irq, PC CPSR, SPSR_irq
13 (Interrupt Request)
14 ------ -------------------------- --------------------------------------------
15 b10011 Supervisor r0-r12, r13_svc, r14_svc, PC CPSR, SPSR_svc
16 (Software Interrupt
17 processing (SVC))
18 ------ -------------------------- --------------------------------------------
19 b10111 Abort r0-r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt
20 (Processing memory
21 faults)
22 ------ -------------------------- --------------------------------------------
23 b11011 Undefined r0-r12, r13_und, r14_und, PC, CPSR, SPSR_und
24 (Undefined instruction
25 processing)
26 ------ -------------------------- --------------------------------------------
27 b11111 System r0-r14, PC, CPSR
28 (Operating System)
29 ------ -------------------------- --------------------------------------------
[!] Note: So far, we have discussed only these 17 (including CPSR
) registers that are visible to us in the user mode. In reality, however, ARM has total 32 registers (excluding CPSR
) and the rest become visible as you switch to the different modes.
(16 user mode registers) + (2 + 2 + 2 + 2 + 8 banked registers) = 32 registers
[!] Note: ARM designers decided to maintain another set of registers to make context switching more efficient by reducing the push/pop of all the registers to/from the stack.
Instead of having to push and pop all 16 registers every time there is an interrupt or mode change.
e.g., In SVC mode, it's got its own playground (r13_SVC
, r14_SVC
) to handle its interrupt without messing other registers.
This helps interrupts handled much faster since there's no need to push things onto the stack which is located in the main memory. (Access to main memory is orders of magnitude SLOWER.)
In the OS there are unique registers that are only available in that specific mode.
The operating mode is changed to the mode corresponding to the exception.
e.g., An interrupt request would select IRQ
mode.
The address of the instruction following the point at which the exception occurred is copied into register r14 (lr)
.
In other words, the exception is treated as a type of subroutine call and the return address is preserved in the link register.
The current value of the CPSR
is saved in the SPSR
of the new mode.
e.g., If the exception is an interrupt request, CPSR
gets saved in SPSR_irq
.
It is necessary to save the current processor status because an exception must not be allowed to modify the processor status.
Interrupt requests are disabled by setting bit 7
of the CPSR
.
If the current exception is a fast interrupt request, further FIQ
exceptions are disabled by setting bit 6 of the CPSR
.
Each location in the exception table contains an instruction that is executed first in the exception handling routine.
This instruction is normally a branch operation (for example B myHandler
)
This would load the program counter with the address of the corresponding current exception handler.
Following table defines the memory locations accessed by the ARM processor's exceptions.
Each memory location contains the first instruction of the appropriate exception handlers; this implies that this table should be in read-only memory.
xxxxxxxxxx
91Exception Mode Vector Address
2================================================ ========== ==============
3Reset SVC 0x00000000
4Undefined instruction UND 0x00000004
5Software interrupt (SWI) SVC 0x00000008
6Prefetch abort (instruction fetch memory fault) Abort 0x0000000C
7Data abort (data access memory fault) Abort 0x00000010
8IRQ (normal interrupt) IRQ 0x00000018
9FIQ (fast interrupt) FIQ 0x0000001C
After the exception has been dealt with by a suitable handler, it is necessary to return to the point at which the exception was called (if the exception was fatal, a return is no longer possible.
In order to return from an exception, the information that defines the pre-exception mode must be restored;
PC
PC
, so it has got to be restored
CPSR
There are 2 CPSR
s in ARM. When entering the ISR, CPSR
gets copied into the auxiliary CPSR
, and when returning back to the user mode, CPSR
gets overwritten by the contents of the auxiliary CPSR
.
This takes two instructions to do! (see the following issue)
Returning from an exception is not as trivial a matter as it might seem. If you restore the PC
first, you are still in the exception-handling mode since the CPSR
hasn't been restored back to the user mode yet. On the other hand, if you restore the CPSR
first, you are no longer within the exception-handling routine and there is no way in which you can restore the PC
and stuff.
You can't use a normal sequence of operations to return from an exception because it involves a change of operating mode.
So, the ARM peope tweaked an existing instruction a little bit to create a special instruction that can restore both PC
and CPSR
at the same time:
2 exception return mechanisms are provided to solve this issue in one instruction.
Mechanism 1 r14
.
Mechanism 2
Moreover, the return mechanism depends on the type of exception being handled.
If you are returning from an exception where the return address is in the link register
, you can execute instructions described in the following table:
xxxxxxxxxx
131ARM Return from Exception Operations
2
3Exception type Instruction to return to user mode
4============================================ ==========================================
5SWI, undefined instruction MOVS pc, r14
6 - --
7 as long as the PC is listed first it
8 knows
9 1) PC has to be restored AND
10 2) CPSR mode has to be restored back
11 to user mode
12IRQ, FIQ SUBS pc, r14, #4
13Data abort to repeat the faulted instruction SUBS pc, r14, #8
MOVS
and SUBS
are special versions of the normal instructions used when the destination register is the PC
. You have to modify the value of the PC
when returning from an IRQ
, FIQ
, or a data abort
.
In the case of IRQ
, the PC
has to be wound back by
This is because of the pipelining. By the time the interrupt was checked and the PC
was saved onto the stack, the PC
has already been updated once. (more to come later)
In the case of FIQ
, the PC
has to be wound back by
Again because of the pipelining. PC
already updated to the next next instruction was saved onto the stack.
If the exception handler has copied the return address onto the stack, you have to use a different mechanism.
Under normal circumstances, you would return from a subroutine with a stacked PC
by means of an instruction such as
xxxxxxxxxx
21LDMFD r13!, {r0-r4, PC} @ or POP {r0-r4, PC}
2 @ r0-r4 is the list of registers to be restored.
If you wish to pop the saved registers and restore the CPSR
at the same time, you have to use the special version of this instruction:
xxxxxxxxxx
41LDMFD r13!, {r0-r4, PC}^ @ restore r0 through r4
2 @ return and restore CPSR
3@ or
4POP {r0-r4, PC}^ @ this needs to be verified on the Raspberry Pi
The ^
symbol after the register list indicates that the CPSR
is to be restored at the same time the PC
is restored.
The program counter was not modified at the point at which it was restored. You have to modify the
PC
before you stack it!