summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2003-05-08 08:25:51 +0000
committerpeter <peter@FreeBSD.org>2003-05-08 08:25:51 +0000
commit5596d2cb7edd2eba69b730a5f6d1b4231c912b87 (patch)
tree068f31415a939896ccfe864a0d51fbe3effc7f7d
parent2ed5055d26dad344fbe651b361efb7697ae3de0b (diff)
downloadFreeBSD-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.c2
-rw-r--r--sys/amd64/amd64/trap.c10
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);
}
OpenPOWER on IntegriCloud