mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
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:
parent
45316fbf63
commit
61df639e4a
5 changed files with 91 additions and 55 deletions
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 **********************************************************/
|
||||
|
|
Loading…
Reference in a new issue