diff options
author | ian <ian@FreeBSD.org> | 2014-03-09 15:36:56 +0000 |
---|---|---|
committer | ian <ian@FreeBSD.org> | 2014-03-09 15:36:56 +0000 |
commit | da7ada7de5386a2e2777c6674ed89b510819ea53 (patch) | |
tree | 6234954156533b6ae93af2cb9ebe3d842641d156 /sys/arm | |
parent | 6fede8098fb65e3b717542230daef531024ed074 (diff) | |
download | FreeBSD-src-da7ada7de5386a2e2777c6674ed89b510819ea53.zip FreeBSD-src-da7ada7de5386a2e2777c6674ed89b510819ea53.tar.gz |
Make undefined exception entry MPSAFE.
The old code used static storage to preserve a couple registers while
setting up the trapframe for the main handler. Doing so was the last
leftover crumbs from the days when a low-level debugger was hooked into
the exception entry code.
Now the exception entry sequence is essentially the same as for the
other exceptions, which still involves needlessly indirecting through
a function pointer which points to the same code on every platform.
Removing that indirection will be handled as a separate cleanup.
This work is based on an analysis by Juergen Weiss.
Diffstat (limited to 'sys/arm')
-rw-r--r-- | sys/arm/arm/exception.S | 49 | ||||
-rw-r--r-- | sys/arm/arm/undefined.c | 1 |
2 files changed, 14 insertions, 36 deletions
diff --git a/sys/arm/arm/exception.S b/sys/arm/arm/exception.S index 3d110e3..d7ef5f2 100644 --- a/sys/arm/arm/exception.S +++ b/sys/arm/arm/exception.S @@ -218,46 +218,25 @@ END(exception_exit) * look like direct entry from the vector. */ ASENTRY_NP(undefined_entry) - stmfd sp!, {r0, r1} - ldr r0, Lundefined_handler_indirection - ldr r1, [sp], #0x0004 - str r1, [r0, #0x0000] - ldr r1, [sp], #0x0004 - str r1, [r0, #0x0004] - ldmia r0, {r0, r1, pc} - -Lundefined_handler_indirection: - .word Lundefined_handler_indirection_data + sub lr, lr, #0x00000004 /* Adjust the lr */ + PUSHFRAMEINSVC /* Push trap frame and switch */ + /* to SVC32 mode */ + ldr r1, Lundefined_handler_address + adr lr, exception_exit + mov r0, sp /* pass the stack pointer as r0 */ + ldr pc, [r1] END(undefined_entry) -/* - * assembly bounce code for calling the kernel - * undefined instruction handler. This uses - * a standard trap frame and is called in SVC mode. - */ - -ENTRY_NP(undefinedinstruction_bounce) - PUSHFRAMEINSVC +ASENTRY_NP(undefinedinstruction_bounce) + b undefinedinstruction +END(undefinedinstruction_bounce) - mov r0, sp - adr lr, exception_exit - b _C_LABEL(undefinedinstruction) +Lundefined_handler_address: + .word _C_LABEL(undefined_handler_address) .data - .align 0 - -/* - * Indirection data - * 2 words use for preserving r0 and r1 - * 3rd word contains the undefined handler address. - */ - -Lundefined_handler_indirection_data: - .word 0 - .word 0 - .global _C_LABEL(undefined_handler_address) _C_LABEL(undefined_handler_address): - .word _C_LABEL(undefinedinstruction_bounce) -END(undefinedinstruction_bounce) + .word undefinedinstruction_bounce + diff --git a/sys/arm/arm/undefined.c b/sys/arm/arm/undefined.c index 7829ece..5b7b917 100644 --- a/sys/arm/arm/undefined.c +++ b/sys/arm/arm/undefined.c @@ -183,7 +183,6 @@ undefinedinstruction(struct trapframe *frame) if (!(frame->tf_spsr & I32_bit)) enable_interrupts(I32_bit|F32_bit); - frame->tf_pc -= INSN_SIZE; PCPU_INC(cnt.v_trap); fault_pc = frame->tf_pc; |