Appendix A: ARM64 additions for Project 2
This appendix covers what is new relative to Project 1’s ARM64 reference, which you should still keep at hand.
Instructions
| Instruction | Meaning |
|---|---|
stp x0, x1, [sp, #16] | Store pair: store two registers at sp+16 and sp+24. Halves the instruction count when saving a context. |
ldp x0, x1, [x2, #16] | Load pair: the inverse, loads a pair of registers. |
eret | Exception return. Sets pc from ELR_ELn and PSTATE from SPSR_ELn (for the current exception level n) in one step. Used both to drop an exception level and to resume a saved context. |
msr DAIFSET, #2 | Mask (disable) interrupts. The immediate is a 4-bit selector over the PSTATE mask bits: 8 = Debug, 4 = SError, 2 = IRQ, 1 = FIQ. So #2 touches only the IRQ mask. |
msr DAIFCLR, #2 | Unmask (enable) interrupts; same selector encoding. |
wfi / wfe | Wait for interrupt / event: put the core in a low-power state until something happens. A good way to park a CPU core that has nothing to do. |
svc #0 | Supervisor call: deliberately raise a synchronous exception. This is how system calls will work in Project 4; here it is useful for testing your exception vector table. |
.balign N | (An assembler directive, not an instruction.) Advance to the next address that is a multiple of N, padding as needed. Essential for laying out an exception vector table. |
System registers
Remember that all of these are read with mrs and written with msr, never mov, and that most of them exist separately at each exception level.
| Register | Meaning |
|---|---|
CurrentEL | Bits 3:2 hold the current exception level. |
ELR_EL1 | Exception Link Register: the address to resume at. Set by the hardware on an exception; set by you when faking one. |
SPSR_EL1 | Saved Program Status Register: the PSTATE to resume with. Its low four bits select the exception level and stack pointer to return to (0b0101 = EL1h, 0b0000 = EL0t). |
ESR_EL1 | Exception Syndrome Register: why the (synchronous) exception happened. Bits 31:26 are the exception class; the rest is class-specific detail. |
FAR_EL1 | Fault Address Register: the address that caused a memory fault. |
VBAR_EL1 | Vector Base Address Register: the address of the exception vector table. 2 KiB-aligned. You must set this. |
SCTLR_EL1 | System Control Register: MMU, caches, endianness, alignment checking. |
HCR_EL2 | Hypervisor Configuration Register. Bit 31 (RW) selects AArch64 (1) or AArch32 (0) for lower exception levels. |
DAIF | The four PSTATE interrupt-mask bits: Debug, SError (Abort), IRQ, FIQ. Read or write all four at once with mrs/msr DAIF (which is what you want in order to save and restore an interrupt state); set or clear individual ones with msr DAIFSET/DAIFCLR and the 4-bit selector above. Note that the bit positions in the DAIF register view, in the DAIFSET/DAIFCLR selector, and in SPSR_EL1 are all different: use the named constants in kernel/aarch64.h rather than writing numbers. |
CNTFRQ_EL0 | Generic timer tick rate, in Hz (lower 32 bits). |
CNTPCT_EL0 | Generic timer current count (64-bit, monotonic). |
CNTP_CTL_EL0 | Generic timer control: bit 0 ENABLE, bit 1 IMASK, bit 2 ISTATUS (read-only). |
CNTP_TVAL_EL0 | Generic timer down-counter: write N to fire N ticks from now. |
MPIDR_EL1 | Multiprocessor Affinity Register: which core am I. (From Project 1.) |
Reaching system registers from C
You cannot write msr in C, so you use GCC’s inline assembly:
// read a system register
uint64 freq;
__asm__ volatile("mrs %0, CNTFRQ_EL0" : "=r"(freq));
// write a system register
__asm__ volatile("msr CNTP_TVAL_EL0, %0" : : "r"(ticks));
// an instruction with no operands
__asm__ volatile("msr DAIFSET, #2" : : : "memory");%0 refers to the first operand; "=r" means “an output in a general register”, "r" means “an input in a general register”. The "memory" clobber tells the compiler not to move memory accesses across the instruction, which matters whenever you are changing something (like the interrupt mask) that affects when other code can run. volatile stops the compiler from deleting the statement because it appears to have no effect.