Make sure stack is 8 byte aligned in shared IRQ handlers (#971)

This commit is contained in:
Graham Sanderson 2022-08-17 10:25:23 -05:00 committed by GitHub
parent 80cde7276d
commit 00780f0de9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 9 additions and 7 deletions

View File

@ -213,7 +213,7 @@ void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_prior
struct irq_handler_chain_slot slot_data = { struct irq_handler_chain_slot slot_data = {
.inst1 = 0xa100, // add r1, pc, #0 .inst1 = 0xa100, // add r1, pc, #0
.inst2 = make_branch(&slot->inst2, irq_handler_chain_first_slot), // b irq_handler_chain_first_slot .inst2 = make_branch(&slot->inst2, irq_handler_chain_first_slot), // b irq_handler_chain_first_slot
.inst3 = 0xbd00, // pop {pc} .inst3 = 0xbd01, // pop {r0, pc}
.link = -1, .link = -1,
.priority = order_priority, .priority = order_priority,
.handler = handler .handler = handler
@ -237,7 +237,7 @@ void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_prior
.inst2 = 0x4780, // blx r0 .inst2 = 0x4780, // blx r0
.inst3 = prev_slot->link >= 0 ? .inst3 = prev_slot->link >= 0 ?
make_branch(&slot->inst3, resolve_branch(&prev_slot->inst3)) : // b next_slot make_branch(&slot->inst3, resolve_branch(&prev_slot->inst3)) : // b next_slot
0xbd00, // pop {pc} 0xbd01, // pop {r0, pc}
.link = prev_slot->link, .link = prev_slot->link,
.priority = order_priority, .priority = order_priority,
.handler = handler .handler = handler
@ -319,7 +319,7 @@ void irq_remove_handler(uint num, irq_handler_t handler) {
to_free_slot->link = next_slot->link; to_free_slot->link = next_slot->link;
to_free_slot->inst3 = next_slot->link >= 0 ? to_free_slot->inst3 = next_slot->link >= 0 ?
make_branch(&to_free_slot->inst3, resolve_branch(&next_slot->inst3)) : // b mext_>slot->next_slot make_branch(&to_free_slot->inst3, resolve_branch(&next_slot->inst3)) : // b mext_>slot->next_slot
0xbd00; // pop {pc} 0xbd01; // pop {r0, pc}
// add old next slot back to free list // add old next slot back to free list
next_slot->link = irq_hander_chain_free_slot_head; next_slot->link = irq_hander_chain_free_slot_head;
@ -331,7 +331,7 @@ void irq_remove_handler(uint num, irq_handler_t handler) {
if (prev_slot) { if (prev_slot) {
// chain is not empty // chain is not empty
prev_slot->link = -1; prev_slot->link = -1;
prev_slot->inst3 = 0xbd00; // pop {pc} prev_slot->inst3 = 0xbd01; // pop {r0, pc}
} else { } else {
// chain is not empty // chain is not empty
vtable_handler = __unhandled_user_irq; vtable_handler = __unhandled_user_irq;
@ -400,7 +400,7 @@ void irq_add_tail_to_free_list(struct irq_handler_chain_slot *slot) {
for(uint i=0;i<count_of(irq_handler_chain_slots);i++) { for(uint i=0;i<count_of(irq_handler_chain_slots);i++) {
if (irq_handler_chain_slots[i].link == slot_index) { if (irq_handler_chain_slots[i].link == slot_index) {
irq_handler_chain_slots[i].link = -1; irq_handler_chain_slots[i].link = -1;
irq_handler_chain_slots[i].inst3 = 0xbd00; // pop {pc} irq_handler_chain_slots[i].inst3 = 0xbd01; // pop {r0, pc}
found = true; found = true;
break; break;
} }

View File

@ -54,7 +54,9 @@ irq_handler_chain_slots:
.endr .endr
irq_handler_chain_first_slot: irq_handler_chain_first_slot:
push {lr} // Save EXC_RETURN token, so `pop {pc}` will return from interrupt push {r0, lr} // Save EXC_RETURN token, so `pop {r0, pc}` will return from interrupt
// Note that r0 does not NEED to be saved, however we must maintain
// an 8 byte stack alignment, and this is the cheapest way to do so
ldr r0, [r1, #4] // Get `handler` field of irq_handler_chain_slot ldr r0, [r1, #4] // Get `handler` field of irq_handler_chain_slot
adds r1, #1 // r1 points to `inst3` field of slot struct. Set Thumb bit on r1, adds r1, #1 // r1 points to `inst3` field of slot struct. Set Thumb bit on r1,
mov lr, r1 // and copy to lr, so `inst3` is executed on return from handler mov lr, r1 // and copy to lr, so `inst3` is executed on return from handler
@ -65,7 +67,7 @@ irq_handler_chain_remove_tail:
subs r0, #9 // so lr points to offset +8. Note also lr has its Thumb bit set! subs r0, #9 // so lr points to offset +8. Note also lr has its Thumb bit set!
ldr r1, =irq_add_tail_to_free_list ldr r1, =irq_add_tail_to_free_list
blx r1 blx r1
pop {pc} // Top of stack is EXC_RETURN pop {r0, pc} // Top of stack is EXC_RETURN
#endif #endif