NMI Support Patch 4:

[HAL]:  Use Mm headers to support PTE/PDE address translation instead of a hardcoded, homegrown macro. WARNING: The current HAL code is not PAE compatible (as it already wasn't).
    [NTOS]: Define an inline function to set and query an interrupt handler associated with a given IDT vector. This results in much cleaner code as the uglyness of manually setting up an IDT handler isn't duplicated 10 times. Additionally, it fixes some callers which had not been using HalVectorToIDTEntry to make the initial translation.

svn path=/trunk/; revision=44855
This commit is contained in:
ReactOS Portable Systems Group 2010-01-01 15:09:14 +00:00
parent 45316fbf63
commit 61df639e4a
5 changed files with 91 additions and 55 deletions

View file

@ -16,8 +16,8 @@
ULONG HalpSavedPfn;
HARDWARE_PTE HalpSavedPte;
ULONG HalpGpfHandler;
ULONG HalpBopHandler;
PVOID HalpGpfHandler;
PVOID HalpBopHandler;
ULONG HalpSavedEsp0;
USHORT HalpSavedTss;
USHORT HalpSavedIopmBase;
@ -25,9 +25,6 @@ PUSHORT HalpSavedIoMap;
USHORT HalpSavedIoMapData[32][2];
ULONG HalpSavedIoMapEntries;
#define GetPdeAddress(x) (PHARDWARE_PTE)(((((ULONG_PTR)(x)) >> 22) << 2) + 0xC0300000)
#define GetPteAddress(x) (PHARDWARE_PTE)(((((ULONG_PTR)(x)) >> 12) << 2) + 0xC0000000)
/* FUNCTIONS ******************************************************************/
VOID
@ -189,7 +186,7 @@ HalpMapRealModeMemory(VOID)
ULONG i;
/* Get the page table directory for the lowest meg of memory */
Pte = GetPdeAddress(0);
Pte = HalAddressToPde(0);
HalpSavedPfn = Pte->PageFrameNumber;
HalpSavedPte = *Pte;
@ -197,7 +194,7 @@ HalpMapRealModeMemory(VOID)
Pte->Valid = 1;
Pte->Write = 1;
Pte->Owner = 1;
Pte->PageFrameNumber = (GetPdeAddress(0xFFC00000))->PageFrameNumber;
Pte->PageFrameNumber = (HalAddressToPde(0xFFC00000))->PageFrameNumber;
/* Flush the TLB by resetting CR3 */
__writecr3(__readcr3());
@ -206,7 +203,7 @@ HalpMapRealModeMemory(VOID)
for (i = 0; i < 0x100000; i += PAGE_SIZE)
{
/* Identity map it */
Pte = GetPteAddress((PVOID)i);
Pte = HalAddressToPte(i);
Pte->PageFrameNumber = i >> PAGE_SHIFT;
Pte->Valid = 1;
Pte->Write = 1;
@ -214,8 +211,8 @@ HalpMapRealModeMemory(VOID)
}
/* Now get the entry for our real mode V86 code and the target */
Pte = GetPteAddress(0x20000);
V86Pte = GetPteAddress(&HalpRealModeStart);
Pte = HalAddressToPte(0x20000);
V86Pte = HalAddressToPte(&HalpRealModeStart);
do
{
/* Map the physical address into our real-mode region */
@ -224,7 +221,7 @@ HalpMapRealModeMemory(VOID)
/* Keep going until we've reached the end of our region */
Pte++;
V86Pte++;
} while (V86Pte <= GetPteAddress(&HalpRealModeEnd));
} while (V86Pte <= HalAddressToPte(&HalpRealModeEnd));
/* Flush the TLB by resetting CR3 */
__writecr3(__readcr3());
@ -234,27 +231,21 @@ VOID
NTAPI
HalpSwitchToRealModeTrapHandlers(VOID)
{
ULONG Handler;
//
// Save the current Invalid Opcode and General Protection Fault Handlers
//
HalpGpfHandler = KeQueryInterruptHandler(13);
HalpBopHandler = KeQueryInterruptHandler(6);
/* Save the current Invalid Opcode and General Protection Fault Handlers */
HalpGpfHandler = ((((PKIPCR)KeGetPcr())->IDT[13].ExtendedOffset << 16) &
0xFFFF0000) |
(((PKIPCR)KeGetPcr())->IDT[13].Offset & 0xFFFF);
HalpBopHandler = ((((PKIPCR)KeGetPcr())->IDT[6].ExtendedOffset << 16) &
0xFFFF0000) |
(((PKIPCR)KeGetPcr())->IDT[6].Offset & 0xFFFF);
/* Now set our own GPF handler to handle exceptions while in real mode */
Handler = (ULONG_PTR)HalpTrap0D;
((PKIPCR)KeGetPcr())->IDT[13].ExtendedOffset =
(USHORT)((Handler >> 16) & 0xFFFF);
((PKIPCR)KeGetPcr())->IDT[13].Offset = (USHORT)Handler;
/* And our own invalid opcode handler to detect the BOP to get us out */
Handler = (ULONG_PTR)HalpTrap06;
((PKIPCR)KeGetPcr())->IDT[6].ExtendedOffset =
(USHORT)((Handler >> 16) & 0xFFFF);
((PKIPCR)KeGetPcr())->IDT[6].Offset = (USHORT)Handler;
//
// Now set our own GPF handler to handle exceptions while in real mode
//
KeRegisterInterruptHandler(13, HalpTrap0D);
//
// And our own invalid opcode handler to detect the BOP to get us out
//
KeRegisterInterruptHandler(6, HalpTrap06);
}
VOID
@ -280,13 +271,11 @@ VOID
NTAPI
HalpRestoreTrapHandlers(VOID)
{
/* We're back, restore the handlers we over-wrote */
((PKIPCR)KeGetPcr())->IDT[13].ExtendedOffset =
(USHORT)((HalpGpfHandler >> 16) & 0xFFFF);
((PKIPCR)KeGetPcr())->IDT[13].Offset = (USHORT)HalpGpfHandler;
((PKIPCR)KeGetPcr())->IDT[6].ExtendedOffset =
(USHORT)((HalpBopHandler >> 16) & 0xFFFF);
((PKIPCR)KeGetPcr())->IDT[6].Offset = (USHORT)HalpBopHandler;
//
// We're back, restore the handlers we over-wrote
//
KeRegisterInterruptHandler(13, HalpGpfHandler);
KeRegisterInterruptHandler(6, HalpBopHandler);
}
VOID
@ -317,7 +306,7 @@ HalpUnmapRealModeMemory(VOID)
for (i = 0; i < 0x100000; i += PAGE_SIZE)
{
/* Invalidate each PTE */
Pte = GetPteAddress((PVOID)i);
Pte = HalAddressToPte(i);
Pte->Valid = 0;
Pte->Write = 0;
Pte->Owner = 0;
@ -325,7 +314,7 @@ HalpUnmapRealModeMemory(VOID)
}
/* Restore the PDE for the lowest megabyte of memory */
Pte = GetPdeAddress(0);
Pte = HalAddressToPde(0);
*Pte = HalpSavedPte;
Pte->PageFrameNumber = HalpSavedPfn;
@ -353,7 +342,7 @@ HalpBiosDisplayReset(VOID)
* the cmpxchg8b lock errata. Unprotect them here so we can set our custom
* invalid op-code handler.
*/
IdtPte = GetPteAddress(((PKIPCR)KeGetPcr())->IDT);
IdtPte = HalAddressToPte(((PKIPCR)KeGetPcr())->IDT);
RestoreWriteProtection = IdtPte->Write;
/* Use special invalid opcode and GPF trap handlers */

