summaryrefslogtreecommitdiffstats
path: root/sys/sparc64
diff options
context:
space:
mode:
authorjake <jake@FreeBSD.org>2002-03-29 16:35:26 +0000
committerjake <jake@FreeBSD.org>2002-03-29 16:35:26 +0000
commit8f9ce8398dc5c2f244495c3d0f279c47f0c2d58d (patch)
treee9eef5126c7bc7935260d949155e4f3eb728510f /sys/sparc64
parent1787e9ff8d12fd561c9345471ac9c345fa9251dd (diff)
downloadFreeBSD-src-8f9ce8398dc5c2f244495c3d0f279c47f0c2d58d.zip
FreeBSD-src-8f9ce8398dc5c2f244495c3d0f279c47f0c2d58d.tar.gz
Remove abuse of intr_disable/restore in MI code by moving the loop in ast()
back into the calling MD code. The MD code must ensure no races between checking the astpening flag and returning to usermode. Submitted by: peter (ia64 bits) Tested on: alpha (peter, jeff), i386, ia64 (peter), sparc64
Diffstat (limited to 'sys/sparc64')
-rw-r--r--sys/sparc64/sparc64/exception.S27
-rw-r--r--sys/sparc64/sparc64/exception.s27
2 files changed, 46 insertions, 8 deletions
diff --git a/sys/sparc64/sparc64/exception.S b/sys/sparc64/sparc64/exception.S
index 3e3b79e..8bc5ff7 100644
--- a/sys/sparc64/sparc64/exception.S
+++ b/sys/sparc64/sparc64/exception.S
@@ -2249,19 +2249,38 @@ ENTRY(tl0_ret)
9:
#endif
- wrpr %g0, PIL_TICK, %pil
+ /*
+ * Check for pending asts atomically with returning. We must raise
+ * the pil before checking, and if no asts are found the pil must
+ * remain raised until the retry is executed, or we risk missing asts
+ * caused by interrupts occuring after the test. If the pil is lowered,
+ * as it is when we call ast, the check must be re-executed.
+ */
+1: wrpr %g0, PIL_TICK, %pil
ldx [PCPU(CURTHREAD)], %l0
ldx [%l0 + TD_KSE], %l1
lduw [%l1 + KE_FLAGS], %l2
and %l2, KEF_ASTPENDING | KEF_NEEDRESCHED, %l2
- brz,pt %l2, 1f
+ brz,a,pt %l2, 2f
nop
+ wrpr %g0, 0, %pil
call ast
add %sp, CCFSZ + SPOFF, %o0
+ ba,a %xcc, 1b
+ nop
-1: ldx [PCB_REG + PCB_NSAVED], %l1
+ /*
+ * Check for windows that were spilled to the pcb and need to be
+ * copied out. This must be the last thing that is done before the
+ * return to usermode. If there are still user windows in the cpu
+ * and we call a nested function after this, which causes them to be
+ * spilled to the pcb, they will not be copied out and the stack will
+ * be inconsistent.
+ */
+2: ldx [PCB_REG + PCB_NSAVED], %l1
+ mov T_SPILL, %o0
brnz,a,pn %l1, .Ltl0_trap_reenter
- mov T_SPILL, %o0
+ wrpr %g0, 0, %pil
ldx [%sp + SPOFF + CCFSZ + TF_O0], %i0
ldx [%sp + SPOFF + CCFSZ + TF_O1], %i1
diff --git a/sys/sparc64/sparc64/exception.s b/sys/sparc64/sparc64/exception.s
index 3e3b79e..8bc5ff7 100644
--- a/sys/sparc64/sparc64/exception.s
+++ b/sys/sparc64/sparc64/exception.s
@@ -2249,19 +2249,38 @@ ENTRY(tl0_ret)
9:
#endif
- wrpr %g0, PIL_TICK, %pil
+ /*
+ * Check for pending asts atomically with returning. We must raise
+ * the pil before checking, and if no asts are found the pil must
+ * remain raised until the retry is executed, or we risk missing asts
+ * caused by interrupts occuring after the test. If the pil is lowered,
+ * as it is when we call ast, the check must be re-executed.
+ */
+1: wrpr %g0, PIL_TICK, %pil
ldx [PCPU(CURTHREAD)], %l0
ldx [%l0 + TD_KSE], %l1
lduw [%l1 + KE_FLAGS], %l2
and %l2, KEF_ASTPENDING | KEF_NEEDRESCHED, %l2
- brz,pt %l2, 1f
+ brz,a,pt %l2, 2f
nop
+ wrpr %g0, 0, %pil
call ast
add %sp, CCFSZ + SPOFF, %o0
+ ba,a %xcc, 1b
+ nop
-1: ldx [PCB_REG + PCB_NSAVED], %l1
+ /*
+ * Check for windows that were spilled to the pcb and need to be
+ * copied out. This must be the last thing that is done before the
+ * return to usermode. If there are still user windows in the cpu
+ * and we call a nested function after this, which causes them to be
+ * spilled to the pcb, they will not be copied out and the stack will
+ * be inconsistent.
+ */
+2: ldx [PCB_REG + PCB_NSAVED], %l1
+ mov T_SPILL, %o0
brnz,a,pn %l1, .Ltl0_trap_reenter
- mov T_SPILL, %o0
+ wrpr %g0, 0, %pil
ldx [%sp + SPOFF + CCFSZ + TF_O0], %i0
ldx [%sp + SPOFF + CCFSZ + TF_O1], %i1
OpenPOWER on IntegriCloud