- Finish the work around for the Pentium cmpxchg8b lock errata: We detected the errat...
[reactos.git] / reactos / hal / halx86 / generic / bios.c
index 279764d..62f7227 100644 (file)
@@ -107,6 +107,21 @@ NTAPI
 HalpSwitchToRealModeTrapHandlers(VOID)
 {
     ULONG Handler;
+    PHARDWARE_PTE IdtPte;
+
+    /* 
+     * On P5, the first 7 entries of the IDT are write protected to work around
+     * the cmpxchg8b lock errata. Unprotect them here so we can set our custom
+     * invalid op-code handler.
+     */
+    if (KeGetCurrentPrcb()->CpuType == 5)
+    {
+        IdtPte = GetPteAddress(((PKIPCR)KeGetPcr())->IDT);
+        IdtPte->Write = 1;
+
+        /* Flush the TLB by resetting CR3 */
+        __writecr3(__readcr3());
+    }
 
     /* Save the current Invalid Opcode and General Protection Fault Handlers */
     HalpGpfHandler = ((((PKIPCR)KeGetPcr())->IDT[13].ExtendedOffset << 16) &
@@ -149,6 +164,8 @@ VOID
 NTAPI
 HalpRestoreTrapHandlers(VOID)
 {
+    PHARDWARE_PTE IdtPte;
+
     /* We're back, restore the handlers we over-wrote */
     ((PKIPCR)KeGetPcr())->IDT[13].ExtendedOffset =
     (USHORT)((HalpGpfHandler >> 16) & 0xFFFF);
@@ -156,6 +173,16 @@ HalpRestoreTrapHandlers(VOID)
     ((PKIPCR)KeGetPcr())->IDT[6].ExtendedOffset =
         (USHORT)((HalpBopHandler >> 16) & 0xFFFF);
     ((PKIPCR)KeGetPcr())->IDT[6].Offset = (USHORT)HalpBopHandler;
+
+    /* On P5, restore the write protection for the first 7 IDT entries */
+    if (KeGetCurrentPrcb()->CpuType == 5)
+    {
+        IdtPte = GetPteAddress(((PKIPCR)KeGetPcr())->IDT);
+        IdtPte->Write = 0;
+
+        /* Flush the TLB by resetting CR3 */
+        __writecr3(__readcr3());
+    }
 }
 
 VOID
@@ -186,6 +213,7 @@ HalpUnmapRealModeMemory(VOID)
         Pte = GetPteAddress((PVOID)i);
         Pte->Valid = 0;
         Pte->Write = 0;
+        Pte->Owner = 0;
         Pte->PageFrameNumber = 0;
     }
     
@@ -202,10 +230,10 @@ BOOLEAN
 NTAPI
 HalpBiosDisplayReset(VOID)
 {
-    ULONG Flags = 0;
+    ULONG Flags;
 
     /* Disable interrupts */
-    Ke386SaveFlags(Flags);
+    Flags = __readeflags();
     _disable();
 
     /* Map memory available to the V8086 real-mode code */
@@ -230,7 +258,7 @@ HalpBiosDisplayReset(VOID)
     HalpUnmapRealModeMemory();
 
     /* Restore interrupts if they were previously enabled */
-    Ke386RestoreFlags(Flags);
+    __writeeflags(Flags);
     return TRUE;
 }