rpi-hal 0.2.0

Hardware abstraction layer for Raspberry Pi boards using the BCM2836/BCM2837 SoC (Pi 2, Pi 3)
Documentation
// AArch64 exception vector table + IRQ trampoline -- the counterpart to
// vectors.s. Installed via VBAR_EL1 (see boot64.s).
//
// Unlike the 8-entry AArch32 table, an AArch64 table has 16 entries in
// four groups of four (Synchronous, IRQ, FIQ, SError), each entry a
// 128-byte (0x80) aligned block, the whole table 2KB-aligned:
//
//   +0x000  Current EL with SP_EL0
//   +0x200  Current EL with SP_ELx   <- where this kernel runs (EL1h)
//   +0x400  Lower EL using AArch64
//   +0x600  Lower EL using AArch32
//
// This kernel runs at EL1h and never drops to EL0, so only the
// "Current EL with SP_ELx" IRQ slot needs a real handler; everything else
// parks in __unhandled_exception.
.section ".text.vectors"
.align 11
.global __vectors
__vectors:
    // Current EL with SP_EL0 (unused: this kernel runs at EL1h).
    .align 7
    b       __unhandled_exception       // Synchronous
    .align 7
    b       __unhandled_exception       // IRQ
    .align 7
    b       __unhandled_exception       // FIQ
    .align 7
    b       __unhandled_exception       // SError

    // Current EL with SP_ELx (EL1h -- this kernel).
    .align 7
    b       __unhandled_exception       // Synchronous
    .align 7
    b       __irq_trampoline            // IRQ
    .align 7
    b       __unhandled_exception       // FIQ
    .align 7
    b       __unhandled_exception       // SError

    // Lower EL using AArch64 (unused: no EL0 code).
    .align 7
    b       __unhandled_exception       // Synchronous
    .align 7
    b       __unhandled_exception       // IRQ
    .align 7
    b       __unhandled_exception       // FIQ
    .align 7
    b       __unhandled_exception       // SError

    // Lower EL using AArch32 (unused).
    .align 7
    b       __unhandled_exception       // Synchronous
    .align 7
    b       __unhandled_exception       // IRQ
    .align 7
    b       __unhandled_exception       // FIQ
    .align 7
    b       __unhandled_exception       // SError

.global __unhandled_exception
__unhandled_exception:
    wfe
    b       __unhandled_exception

.global __irq_trampoline
__irq_trampoline:
    // AArch64 takes no registers automatically on exception entry, so save
    // the caller-saved GP registers (x0-x18) and the link register (x30)
    // that __irq_handler may clobber. Callee-saved registers (x19-x29) are
    // preserved by __irq_handler itself per the C ABI, so they need no
    // saving here. ELR_EL1/SPSR_EL1 hold the return state and are left
    // untouched (IRQ stays masked throughout, so no nested exception can
    // overwrite them).
    stp     x0, x1, [sp, #-160]!
    stp     x2, x3, [sp, #16]
    stp     x4, x5, [sp, #32]
    stp     x6, x7, [sp, #48]
    stp     x8, x9, [sp, #64]
    stp     x10, x11, [sp, #80]
    stp     x12, x13, [sp, #96]
    stp     x14, x15, [sp, #112]
    stp     x16, x17, [sp, #128]
    stp     x18, x30, [sp, #144]

    bl      __irq_handler

    ldp     x2, x3, [sp, #16]
    ldp     x4, x5, [sp, #32]
    ldp     x6, x7, [sp, #48]
    ldp     x8, x9, [sp, #64]
    ldp     x10, x11, [sp, #80]
    ldp     x12, x13, [sp, #96]
    ldp     x14, x15, [sp, #112]
    ldp     x16, x17, [sp, #128]
    ldp     x18, x30, [sp, #144]
    ldp     x0, x1, [sp], #160

    // Restores PSTATE from SPSR_EL1 and branches to ELR_EL1 -- the
    // AArch64 way to return from an exception (vs. AArch32's `movs pc, lr`).
    eret

// Weak default so examples that never enable IRQ don't need to define
// this; a strong `__irq_handler` (e.g. an example's own `#[no_mangle]
// extern "C" fn`) overrides it at link time. Never reached unless
// something unmasks IRQ and enables a source without registering a handler.
.weak __irq_handler
__irq_handler:
    ret