diff options
author | peter <peter@FreeBSD.org> | 2003-05-08 08:25:51 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2003-05-08 08:25:51 +0000 |
commit | 5596d2cb7edd2eba69b730a5f6d1b4231c912b87 (patch) | |
tree | 068f31415a939896ccfe864a0d51fbe3effc7f7d | |
parent | 2ed5055d26dad344fbe651b361efb7697ae3de0b (diff) | |
download | FreeBSD-src-5596d2cb7edd2eba69b730a5f6d1b4231c912b87.zip FreeBSD-src-5596d2cb7edd2eba69b730a5f6d1b4231c912b87.tar.gz |
Oops. Turn T_PAGEFLT back into an interrupt gate. It is *critical*
that interrupts be disabled and remain disabled until %cr2 is read.
Otherwise we can preempt and another process can fault, and by the
time we read %cr2, we see a different processes fault address. This
Greatly Confuses vm_fault() (to say the least). The i386 port has
got this marked as a bug workaround for a Cyrix CPU, which is what
lead me astray. Its actually necessary for preemption, regardless
of whether Cyrix cpus had a bug or not.
-rw-r--r-- | sys/amd64/amd64/machdep.c | 2 | ||||
-rw-r--r-- | sys/amd64/amd64/trap.c | 10 |
2 files changed, 10 insertions, 2 deletions
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 5fd94d7..dd9c8c3 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1219,7 +1219,7 @@ hammer_time(void) setidt(11, &IDTVEC(missing), SDT_SYSTGT, SEL_KPL, 0); setidt(12, &IDTVEC(stk), SDT_SYSTGT, SEL_KPL, 0); setidt(13, &IDTVEC(prot), SDT_SYSTGT, SEL_KPL, 0); - setidt(14, &IDTVEC(page), SDT_SYSTGT, SEL_KPL, 0); + setidt(14, &IDTVEC(page), SDT_SYSIGT, SEL_KPL, 0); setidt(15, &IDTVEC(rsvd), SDT_SYSTGT, SEL_KPL, 0); setidt(16, &IDTVEC(fpu), SDT_SYSTGT, SEL_KPL, 0); setidt(17, &IDTVEC(align), SDT_SYSTGT, SEL_KPL, 0); diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 980e95f..ca74135 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -213,9 +213,17 @@ trap(frame) * do the VM lookup, so just consider it a fatal trap so the * kernel can print out a useful trap message and even get * to the debugger. + * + * Note that T_PAGEFLT is registered as an interrupt gate. This + * is just like a trap gate, except interrupts are disabled. This + * happens to be critically important, because we could otherwise + * preempt and run another process that may cause %cr2 to be + * clobbered for something else. */ eva = rcr2(); - if (PCPU_GET(spinlocks) != NULL) + if (PCPU_GET(spinlocks) == NULL) + enable_intr(); + else trap_fatal(&frame, eva); } |