diff --git a/reactos/hal/halx86/generic/bios.c b/reactos/hal/halx86/generic/bios.c index 62f7227af08..76b080c0c01 100644 --- a/reactos/hal/halx86/generic/bios.c +++ b/reactos/hal/halx86/generic/bios.c @@ -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();