diff options
author | Bruce Evans <bde@FreeBSD.org> | 2001-05-02 13:06:58 +0000 |
---|---|---|
committer | Bruce Evans <bde@FreeBSD.org> | 2001-05-02 13:06:58 +0000 |
commit | 79d4e25beae13146f8748f44fc0a37e99957a68a (patch) | |
tree | 30c6caade34e7bf3e24bbd58875e191f7321e6b6 | |
parent | 7f17ea13a30083739564dae8dc07df961983a14f (diff) | |
download | src-79d4e25beae13146f8748f44fc0a37e99957a68a.tar.gz src-79d4e25beae13146f8748f44fc0a37e99957a68a.zip |
Fixed panics in npx exception handling. When using IRQ13 exception
handling, SMPng always switches the npx context away from curproc
before calling the handler, so the handler always paniced. When using
exception 16 exception handling, SMPng sometimes switches the npx
context away from curproc before calling the handler, so the handler
sometimes paniced. Also, we didn't lock the context while using it,
so we sometimes didn't detect the switch and then paniced in a less
controlled way.
Just lock the context while using it, and return without doing anything
except clearing the busy latch if the context is not for curproc. This
fixes the exception 16 case and makes the IRQ13 case harmless. In both
cases, the instruction that caused the exception is restarted and the
exception repeats. In the exception 16 case, we soon get an exception
that can be handled without doing anything special. In the IRQ13 case,
we get an easy to kill hung process.
Notes
Notes:
svn path=/head/; revision=76205
-rw-r--r-- | sys/amd64/amd64/fpu.c | 25 | ||||
-rw-r--r-- | sys/amd64/isa/npx.c | 25 | ||||
-rw-r--r-- | sys/i386/isa/npx.c | 25 |
3 files changed, 54 insertions, 21 deletions
diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c index 91dbcade7b83..4b04b462a097 100644 --- a/sys/amd64/amd64/fpu.c +++ b/sys/amd64/amd64/fpu.c @@ -725,26 +725,37 @@ npx_intr(dummy) u_short control; struct intrframe *frame; - mtx_lock(&Giant); - if (PCPU_GET(npxproc) == NULL || !npx_exists) { + if (!npx_exists) { printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n", PCPU_GET(npxproc), curproc, npx_exists); panic("npxintr from nowhere"); } + outb(0xf0, 0); + mtx_lock_spin(&sched_lock); if (PCPU_GET(npxproc) != curproc) { - printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n", - PCPU_GET(npxproc), curproc, npx_exists); - panic("npxintr from non-current process"); + /* + * Interrupt handling (for this or another interrupt) has + * switched npxproc from underneath us before we managed + * to handle this interrupt. Just ignore this interrupt. + * Control will eventually return to the instruction that + * caused it and it will repeat. In the npx_ex16 case, + * then we will eventually (usually soon) win the race. + * In the npx_irq13 case, we will always lose the race + * because we have switched to the IRQ13 thread. This will + * be fixed later. + */ + mtx_unlock_spin(&sched_lock); + return; } - - outb(0xf0, 0); fnstsw(&PCPU_GET(curpcb)->pcb_savefpu.sv_ex_sw); fnstcw(&control); fnclex(); + mtx_unlock_spin(&sched_lock); /* * Pass exception to process. */ + mtx_lock(&Giant); frame = (struct intrframe *)&dummy; /* XXX */ if ((ISPL(frame->if_cs) == SEL_UPL) || (frame->if_eflags & PSL_VM)) { /* diff --git a/sys/amd64/isa/npx.c b/sys/amd64/isa/npx.c index 91dbcade7b83..4b04b462a097 100644 --- a/sys/amd64/isa/npx.c +++ b/sys/amd64/isa/npx.c @@ -725,26 +725,37 @@ npx_intr(dummy) u_short control; struct intrframe *frame; - mtx_lock(&Giant); - if (PCPU_GET(npxproc) == NULL || !npx_exists) { + if (!npx_exists) { printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n", PCPU_GET(npxproc), curproc, npx_exists); panic("npxintr from nowhere"); } + outb(0xf0, 0); + mtx_lock_spin(&sched_lock); if (PCPU_GET(npxproc) != curproc) { - printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n", - PCPU_GET(npxproc), curproc, npx_exists); - panic("npxintr from non-current process"); + /* + * Interrupt handling (for this or another interrupt) has + * switched npxproc from underneath us before we managed + * to handle this interrupt. Just ignore this interrupt. + * Control will eventually return to the instruction that + * caused it and it will repeat. In the npx_ex16 case, + * then we will eventually (usually soon) win the race. + * In the npx_irq13 case, we will always lose the race + * because we have switched to the IRQ13 thread. This will + * be fixed later. + */ + mtx_unlock_spin(&sched_lock); + return; } - - outb(0xf0, 0); fnstsw(&PCPU_GET(curpcb)->pcb_savefpu.sv_ex_sw); fnstcw(&control); fnclex(); + mtx_unlock_spin(&sched_lock); /* * Pass exception to process. */ + mtx_lock(&Giant); frame = (struct intrframe *)&dummy; /* XXX */ if ((ISPL(frame->if_cs) == SEL_UPL) || (frame->if_eflags & PSL_VM)) { /* diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c index 91dbcade7b83..4b04b462a097 100644 --- a/sys/i386/isa/npx.c +++ b/sys/i386/isa/npx.c @@ -725,26 +725,37 @@ npx_intr(dummy) u_short control; struct intrframe *frame; - mtx_lock(&Giant); - if (PCPU_GET(npxproc) == NULL || !npx_exists) { + if (!npx_exists) { printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n", PCPU_GET(npxproc), curproc, npx_exists); panic("npxintr from nowhere"); } + outb(0xf0, 0); + mtx_lock_spin(&sched_lock); if (PCPU_GET(npxproc) != curproc) { - printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n", - PCPU_GET(npxproc), curproc, npx_exists); - panic("npxintr from non-current process"); + /* + * Interrupt handling (for this or another interrupt) has + * switched npxproc from underneath us before we managed + * to handle this interrupt. Just ignore this interrupt. + * Control will eventually return to the instruction that + * caused it and it will repeat. In the npx_ex16 case, + * then we will eventually (usually soon) win the race. + * In the npx_irq13 case, we will always lose the race + * because we have switched to the IRQ13 thread. This will + * be fixed later. + */ + mtx_unlock_spin(&sched_lock); + return; } - - outb(0xf0, 0); fnstsw(&PCPU_GET(curpcb)->pcb_savefpu.sv_ex_sw); fnstcw(&control); fnclex(); + mtx_unlock_spin(&sched_lock); /* * Pass exception to process. */ + mtx_lock(&Giant); frame = (struct intrframe *)&dummy; /* XXX */ if ((ISPL(frame->if_cs) == SEL_UPL) || (frame->if_eflags & PSL_VM)) { /* |