From 5596d2cb7edd2eba69b730a5f6d1b4231c912b87 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 8 May 2003 08:25:51 +0000 Subject: [PATCH] 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. --- sys/amd64/amd64/machdep.c | 2 +- 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 5fd94d7ca947..dd9c8c32b5e4 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 980e95f606aa..ca74135b603f 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); }