|
@@ -174,9 +174,11 @@ FUNCTION ArpUndefinedInstructionEntry
|
|
|
mov %sp, %r4
|
|
|
|
|
|
//
|
|
|
- // Restore state and return.
|
|
|
+ // Restore state and return. The label below is used by the software
|
|
|
+ // interrupt code, not this function, to reuse a bit of code.
|
|
|
//
|
|
|
|
|
|
+ArpFullRestore:
|
|
|
ARM_EXIT_INTERRUPT
|
|
|
|
|
|
END_FUNCTION ArpUndefinedInstructionEntry
|
|
@@ -193,7 +195,8 @@ END_FUNCTION ArpUndefinedInstructionEntry
|
|
|
Routine Description:
|
|
|
|
|
|
This routine directly handles an exception generated by a software
|
|
|
- interrupt (a system call).
|
|
|
+ interrupt (a system call). Upon entry, R0 holds the system call number,
|
|
|
+ and R1 holds the system call parameter.
|
|
|
|
|
|
Arguments:
|
|
|
|
|
@@ -209,8 +212,6 @@ Return Value:
|
|
|
|
|
|
FUNCTION ArpSoftwareInterruptEntry
|
|
|
srsdb %sp!, #ARM_MODE_SVC @ Push lr and spsr.
|
|
|
- tst %r2, %r2 @ See if "full" is zero.
|
|
|
- bne ArpSoftwareInterruptEntrySlow @ Go to slow path if non-zero.
|
|
|
sub %sp, #(TRAP_FRAME_SIZE - 8) @ Make space for rest of frame.
|
|
|
mov %r2, %sp @ Get stack/trap frame param.
|
|
|
cps #ARM_MODE_SYSTEM @ Switch to system mode.
|
|
@@ -219,14 +220,15 @@ FUNCTION ArpSoftwareInterruptEntry
|
|
|
cpsie i, #ARM_MODE_SVC @ Enable interrupts, svc mode.
|
|
|
|
|
|
//
|
|
|
- // Save R0 and R1. These are needed by the signal dispatcher and if the
|
|
|
- // system call gets restarted.
|
|
|
+ // Save R0 and R1. These are needed if the system call gets restarted.
|
|
|
+ // Save R0 into R2 since R0 is used for the return value.
|
|
|
//
|
|
|
|
|
|
- stmdb %sp!, {%r0, %r1} @ Save the parameters.
|
|
|
+ str %r0, [%r2, #TRAP_R2]
|
|
|
+ str %r1, [%r2, #TRAP_R1]
|
|
|
|
|
|
- CFI_OFFSET(r0, 0)
|
|
|
- CFI_OFFSET(r1, 4)
|
|
|
+ CFI_OFFSET(r1, TRAP_R1)
|
|
|
+ CFI_OFFSET(r0, TRAP_R2)
|
|
|
CFI_OFFSET(sp, TRAP_USERSP + 8)
|
|
|
CFI_OFFSET(lr, TRAP_USERLR + 8)
|
|
|
CFI_OFFSET(pc, TRAP_PC + 8)
|
|
@@ -241,10 +243,9 @@ FUNCTION ArpSoftwareInterruptEntry
|
|
|
|
|
|
//
|
|
|
// The system call routine takes three parameters: the system call number,
|
|
|
- // system call parameter, and a pointer to the trap frame. User-mode
|
|
|
- // already set up the first two parameters in R0 and R1, and they were
|
|
|
- // preserved throughout the context save process. R2 already holds the trap
|
|
|
- // frame from above.
|
|
|
+ // system call parameter, and a pointer to the trap frame. The number was
|
|
|
+ // moved from R2 into R0 early in the function, the parameter is in R1 from
|
|
|
+ // user mode, and R2 == SP == trap frame.
|
|
|
//
|
|
|
|
|
|
bl KeSystemCallHandler @ Handle system call.
|
|
@@ -262,24 +263,36 @@ FUNCTION ArpSoftwareInterruptEntry
|
|
|
eor %r12, %r12 @ Scrub volatile R12.
|
|
|
ldr %r1, [%r1, #THREAD_SIGNAL_PENDING] @ Load signal pending status.
|
|
|
cmp %r1, #ThreadSignalPending @ Compare to signal pending.
|
|
|
- beq ArpSoftwareInterruptFastSignal @ Jump to dispatch signal.
|
|
|
+ beq ArpSoftwareInterruptSignalCheck @ Jump to dispatch signal.
|
|
|
+
|
|
|
+ArpSoftwareInterruptRestore:
|
|
|
+
|
|
|
+ //
|
|
|
+ // See if the trap frame was upgraded to a complete one. If so, go do the
|
|
|
+ // slow restore. Add 1 to the exception CPSR to see if it was -1 (the
|
|
|
+ // magic value indicating an incomplete trap frame).
|
|
|
+ //
|
|
|
+
|
|
|
+ ldr %r1, [%sp, #TRAP_EXCEPTION_CPSR] @ Get hint about frame complete.
|
|
|
+ adds %r1, %r1, #1 @ Add 1 and set flags.
|
|
|
+ bne ArpFullRestore @ Do a full restore if needed.
|
|
|
|
|
|
//
|
|
|
// Restore the user mode stack and link registers. Do not restore or
|
|
|
// clobber R0 as it holds the system call's return value.
|
|
|
//
|
|
|
|
|
|
- add %r1, %sp, #8 @ Get trap frame pointer.
|
|
|
+ mov %r1, %sp @ Get trap frame pointer.
|
|
|
cpsid i, #ARM_MODE_SYSTEM @ Switch to system mode.
|
|
|
ldr %sp, [%r1, #TRAP_USERSP] @ Restore usermode SP.
|
|
|
ldr %lr, [%r1, #TRAP_USERLR] @ Restore usermode LR.
|
|
|
cpsid i, #ARM_MODE_SVC @ Switch back to svc mode.
|
|
|
|
|
|
//
|
|
|
- // Pop off the saved R0 and R1 and most of the trap frame.
|
|
|
+ // Pop off most of the trap frame.
|
|
|
//
|
|
|
|
|
|
- add %sp, #TRAP_FRAME_SIZE @ Pop up to PC/Cpsr.
|
|
|
+ add %sp, #(TRAP_FRAME_SIZE - 8) @ Pop up to PC/Cpsr.
|
|
|
CFI_UNDEFINED(r0)
|
|
|
CFI_UNDEFINED(r1)
|
|
|
CFI_UNDEFINED(sp)
|
|
@@ -293,162 +306,40 @@ FUNCTION ArpSoftwareInterruptEntry
|
|
|
eor %r1, %r1
|
|
|
rfeia %sp! @ Restore PC and CPSR. Bye!
|
|
|
|
|
|
- //
|
|
|
- // Save the full trap frame. The CPSR, PC, user SP, user LR and exception
|
|
|
- // CPSR are the only values saved in the trap frame. The exception CPSR is
|
|
|
- // a dummy value, but keep it so that the signal dispatcher knows this trap
|
|
|
- // frame came from the fast path. R0 currently holds the system call's
|
|
|
- // return value. Do not scrub it. Just save it in the trap frame.
|
|
|
- //
|
|
|
-
|
|
|
-ArpSoftwareInterruptFastSignal:
|
|
|
- CFI_UNDEFINED(lr)
|
|
|
- eor %lr, %lr @ Zero SVC link register.
|
|
|
- eor %r1, %r1 @ Scrub volatile R1.
|
|
|
- str %r0, [%sp, #(TRAP_R0 + 8)] @ Save the return value in R0.
|
|
|
- mrs %r0, cpsr @ Get the "exception" CPSR.
|
|
|
- str %r0, [%sp, #(TRAP_EXCEPTION_CPSR + 8)] @ Save "exception" CPSR.
|
|
|
- add %r0, %sp, #(TRAP_PC + 8) @ Get location after SVC LR.
|
|
|
- stmdb %r0!, {%r1-%r12, %lr} @ Push registers and CPSR.
|
|
|
- str %sp, [%sp, #8] @ Save SP.
|
|
|
+ArpSoftwareInterruptSignalCheck:
|
|
|
|
|
|
//
|
|
|
- // Jump down to the slow signal path which starts an IT block. The compare
|
|
|
- // that dropped the fast path to dispatch a signal should have set the zero
|
|
|
- // flag and none of the instructions above should have changed the flags,
|
|
|
- // making the IT block safe to jump to.
|
|
|
+ // See if the trap frame is already complete as a result of the system
|
|
|
+ // call operation (like restore from signal).
|
|
|
//
|
|
|
|
|
|
- b ArpSoftwareInterruptSlowSignal
|
|
|
+ ldr %r1, [%sp, #TRAP_EXCEPTION_CPSR] @ Get hint about frame complete.
|
|
|
+ adds %r1, %r1, #1 @ Add 1 and set flags.
|
|
|
+ bne ArpSoftwareInterruptSignalDispatch @ Skip the save if zero now.
|
|
|
|
|
|
//
|
|
|
- // Perform the slow version of the system call that builds up a complete
|
|
|
- // trap frame. This is used for system calls like fork and exec, where the
|
|
|
- // trap frame is used in the system call.
|
|
|
+ // Save the full trap frame. The CPSR, PC, user SP, user LR, exception CPSR,
|
|
|
+ // R1, and R2 are the only values saved in the trap frame. R0 currently
|
|
|
+ // holds the system call's return value. Save it in the trap frame.
|
|
|
//
|
|
|
|
|
|
-ArpSoftwareInterruptEntrySlow:
|
|
|
- mov %lr, #0 @ Zero SVC link register.
|
|
|
- stmdb %sp!, {%r1-%r12, %lr} @ Push general registers.
|
|
|
- mrs %r2, cpsr @ Get the "exception" CPSR.
|
|
|
- stmdb %sp!, {%r0, %r2} @ Push exception CPSR and R0.
|
|
|
- sub %sp, #12 @ Account for pushes.
|
|
|
- mov %r2, %sp @ Get stack/trap frame.
|
|
|
- cps #ARM_MODE_SYSTEM @ Switch to system mode.
|
|
|
- str %lr, [%r2, #TRAP_USERLR] @ Save usermode SP.
|
|
|
- str %sp, [%r2, #TRAP_USERSP] @ Save usermode LR.
|
|
|
- cpsie i, #ARM_MODE_SVC @ Enable interrupts, svc mode.
|
|
|
-
|
|
|
- //
|
|
|
- // Save R0 and R1. These are needed by the signal dispatcher if the system
|
|
|
- // call gets restarted. It is not good enough to have them saved in the
|
|
|
- // trap frame as KeSystemCallHandler may restore an old trap frame.
|
|
|
- //
|
|
|
-
|
|
|
- stmdb %sp!, {%r0, %r1} @ Save the parameters.
|
|
|
- str %sp, [%r2] @ Save SP in the trap frame.
|
|
|
-
|
|
|
- CFI_DEF_CFA_OFFSET(8)
|
|
|
- CFI_OFFSET(r0, 0)
|
|
|
- CFI_OFFSET(r1, TRAP_R1)
|
|
|
- CFI_OFFSET(r2, TRAP_R2)
|
|
|
- CFI_OFFSET(r3, TRAP_R3)
|
|
|
- CFI_OFFSET(r4, TRAP_R4)
|
|
|
- CFI_OFFSET(r5, TRAP_R5)
|
|
|
- CFI_OFFSET(r6, TRAP_R6)
|
|
|
- CFI_OFFSET(r7, TRAP_R7)
|
|
|
- CFI_OFFSET(r8, TRAP_R8)
|
|
|
- CFI_OFFSET(r9, TRAP_R9)
|
|
|
- CFI_OFFSET(r10, TRAP_R10)
|
|
|
- CFI_OFFSET(r11, TRAP_R11)
|
|
|
- CFI_OFFSET(r12, TRAP_R12)
|
|
|
- CFI_OFFSET(sp, TRAP_USERSP)
|
|
|
- CFI_OFFSET(lr, TRAP_USERLR)
|
|
|
- CFI_OFFSET(pc, TRAP_PC)
|
|
|
-
|
|
|
- //
|
|
|
- // Just like in the fast case, R0 and R1 are preserved as the first two
|
|
|
- // parameters and R2 gets a pointer to the trap frame during the save.
|
|
|
- //
|
|
|
-
|
|
|
- bl KeSystemCallHandler
|
|
|
-
|
|
|
- //
|
|
|
- // Save the return value in the trap frame. It will either get restored on
|
|
|
- // exit or preserved for later if a signal is applied.
|
|
|
- //
|
|
|
-
|
|
|
- str %r0, [%sp, #(TRAP_R0 + 8)]
|
|
|
-
|
|
|
- //
|
|
|
- // Determine whether or not a signal is pending on the thread.
|
|
|
- //
|
|
|
-
|
|
|
- ARM_GET_CURRENT_THREAD @ Get current thread in R1.
|
|
|
- ldr %r1, [%r1, #THREAD_SIGNAL_PENDING] @ Load signal pending status.
|
|
|
- cmp %r1, #ThreadSignalPending @ Compare to signal pending.
|
|
|
-
|
|
|
-ArpSoftwareInterruptSlowSignal:
|
|
|
-
|
|
|
- //
|
|
|
- // The dispatch routine takes the trap frame, system call number and
|
|
|
- // system call parameter.
|
|
|
- //
|
|
|
-
|
|
|
- ITTTT EQ @ If the zero flag is set...
|
|
|
- ldreq %r2, [%sp, #4] @ Get system call parameter.
|
|
|
- ldreq %r1, [%sp] @ Get system call number.
|
|
|
- addeq %r0, %sp, #8 @ Get trap frame.
|
|
|
- bleq PsDispatchPendingSignalsOnCurrentThread @ Dispatch signal.
|
|
|
-
|
|
|
- //
|
|
|
- // A slow exit or an exit from a signal dispatch restores the full trap
|
|
|
- // frame.
|
|
|
- //
|
|
|
-
|
|
|
-ArpSoftwareInterruptEntrySlowEnd:
|
|
|
-
|
|
|
- //
|
|
|
- // Pop off the saved system call number and parameter and the SVC stack
|
|
|
- // pointer. The stack pointer should be the location of the saved system
|
|
|
- // call number, which isn't needed.
|
|
|
- //
|
|
|
-
|
|
|
- add %sp, %sp, #12
|
|
|
- CFI_ADJUST_CFA_OFFSET(-12)
|
|
|
+ CFI_UNDEFINED(lr)
|
|
|
+ eor %lr, %lr @ Zero SVC link register.
|
|
|
+ str %r0, [%sp, #TRAP_R0] @ Save the return value in R0.
|
|
|
+ str %lr, [%sp, #TRAP_EXCEPTION_CPSR] @ Indicate frame is complete.
|
|
|
+ add %r0, %sp, #TRAP_PC @ Get location after SVC LR.
|
|
|
+ stmdb %r0!, {%r3-%r12, %lr} @ Push registers and CPSR.
|
|
|
+ str %sp, [%sp] @ Save SP.
|
|
|
|
|
|
//
|
|
|
- // Restore the user mode stack and link registers.
|
|
|
+ // The dispatch routine takes the trap frame and either dispatches a signal
|
|
|
+ // or tinkers with the trap frame to restart the system call.
|
|
|
//
|
|
|
|
|
|
- mov %r0, %sp @ Get SVC stack pointer.
|
|
|
- cpsid i, #ARM_MODE_SYSTEM @ Switch to system mode.
|
|
|
- ldr %sp, [%r0, #(TRAP_USERSP - 4)] @ Restore usermode SP.
|
|
|
- ldr %lr, [%r0, #(TRAP_USERLR - 4)] @ Resotre usermode LR.
|
|
|
- cpsid i, #ARM_MODE_SVC @ Switch back to svc mode.
|
|
|
- ldr %r0, [%sp, #(TRAP_R0 - 4)] @ Restore R0.
|
|
|
- add %sp, %sp, #16 @ Pop up to R1.
|
|
|
- ldmia %sp!, {%r1-%r12, %lr} @ Restore general registers.
|
|
|
-
|
|
|
- CFI_DEF_CFA_OFFSET(0)
|
|
|
- CFI_SAME_VALUE(r0)
|
|
|
- CFI_SAME_VALUE(r1)
|
|
|
- CFI_SAME_VALUE(r2)
|
|
|
- CFI_SAME_VALUE(r3)
|
|
|
- CFI_SAME_VALUE(r4)
|
|
|
- CFI_SAME_VALUE(r5)
|
|
|
- CFI_SAME_VALUE(r6)
|
|
|
- CFI_SAME_VALUE(r7)
|
|
|
- CFI_SAME_VALUE(r8)
|
|
|
- CFI_SAME_VALUE(r9)
|
|
|
- CFI_SAME_VALUE(r10)
|
|
|
- CFI_SAME_VALUE(r11)
|
|
|
- CFI_SAME_VALUE(r12)
|
|
|
- CFI_UNDEFINED(sp)
|
|
|
- CFI_SAME_VALUE(lr)
|
|
|
- CFI_OFFSET(pc, 0)
|
|
|
-
|
|
|
- rfeia %sp! @ Restore PC and CPSR.
|
|
|
+ArpSoftwareInterruptSignalDispatch:
|
|
|
+ mov %r0, %sp @ Pass the trap frame.
|
|
|
+ bl PsApplyPendingSignalsOrRestart @ Dispatch or restart.
|
|
|
+ b ArpSoftwareInterruptRestore @ Jump in the line.
|
|
|
|
|
|
END_FUNCTION ArpSoftwareInterruptEntry
|
|
|
|