summaryrefslogtreecommitdiffstats
path: root/sys/arm
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-03-11 03:19:43 +0000
committerian <ian@FreeBSD.org>2014-03-11 03:19:43 +0000
commitf9d0a84c5cf585be9fe567b22ffe70f03ef22d73 (patch)
tree03c49f7284279dadf5f50b44894e3ada6bbd49a5 /sys/arm
parent588b3c0ed0bfc96b7bec31ceddf938f7a71b64f8 (diff)
downloadFreeBSD-src-f9d0a84c5cf585be9fe567b22ffe70f03ef22d73.zip
FreeBSD-src-f9d0a84c5cf585be9fe567b22ffe70f03ef22d73.tar.gz
Now that the PUSHFRAME and PULLFRAME macros are used only in the swi
entry/exit code, they don't need to be macros. Now they're just inline code, and rewritten to use shorter instruction sequences.
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/arm/exception.S120
1 files changed, 37 insertions, 83 deletions
diff --git a/sys/arm/arm/exception.S b/sys/arm/arm/exception.S
index ec2c33b..a4a9d09 100644
--- a/sys/arm/arm/exception.S
+++ b/sys/arm/arm/exception.S
@@ -57,75 +57,6 @@ __FBSDID("$FreeBSD$");
.align 0
/*
- * ASM macros for pushing and pulling trapframes from the stack
- *
- * These macros are used to handle the irqframe and trapframe structures
- * defined above.
- */
-
-/*
- * PUSHFRAME - macro to push a trap frame on the stack in the current mode
- * Since the current mode is used, the SVC lr field is not defined.
- *
- * NOTE: r13 and r14 are stored separately as a work around for the
- * SA110 rev 2 STM^ bug
- */
-#ifdef ARM_TP_ADDRESS
-#define PUSHFRAME \
- sub sp, sp, #4; /* Align the stack */ \
- str lr, [sp, #-4]!; /* Push the return address */ \
- sub sp, sp, #(4*17); /* Adjust the stack pointer */ \
- stmia sp, {r0-r12}; /* Push the user mode registers */ \
- add r0, sp, #(4*13); /* Adjust the stack pointer */ \
- stmia r0, {r13-r14}^; /* Push the user mode registers */ \
- mov r0, r0; /* NOP for previous instruction */ \
- mrs r0, spsr; /* Put the SPSR on the stack */ \
- str r0, [sp, #-4]!; \
- ldr r0, =ARM_RAS_START; \
- mov r1, #0; \
- str r1, [r0]; \
- mov r1, #0xffffffff; \
- str r1, [r0, #4];
-#else
-#define PUSHFRAME \
- sub sp, sp, #4; /* Align the stack */ \
- str lr, [sp, #-4]!; /* Push the return address */ \
- sub sp, sp, #(4*17); /* Adjust the stack pointer */ \
- stmia sp, {r0-r12}; /* Push the user mode registers */ \
- add r0, sp, #(4*13); /* Adjust the stack pointer */ \
- stmia r0, {r13-r14}^; /* Push the user mode registers */ \
- mov r0, r0; /* NOP for previous instruction */ \
- mrs r0, spsr; /* Put the SPSR on the stack */ \
- str r0, [sp, #-4]!;
-#endif
-
-/*
- * PULLFRAME - macro to pull a trap frame from the stack in the current mode
- * Since the current mode is used, the SVC lr field is ignored.
- */
-
-#ifdef ARM_TP_ADDRESS
-#define PULLFRAME \
- ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \
- msr spsr_fsxc, r0; \
- ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \
- mov r0, r0; /* NOP for previous instruction */ \
- add sp, sp, #(4*17); /* Adjust the stack pointer */ \
- ldr lr, [sp], #0x0004; /* Pull the return address */ \
- add sp, sp, #4 /* Align the stack */
-#else
-#define PULLFRAME \
- ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \
- msr spsr_fsxc, r0; \
- clrex; \
- ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \
- mov r0, r0; /* NOP for previous instruction */ \
- add sp, sp, #(4*17); /* Adjust the stack pointer */ \
- ldr lr, [sp], #0x0004; /* Pull the return address */ \
- add sp, sp, #4 /* Align the stack */
-#endif
-
-/*
* PUSHFRAMEINSVC - macro to push a trap frame on the stack in SVC32 mode
* This should only be used if the processor is not currently in SVC32
* mode. The processor mode is switched to SVC mode and the trap frame is
@@ -263,8 +194,15 @@ __FBSDID("$FreeBSD$");
b 1b ;\
2:
-
-
+/*
+ * If ARM_TP_ADDRESS is defined we're on armv4 or v5 and there is no clrex
+ * instruction, or need for one, so just #define it away.
+ */
+#ifdef ARM_TP_ADDRESS
+#define CLREX
+#else
+#define CLREX clrex
+#endif
/*
* reset_entry:
@@ -281,17 +219,27 @@ Lreset_panicmsg:
END(reset_entry)
/*
- * swi_entry
- *
- * Handler for the Software Interrupt exception.
+ * Entry point for Software Interrupt (SWI).
+ *
+ * The swi instruction switches to svc32 mode, so we're already on the
+ * right stack. We build a trapframe and invoke swi_handler().
*/
ASENTRY_NP(swi_entry)
- STOP_UNWINDING /* Don't unwind into user mode. */
-
- PUSHFRAME
-
- mov r0, sp /* Pass the frame to any function */
- bl _C_LABEL(swi_handler) /* It's a SWI ! */
+ sub sp, sp, #4 /* Align the stack (tf_pad). */
+ str lr, [sp, #-4]! /* Push the return address (tf_pc). */
+ sub sp, sp, #(4*17) /* Point sp to tf_r0, store the user */
+ stmia sp, {r0-r14}^ /* registers. Store SPSR in tf_spsr. */
+ mrs r0, spsr /* Now sp points to struct trapframe */
+ str r0, [sp, #-4]! /* we've constructed on svc32 stack. */
+#ifdef ARM_RAS_START
+ ldr r0, =ARM_RAS_START /* If we're using RAS-based atomicity */
+ mov r1, #0 /* we should never have a SWI in the */
+ str r1, [r0] /* midst of a RAS sequence, but */
+ mov r1, #0xffffffff /* be safe and reset the RAS vars. */
+ str r1, [r0, #4]
+#endif
+ mov r0, sp /* Pass the trapframe we just built */
+ bl _C_LABEL(swi_handler) /* on the stack to the swi handler. */
/*
* The fork_trampoline() code in swtch.S aranges for the MI fork_exit()
@@ -301,11 +249,17 @@ ASENTRY_NP(swi_entry)
*/
ASENTRY_NP(swi_exit)
- DO_AST /* Deliver signals. */
+ DO_AST /* Do scheduling and signal delivery. */
- PULLFRAME
- movs pc, lr /* Exit */
+ CLREX /* Should never happen but be safe */
+ ldr r0, [sp], #4 /* and don't exit with open monitor. */
+ msr spsr_fsxc, r0 /* Restore SPSR. */
+ ldmia sp, {r0-r14}^ /* Restore user mode registers. */
+ ldr lr, [sp, #8] /* Restore the return address. */
+ add sp, sp, #12 /* Deallocate the rest of trapframe. */
+ movs pc, lr /* Return to user mode. */
+ STOP_UNWINDING /* Don't unwind into user mode. */
END(swi_exit)
END(swi_entry)
OpenPOWER on IntegriCloud