Skip to content

LR might be smashed in pre-ARMv7 ASM interrupt handler. #142

@robamu

Description

@robamu

The current ASM interrupt handler for pre ARMv7 architectures looks like this:

    _asm_default_irq_handler:
        sub     lr, lr, 4                 // make sure we jump back to the right place
        push    {{ lr }}                  // save adjusted LR to IRQ stack
        mrs     lr, spsr                  // The hardware has copied the interrupted task's CPSR to SPSR_irq - grab it and
        push    {{ lr }}                  //   save it to IRQ stack using LR
        msr     cpsr_c, {sys_mode}        // switch to system mode so we can handle another interrupt (because if we interrupt irq mode we trash our own shadow registers)
        mov     lr, sp                    // align SP down to eight byte boundary using LR
        and     lr, lr, 7                 //
        sub     sp, lr                    // SP now aligned - only push 64-bit values from here
        push    {{ r0-r3, r12, lr }}      // push alignment amount (in LR) and preserved registers
     "#,
    crate::save_fpu_context!(),
    r#"
        bl      _irq_handler              // call C handler (they may choose to re-enable interrupts)
    "#,
    crate::restore_fpu_context!(),
    r#"
        pop     {{ r0-r3, r12, lr }}      // restore alignment amount (in LR) and preserved registers
        add     sp, lr                    // restore SP alignment using LR
        msr     cpsr_c, {irq_mode}        // switch back to IRQ mode (with IRQ masked)
        pop     {{ lr }}                  // load and restore SPSR using LR
        msr     spsr, lr                  //
        ldmfd   sp!, {{ pc }}^            // return from exception (^ => restore SPSR to CPSR)
    .size _asm_default_irq_handler, . - _asm_default_irq_handler
    "#,

Is this not smashing the banked LR of system mode? The ARMv7M + interrupt handler actually stores the LR by pushing it before using it for stack alignment. I tried to do the same for the interrupt handler above and the tests are still passing. I am just wondering why the tests are working in the first place. Was the LR not saved deliberately and I am just missing something?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions