Author: ros-arm-bringup
Date: Fri Jan 1 01:03:52 2010
New Revision: 44843
URL:
http://svn.reactos.org/svn/reactos?rev=44843&view=rev
Log:
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).
Modified:
trunk/reactos/hal/halx86/generic/bios.c
trunk/reactos/hal/halx86/include/halp.h
Modified: trunk/reactos/hal/halx86/generic/bios.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/bios.c?…
==============================================================================
--- trunk/reactos/hal/halx86/generic/bios.c [iso-8859-1] (original)
+++ trunk/reactos/hal/halx86/generic/bios.c [iso-8859-1] Fri Jan 1 01:03:52 2010
@@ -19,6 +19,7 @@
ULONG HalpGpfHandler;
ULONG HalpBopHandler;
ULONG HalpSavedEsp0;
+USHORT HalpSavedTss;
USHORT HalpSavedIopmBase;
PUSHORT HalpSavedIoMap;
USHORT HalpSavedIoMapData[32][2];
@@ -28,6 +29,98 @@
#define GetPteAddress(x) (PHARDWARE_PTE)(((((ULONG_PTR)(x)) >> 12) << 2) +
0xC0000000)
/* 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
@@ -168,6 +261,9 @@
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 @@
HalpRestoreIopm();
/* Restore the IOPM */
- KeGetPcr()->TSS->IoMapBase = HalpSavedIopmBase;
+ KeGetPcr()->TSS->IoMapBase = HalpSavedIopmBase;
+
+ /* Restore the TSS */
+ if (HalpSavedTss) HalpReturnTss();
}
VOID
Modified: trunk/reactos/hal/halx86/include/halp.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/include/halp.h?…
==============================================================================
--- trunk/reactos/hal/halx86/include/halp.h [iso-8859-1] (original)
+++ trunk/reactos/hal/halx86/include/halp.h [iso-8859-1] Fri Jan 1 01:03:52 2010
@@ -172,18 +172,6 @@
VOID
);
-ULONG
-NTAPI
-HalpBorrowTss(
- VOID
-);
-
-ULONG
-NTAPI
-HalpReturnTss(
- ULONG SavedTss
-);
-
VOID
NTAPI
HalpBiosCall(