- Finish the work around for the Pentium cmpxchg8b lock errata: We detected the errat...
authorStefan Ginsberg <stefanginsberg@gmail.com>
Wed, 4 Nov 2009 21:57:32 +0000 (21:57 +0000)
committerStefan Ginsberg <stefanginsberg@gmail.com>
Wed, 4 Nov 2009 21:57:32 +0000 (21:57 +0000)
- Fix the "fix" of un-protecting the 7 IDT entries on P5 in HAL's BIOS call code when setting the custom Invalid Opcode handler. The IDT was unprotected but the write protection wasn't reapplied after the BIOS call, breaking the work around.

Other:
- KdDebuggerEnabled is a BOOLEAN, so don't do a dword compare in KeUpdateSystemTime.
- Use better comment for the hack where we always allow page faults to be handled, even if they the fault occured with interrupts disabled.

svn path=/trunk/; revision=43958

reactos/hal/halx86/generic/bios.c
reactos/hal/halx86/generic/reboot.c
reactos/ntoskrnl/ke/i386/systimer.S
reactos/ntoskrnl/ke/i386/trap.s

index ebbbce5..62f7227 100644 (file)
@@ -109,7 +109,11 @@ HalpSwitchToRealModeTrapHandlers(VOID)
     ULONG Handler;
     PHARDWARE_PTE IdtPte;
 
-    /* On i586, the first 7 entries of IDT are write-protected, unprotect them. */ // Nasty hto hack
+    /* 
+     * 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);
@@ -160,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);
@@ -167,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
@@ -197,7 +213,7 @@ HalpUnmapRealModeMemory(VOID)
         Pte = GetPteAddress((PVOID)i);
         Pte->Valid = 0;
         Pte->Write = 0;
-        //Pte->Owner = 0; // Missing this?
+        Pte->Owner = 0;
         Pte->PageFrameNumber = 0;
     }
     
index 510a66d..fe822ac 100644 (file)
@@ -49,7 +49,7 @@ HalpReboot(VOID)
     /* Enable warm reboot */
     ((PUSHORT)ZeroPageMapping)[0x239] = 0x1234;
 
-    /* Lock CMOS Access */
+    /* Lock CMOS Access (and disable interrupts) */
     HalpAcquireSystemHardwareSpinLock();
 
     /* Setup control register B */
index 8bf933b..8790f88 100644 (file)
@@ -114,7 +114,7 @@ _KeUpdateRunTime@8:
 
     /* Check if the debugger is enabled */
     cmp byte ptr __KdDebuggerEnabled, 0
-    je ResetDpcTime
+    jz ResetDpcTime
 
     /* Breakpoint */
     call _DbgBreakPoint@0
@@ -338,7 +338,7 @@ TimerExpired:
 
 DebugCheck:
     /* Check if the debugger is enabled */
-    cmp dword ptr __KdDebuggerEnabled, 0
+    cmp byte ptr __KdDebuggerEnabled, 0
     jnz DebuggerEnabled
 
     /* Check if this was a full tick */
index 15a146e..c8458c3 100644 (file)
@@ -947,6 +947,7 @@ _KiTrap6:
     /* Enter V86 Trap */
     V86_TRAP_PROLOG kit6_a, kit6_v
 
+VdmOpCodeFault:
     /* Not yet supported (Invalid OPCODE from V86) */
     UNHANDLED_PATH
 
@@ -957,6 +958,7 @@ NotV86UD:
     /* Enter trap */
     TRAP_PROLOG kit6_a, kit6_t
 
+DispatchLockErrata:
     /* Check if this happened in kernel mode */
     test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
     jz KmodeOpcode
@@ -1949,14 +1951,21 @@ _KiTrap14:
 NoFixUp:
     mov edi, cr2
 
-    /* REACTOS Mm Hack of Doom */
+    /* Check if this processor has the cmpxchg8b lock errata */
+    cmp byte ptr _KiI386PentiumLockErrataPresent, 0
+    jnz HandleLockErrata
+
+NotLockErrata:
+    /* HACK: Handle page faults with interrupts disabled */
     test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
     je HandlePf
 
     /* Enable interrupts and check if we got here with interrupts disabled */
     sti
-    /* test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
-    jz IllegalState */
+#ifdef HACK_ABOVE_FIXED
+    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
+    jz IllegalState
+#endif
 
 HandlePf:
     /* Send trap frame and check if this is kernel-mode or usermode */
@@ -2075,6 +2084,33 @@ VdmAlertGpf:
 
     /* FIXME: NOT SUPPORTED */
     UNHANDLED_PATH
+
+HandleLockErrata:
+
+    /* Fail if this isn't a write fault */
+    test word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0x4
+    jnz NotLockErrata
+
+    /* Also make sure the page fault is for IDT entry 6 */
+    mov eax, PCR[KPCR_IDT]
+    add eax, 0x30
+    cmp eax, edi
+    jne NotLockErrata
+
+    /*
+     * This is a write fault to the Invalid Opcode handler entry.
+     * We assume this is the lock errata and not a real write fault.
+     */
+
+    /* Clear the error code */
+    and dword ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0
+
+    /* Check if this happened in V86 mode */
+    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
+    jnz VdmOpCodeFault
+
+    /* Dispatch this to the invalid opcode handler */
+    jmp DispatchLockErrata
 .endfunc
 
 .func KiTrap0F