View file

@ -29,6 +29,9 @@
/* Internal kernel headers */
#include "internal/pci.h"
#define KeGetCurrentThread _KeGetCurrentThread
#include <internal/i386/ke.h>
#include <internal/i386/mm.h>
#ifdef _M_AMD64
#include "internal/amd64/intrin_i.h"
#else

View file

@ -34,7 +34,13 @@
(((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F))
#define INT_BCD(int) \
(UCHAR)(((int / 10) << 4) + (int % 10))
//
// Mm PTE/PDE to Hal PTE/PDE
//
#define HalAddressToPde(x) (PHARDWARE_PTE)MiAddressToPde(x)
#define HalAddressToPte(x) (PHARDWARE_PTE)MiAddressToPte(x)
typedef struct _IDTUsageFlags
{
UCHAR Flags;

View file

@ -65,6 +65,53 @@ extern ULONG Ke386CacheAlignment;
//
#define KeGetTrapFrameInterruptState(TrapFrame) \
BooleanFlagOn((TrapFrame)->EFlags, EFLAGS_INTERRUPT_MASK)
//
// Registers an interrupt handler with an IDT vector
//
FORCEINLINE
VOID
KeRegisterInterruptHandler(IN ULONG Vector,
IN PVOID Handler)
{
UCHAR Entry;
ULONG_PTR Address;
PKIPCR Pcr = (PKIPCR)KeGetPcr();
//
// Get the entry from the HAL
//
Entry = HalVectorToIDTEntry(Vector);
Address = PtrToUlong(Handler);
//
// Now set the data
//
Pcr->IDT[Entry].ExtendedOffset = (USHORT)(Address >> 16);
Pcr->IDT[Entry].Offset = (USHORT)Address;
}
//
// Returns the registered interrupt handler for a given IDT vector
//
FORCEINLINE
PVOID
KeQueryInterruptHandler(IN ULONG Vector)
{
PKIPCR Pcr = (PKIPCR)KeGetPcr();
UCHAR Entry;
//
// Get the entry from the HAL
//
Entry = HalVectorToIDTEntry(Vector);
//
// Read the entry from the IDT
//
return (PVOID)(((Pcr->IDT[Entry].ExtendedOffset << 16) & 0xFFFF0000) |
(Pcr->IDT[Entry].Offset & 0xFFFF));
}
//
// Invalidates the TLB entry for a specified address

View file

@ -29,7 +29,7 @@ KiGetVectorDispatch(IN ULONG Vector,
IN PDISPATCH_INFO Dispatch)
{
PKINTERRUPT_ROUTINE Handler;
ULONG Current;
PVOID Current;
UCHAR Type;
UCHAR Entry;
@ -54,9 +54,7 @@ KiGetVectorDispatch(IN ULONG Vector,
Dispatch->FlatDispatch = NULL;
/* Get the current handler */
Current = ((((PKIPCR)KeGetPcr())->IDT[Entry].ExtendedOffset << 16)
& 0xFFFF0000) |
(((PKIPCR)KeGetPcr())->IDT[Entry].Offset & 0xFFFF);
Current = KeQueryInterruptHandler(Vector);
/* Set the interrupt */
Dispatch->Interrupt = CONTAINING_RECORD(Current,
@ -100,7 +98,6 @@ KiConnectVectorToInterrupt(IN PKINTERRUPT Interrupt,
DISPATCH_INFO Dispatch;
PKINTERRUPT_ROUTINE Handler;
PULONG Patch = &Interrupt->DispatchCode[0];
UCHAR Entry;
/* Get vector data */
KiGetVectorDispatch(Interrupt->Vector, &Dispatch);
@ -135,14 +132,8 @@ KiConnectVectorToInterrupt(IN PKINTERRUPT Interrupt,
Handler = (PVOID)&Interrupt->DispatchCode;
}
/* Get the IDT entry for this vector */
Entry = HalVectorToIDTEntry(Interrupt->Vector);
/* Set the pointer in the IDT */
((PKIPCR)KeGetPcr())->IDT[Entry].ExtendedOffset =
(USHORT)(((ULONG_PTR)Handler >> 16) & 0xFFFF);
((PKIPCR)KeGetPcr())->IDT[Entry].Offset =
(USHORT)PtrToUlong(Handler);
/* Register the interrupt */
KeRegisterInterruptHandler(Interrupt->Vector, Handler);
}
/* PUBLIC FUNCTIONS **********************************************************/