NMI Support Patch 3:

[HAL]: If the current TSS does not have enough space for an I/O Privilege Map then "borrow" the default TSS while the BIOS Call is in-flight. "Return" it when the BIOS call has ended. Fixes panics during a double fault (since the double fault handler will attempt to clear the display through a Video ROM BIOS Interrupt 10h). Allows NMI panics to do BIOS calls as well (for later).


svn path=/trunk/; revision=44843
This commit is contained in:
ReactOS Portable Systems Group 2010-01-01 00:03:52 +00:00
parent fd1ccbe10c
commit 040c742cac
2 changed files with 100 additions and 13 deletions

View file

@ -19,6 +19,7 @@ HARDWARE_PTE HalpSavedPte;
ULONG HalpGpfHandler;
ULONG HalpBopHandler;
ULONG HalpSavedEsp0;
USHORT HalpSavedTss;
USHORT HalpSavedIopmBase;
PUSHORT HalpSavedIoMap;
USHORT HalpSavedIoMapData[32][2];
@ -29,6 +30,98 @@ ULONG HalpSavedIoMapEntries;
/* FUNCTIONS ******************************************************************/
VOID
NTAPI
HalpBorrowTss(VOID)
{
USHORT Tss;
PKGDTENTRY TssGdt;
ULONG_PTR TssLimit;
PKTSS TssBase;
//
// Get the current TSS and its GDT entry
//
Tss = Ke386GetTr();
TssGdt = &((PKIPCR)KeGetPcr())->GDT[Tss / sizeof(KGDTENTRY)];
//
// Get the KTSS limit and check if it has IOPM space
//
TssLimit = TssGdt->LimitLow | TssGdt->HighWord.Bits.LimitHi << 16;
//
// If the KTSS doesn't have enough space this is probably an NMI or DF
//
if (TssLimit > IOPM_SIZE)
{
//
// We are good to go
//
HalpSavedTss = 0;
return;
}
//
// Get the "real" TSS
//
TssGdt = &((PKIPCR)KeGetPcr())->GDT[KGDT_TSS / sizeof(KGDTENTRY)];
TssBase = (PKTSS)(ULONG_PTR)(TssGdt->BaseLow |
TssGdt->HighWord.Bytes.BaseMid << 16 |
TssGdt->HighWord.Bytes.BaseHi << 24);
//
// Switch to it
//
KeGetPcr()->TSS = TssBase;
//
// Set it up
//
TssGdt->HighWord.Bits.Type = I386_TSS;
TssGdt->HighWord.Bits.Pres = 1;
TssGdt->HighWord.Bits.Dpl = 0;
//
// Load new TSS and return old one
//
Ke386SetTr(KGDT_TSS);
HalpSavedTss = Tss;
}
VOID
NTAPI
HalpReturnTss(VOID)
{
PKGDTENTRY TssGdt;
PKTSS TssBase;
//
// Get the original TSS
//
TssGdt = &((PKIPCR)KeGetPcr())->GDT[HalpSavedTss / sizeof(KGDTENTRY)];
TssBase = (PKTSS)(ULONG_PTR)(TssGdt->BaseLow |
TssGdt->HighWord.Bytes.BaseMid << 16 |
TssGdt->HighWord.Bytes.BaseHi << 24);
//
// Switch to it
//
KeGetPcr()->TSS = TssBase;
//
// Set it up
//
TssGdt->HighWord.Bits.Type = I386_TSS;
TssGdt->HighWord.Bits.Pres = 1;
TssGdt->HighWord.Bits.Dpl = 0;
//
// Load old TSS
//
Ke386SetTr(HalpSavedTss);
}
VOID
NTAPI
HalpStoreAndClearIopm(VOID)
@ -168,6 +261,9 @@ VOID
NTAPI
HalpSetupRealModeIoPermissionsAndTask(VOID)
{
/* Switch to valid TSS */
HalpBorrowTss();
/* Save a copy of the I/O Map and delete it */
HalpSavedIoMap = (PUSHORT)&(KeGetPcr()->TSS->IoMaps[0]);
HalpStoreAndClearIopm();
@ -204,7 +300,10 @@ HalpRestoreIoPermissionsAndTask(VOID)
HalpRestoreIopm();
/* Restore the IOPM */
KeGetPcr()->TSS->IoMapBase = HalpSavedIopmBase;
KeGetPcr()->TSS->IoMapBase = HalpSavedIopmBase;
/* Restore the TSS */
if (HalpSavedTss) HalpReturnTss();
}
VOID

View file

@ -172,18 +172,6 @@ HalpBiosDisplayReset(
VOID
);
ULONG
NTAPI
HalpBorrowTss(
VOID
);
ULONG
NTAPI
HalpReturnTss(
ULONG SavedTss
);
VOID
NTAPI
HalpBiosCall(