- Finish the work around for the Pentium cmpxchg8b lock errata: We detected the errata and allocated the 7 first IDT entries on a write protected page, but the final piece of the work around, detecting the write fault ti the Invalid Opcode handler, was missing. Implemented this in the page fault handler to detect and dispatch the write fault to the Invalid Opcode handler.

- 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
This commit is contained in:
Stefan Ginsberg 2009-11-04 21:57:32 +00:00
parent 66afccbaeb
commit 422721748d
4 changed files with 60 additions and 8 deletions

View 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;
}

View 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 */

View 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 */

View 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