diff options
author | jake <jake@FreeBSD.org> | 2002-03-29 16:35:26 +0000 |
---|---|---|
committer | jake <jake@FreeBSD.org> | 2002-03-29 16:35:26 +0000 |
commit | 8f9ce8398dc5c2f244495c3d0f279c47f0c2d58d (patch) | |
tree | e9eef5126c7bc7935260d949155e4f3eb728510f /sys/sparc64 | |
parent | 1787e9ff8d12fd561c9345471ac9c345fa9251dd (diff) | |
download | FreeBSD-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.S | 27 | ||||
-rw-r--r-- | sys/sparc64/sparc64/exception.s | 27 |
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 |