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.
This commit is contained in:
parent
2ed5055d26
commit
5596d2cb7e
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user