[NTOS:KE] Use multi-processor-aware KeGetPcr() instead of the legacy PCR.
[reactos.git] / ntoskrnl / ke / i386 / traphdlr.c
index 7cf1fcd..6f26ac9 100644 (file)
@@ -455,10 +455,9 @@ KiTrap01Handler(IN PKTRAP_FRAME TrapFrame)
                              TrapFrame);
 }
 
-DECLSPEC_NORETURN
 VOID
 __cdecl
-KiTrap02(VOID)
+KiTrap02Handler(VOID)
 {
     PKTSS Tss, NmiTss;
     PKTHREAD Thread;
@@ -478,8 +477,8 @@ KiTrap02(VOID)
     _disable();
 
     /* Get the current TSS, thread, and process */
-    Tss = PCR->TSS;
-    Thread = ((PKIPCR)PCR)->PrcbData.CurrentThread;
+    Tss = KeGetPcr()->TSS;
+    Thread = ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
     Process = Thread->ApcState.Process;
 
     /* Save data usually not present in the TSS */
@@ -499,7 +498,7 @@ KiTrap02(VOID)
      * Note that in reality, we are already on the NMI TSS -- we just
      * need to update the PCR to reflect this.
      */
-    PCR->TSS = NmiTss;
+    KeGetPcr()->TSS = NmiTss;
     __writeeflags(__readeflags() &~ EFLAGS_NESTED_TASK);
     TssGdt->HighWord.Bits.Dpl = 0;
     TssGdt->HighWord.Bits.Pres = 1;
@@ -524,7 +523,7 @@ KiTrap02(VOID)
     TrapFrame.Esi = Tss->Esi;
     TrapFrame.Edi = Tss->Edi;
     TrapFrame.SegFs = Tss->Fs;
-    TrapFrame.ExceptionList = PCR->NtTib.ExceptionList;
+    TrapFrame.ExceptionList = KeGetPcr()->NtTib.ExceptionList;
     TrapFrame.PreviousPreviousMode = (ULONG)-1;
     TrapFrame.Eax = Tss->Eax;
     TrapFrame.Ecx = Tss->Ecx;
@@ -548,10 +547,10 @@ KiTrap02(VOID)
          * the normal APIs here as playing with the IRQL could change the system
          * state.
          */
-        OldIrql = PCR->Irql;
-        PCR->Irql = HIGH_LEVEL;
+        OldIrql = KeGetPcr()->Irql;
+        KeGetPcr()->Irql = HIGH_LEVEL;
         HalHandleNMI(NULL);
-        PCR->Irql = OldIrql;
+        KeGetPcr()->Irql = OldIrql;
     }
 
     /*
@@ -561,25 +560,24 @@ KiTrap02(VOID)
      * We have to make sure we're still in our original NMI -- a nested NMI
      * will point back to the NMI TSS, and in that case we're hosed.
      */
-    if (PCR->TSS->Backlink != KGDT_NMI_TSS)
+    if (KeGetPcr()->TSS->Backlink == KGDT_NMI_TSS)
     {
-        /* Restore original TSS */
-        PCR->TSS = Tss;
+        /* Unhandled: crash the system */
+        KiSystemFatalException(EXCEPTION_NMI, NULL);
+    }
 
-        /* Set it back to busy */
-        TssGdt->HighWord.Bits.Dpl = 0;
-        TssGdt->HighWord.Bits.Pres = 1;
-        TssGdt->HighWord.Bits.Type = I386_ACTIVE_TSS;
+    /* Restore original TSS */
+    KeGetPcr()->TSS = Tss;
 
-        /* Restore nested flag */
-        __writeeflags(__readeflags() | EFLAGS_NESTED_TASK);
+    /* Set it back to busy */
+    TssGdt->HighWord.Bits.Dpl = 0;
+    TssGdt->HighWord.Bits.Pres = 1;
+    TssGdt->HighWord.Bits.Type = I386_ACTIVE_TSS;
 
-        /* Handled, return from interrupt */
-        KiIret();
-    }
+    /* Restore nested flag */
+    __writeeflags(__readeflags() | EFLAGS_NESTED_TASK);
 
-    /* Unhandled: crash the system */
-    KiSystemFatalException(EXCEPTION_NMI, NULL);
+    /* Handled, return from interrupt */
 }
 
 DECLSPEC_NORETURN
@@ -829,11 +827,53 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
 
 DECLSPEC_NORETURN
 VOID
-FASTCALL
-KiTrap08Handler(IN PKTRAP_FRAME TrapFrame)
+__cdecl
+KiTrap08Handler(VOID)
 {
-    /* FIXME: Not handled */
-    KiSystemFatalException(EXCEPTION_DOUBLE_FAULT, TrapFrame);
+    PKTSS Tss, DfTss;
+    PKTHREAD Thread;
+    PKPROCESS Process;
+    PKGDTENTRY TssGdt;
+
+    /* For sanity's sake, make sure interrupts are disabled */
+    _disable();
+
+    /* Get the current TSS, thread, and process */
+    Tss = KeGetPcr()->TSS;
+    Thread = ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
+    Process = Thread->ApcState.Process;
+
+    /* Save data usually not present in the TSS */
+    Tss->CR3 = Process->DirectoryTableBase[0];
+    Tss->IoMapBase = Process->IopmOffset;
+    Tss->LDT = Process->LdtDescriptor.LimitLow ? KGDT_LDT : 0;
+
+    /* Now get the base address of the double-fault TSS */
+    TssGdt = &((PKIPCR)KeGetPcr())->GDT[KGDT_DF_TSS / sizeof(KGDTENTRY)];
+    DfTss  = (PKTSS)(ULONG_PTR)(TssGdt->BaseLow |
+                                TssGdt->HighWord.Bytes.BaseMid << 16 |
+                                TssGdt->HighWord.Bytes.BaseHi << 24);
+
+    /*
+     * Switch to it and activate it, masking off the nested flag.
+     *
+     * Note that in reality, we are already on the double-fault TSS
+     * -- we just need to update the PCR to reflect this.
+     */
+    KeGetPcr()->TSS = DfTss;
+    __writeeflags(__readeflags() &~ EFLAGS_NESTED_TASK);
+    TssGdt->HighWord.Bits.Dpl = 0;
+    TssGdt->HighWord.Bits.Pres = 1;
+    // TssGdt->HighWord.Bits.Type &= ~0x2; /* I386_ACTIVE_TSS --> I386_TSS */
+    TssGdt->HighWord.Bits.Type = I386_TSS; // Busy bit cleared in the TSS selector.
+
+    /* Bugcheck the system */
+    KeBugCheckWithTf(UNEXPECTED_KERNEL_MODE_TRAP,
+                     EXCEPTION_DOUBLE_FAULT,
+                     (ULONG_PTR)Tss,
+                     0,
+                     0,
+                     NULL);
 }
 
 DECLSPEC_NORETURN