- Fix work around for the cmpxchg8b lock errata work around -- don't set write protec...
authorStefan Ginsberg <stefanginsberg@gmail.com>
Sun, 8 Nov 2009 21:42:28 +0000 (21:42 +0000)
committerStefan Ginsberg <stefanginsberg@gmail.com>
Sun, 8 Nov 2009 21:42:28 +0000 (21:42 +0000)
svn path=/trunk/; revision=44032

reactos/hal/halx86/generic/bios.c

index 62f7227..76b080c 100644 (file)
@@ -26,6 +26,14 @@ ULONG HalpSavedEsp0;
 #define GetPdeAddress(x) (PHARDWARE_PTE)(((((ULONG_PTR)(x)) >> 22) << 2) + 0xC0300000)
 #define GetPteAddress(x) (PHARDWARE_PTE)(((((ULONG_PTR)(x)) >> 12) << 2) + 0xC0000000)
 
+#if !defined(CONFIG_SMP)
+#define GetPteWriteBit(PTE) ((PTE)->Write)
+#define SetPteWriteBit(PTE, x) ((PTE)->Write = (x))
+#else
+#define GetPteWriteBit(PTE) ((PTE)->Writable)
+#define SetPteWriteBit(PTE, x) ((PTE)->Writable = (x))
+#endif
+
 /* FUNCTIONS ******************************************************************/
 
 VOID
@@ -107,21 +115,6 @@ 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) &
@@ -164,8 +157,6 @@ 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);
@@ -173,16 +164,6 @@ 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
@@ -231,6 +212,8 @@ NTAPI
 HalpBiosDisplayReset(VOID)
 {
     ULONG Flags;
+    PHARDWARE_PTE IdtPte;
+    BOOLEAN RestoreWriteProtection = FALSE;
 
     /* Disable interrupts */
     Flags = __readeflags();
@@ -239,6 +222,24 @@ HalpBiosDisplayReset(VOID)
     /* Map memory available to the V8086 real-mode code */
     HalpMapRealModeMemory();
 
+    /* 
+     * 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)
+    {
+        /* Get the PTE and check if it is has been write protected yet  */
+        IdtPte = GetPteAddress(((PKIPCR)KeGetPcr())->IDT);
+        if (GetPteWriteBit(IdtPte) == 0)
+        {
+            /* Remove the protection and flush the TLB */
+            SetPteWriteBit(IdtPte, 1);
+            __writecr3(__readcr3());
+            RestoreWriteProtection = TRUE;
+        }
+    }
+
     /* Use special invalid opcode and GPF trap handlers */
     HalpSwitchToRealModeTrapHandlers();
 
@@ -250,6 +251,15 @@ HalpBiosDisplayReset(VOID)
 
     /* Restore kernel trap handlers */
     HalpRestoreTrapHandlers();
+
+    /* Check if we removed the write protection before */
+    if (RestoreWriteProtection)
+    {
+        /* Get the PTE, restore the write protection and flush the TLB */
+        IdtPte = GetPteAddress(((PKIPCR)KeGetPcr())->IDT);
+        SetPteWriteBit(IdtPte, 0);
+        __writecr3(__readcr3());
+    }
     
     /* Restore TSS and IOPM */
     HalpRestoreIoPermissionsAndTask();