summaryrefslogtreecommitdiffstats
path: root/sys/arm
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-03-09 15:36:56 +0000
committerian <ian@FreeBSD.org>2014-03-09 15:36:56 +0000
commitda7ada7de5386a2e2777c6674ed89b510819ea53 (patch)
tree6234954156533b6ae93af2cb9ebe3d842641d156 /sys/arm
parent6fede8098fb65e3b717542230daef531024ed074 (diff)
downloadFreeBSD-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.S49
-rw-r--r--sys/arm/arm/undefined.c1
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;
OpenPOWER on IntegriCloud