15#include "CommonHeader.h"
17#define EXCEPTION_VECTOR_NUMBER 0x22
20#define IA32_PG_RW BIT1
21#define IA32_PG_PS BIT7
24 BOOLEAN Page1GSupport;
26 UINTN PageFaultBuffer;
28 UINT64 AddressEncMask;
32 UINT64 *PageFaultUplink[EXTRA_PAGE_TABLE_PAGES];
33 VOID *OriginalHandler;
38 IA32_IDT_GATE_DESCRIPTOR IdtEntryTable[EXCEPTION_VECTOR_NUMBER];
60 IN OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
65 UINT8 PhysicalAddressBits;
66 UINTN PageFaultHandlerHookAddress;
69 if (RegEax >= 0x80000008) {
71 PhysicalAddressBits = (UINT8)RegEax;
73 PhysicalAddressBits = 36;
76 PageFaultContext->PhyMask =
LShiftU64 (1, PhysicalAddressBits) - 1;
77 PageFaultContext->PhyMask &= (1ull << 48) - SIZE_4KB;
83 PageFaultContext->OriginalHandler = (VOID *)(
UINTN)(
LShiftU64 (IdtEntry->Bits.OffsetUpper, 32) + IdtEntry->Bits.OffsetLow + (IdtEntry->Bits.OffsetHigh << 16));
84 IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;
85 IdtEntry->Bits.Selector = (UINT16)
AsmReadCs ();
86 IdtEntry->Bits.Reserved_0 = 0;
87 IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
88 IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);
89 IdtEntry->Bits.OffsetUpper = (UINT32)(PageFaultHandlerHookAddress >> 32);
90 IdtEntry->Bits.Reserved_1 = 0;
92 if (PageFaultContext->Page1GSupport) {
98 PageFaultContext->PageFaultIndex = 0;
99 ZeroMem (PageFaultContext->PageFaultUplink, sizeof (PageFaultContext->PageFaultUplink));
112 IN OUT UINT64 *Uplink
116 UINT64 AddressEncMask;
118 Address = PageFaultContext->PageFaultBuffer +
EFI_PAGES_TO_SIZE (PageFaultContext->PageFaultIndex);
121 AddressEncMask = PageFaultContext->AddressEncMask;
126 if ((PageFaultContext->PageFaultUplink[PageFaultContext->PageFaultIndex] !=
NULL) &&
127 ((*PageFaultContext->PageFaultUplink[PageFaultContext->PageFaultIndex] & ~AddressEncMask & PageFaultContext->PhyMask) == Address))
129 *PageFaultContext->PageFaultUplink[PageFaultContext->PageFaultIndex] = 0;
135 *Uplink = Address | AddressEncMask | IA32_PG_P | IA32_PG_RW;
136 PageFaultContext->PageFaultUplink[PageFaultContext->PageFaultIndex] = Uplink;
138 PageFaultContext->PageFaultIndex = (PageFaultContext->PageFaultIndex + 1) % EXTRA_PAGE_TABLE_PAGES;
154 IA32_DESCRIPTOR Idtr;
160 UINT64 AddressEncMask;
170 PhyMask = PageFaultContext->PhyMask;
171 AddressEncMask = PageFaultContext->AddressEncMask;
174 DEBUG ((DEBUG_ERROR,
"CapsuleX64 - PageFaultHandler: Cr2 - %lx\n", PFAddress));
176 if (PFAddress >= PhyMask + SIZE_4KB) {
177 return PageFaultContext->OriginalHandler;
180 PFAddress &= PhyMask;
186 if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
187 AcquirePage (PageFaultContext, &PageTable[PTIndex]);
190 PageTable = (UINT64 *)(
UINTN)(PageTable[PTIndex] & ~AddressEncMask & PhyMask);
193 if (PageFaultContext->Page1GSupport) {
194 PageTable[PTIndex] = ((PFAddress | AddressEncMask) & ~((1ull << 30) - 1)) | IA32_PG_P | IA32_PG_RW | IA32_PG_PS;
196 if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
197 AcquirePage (PageFaultContext, &PageTable[PTIndex]);
200 PageTable = (UINT64 *)(
UINTN)(PageTable[PTIndex] & ~AddressEncMask & PhyMask);
203 PageTable[PTIndex] = ((PFAddress | AddressEncMask) & ~((1ull << 21) - 1)) | IA32_PG_P | IA32_PG_RW | IA32_PG_PS;
222 SWITCH_32_TO_64_CONTEXT *EntrypointContext,
223 SWITCH_64_TO_32_CONTEXT *ReturnContext
227 IA32_DESCRIPTOR Ia32Idtr;
228 IA32_DESCRIPTOR X64Idtr;
230 IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
240 ZeroMem (PageFaultIdtTable.IdtEntryTable, sizeof (IA32_IDT_GATE_DESCRIPTOR) * EXCEPTION_VECTOR_NUMBER);
241 X64Idtr.Base = (
UINTN)PageFaultIdtTable.IdtEntryTable;
242 X64Idtr.Limit = (UINT16)(
sizeof (IA32_IDT_GATE_DESCRIPTOR) * EXCEPTION_VECTOR_NUMBER - 1);
248 Status = InitializeCpuExceptionHandlers (
NULL);
254 PageFaultIdtTable.PageFaultContext.Page1GSupport = EntrypointContext->Page1GSupport;
255 PageFaultIdtTable.PageFaultContext.AddressEncMask = EntrypointContext->AddressEncMask;
256 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)(X64Idtr.Base + (14 * sizeof (IA32_IDT_GATE_DESCRIPTOR)));
271 (VOID **)(
UINTN)EntrypointContext->MemoryBase64Ptr,
272 (
UINTN *)(
UINTN)EntrypointContext->MemorySize64Ptr
275 ReturnContext->ReturnStatus = Status;
279 "%a() Stack Base: 0x%lx, Stack Size: 0x%lx\n",
281 EntrypointContext->StackBufferBase,
282 EntrypointContext->StackBufferLength
298 ReturnContext->ReturnCs,
299 (UINT32)ReturnContext->ReturnEntryPoint,
300 (UINT32)(
UINTN)EntrypointContext,
301 (UINT32)(
UINTN)ReturnContext,
302 (UINT32)(EntrypointContext->StackBufferBase + EntrypointContext->StackBufferLength)
UINT64 EFIAPI BitFieldRead64(IN UINT64 Operand, IN UINTN StartBit, IN UINTN EndBit)
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS EFIAPI CapsuleDataCoalesce(IN EFI_PEI_SERVICES **PeiServices, IN EFI_PHYSICAL_ADDRESS *BlockListBuffer, IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource, IN OUT VOID **MemoryBase, IN OUT UINTN *MemorySize)
BOOLEAN EFIAPI SaveAndSetDebugTimerInterrupt(IN BOOLEAN EnableStatus)
VOID EFIAPI InitializeDebugAgent(IN UINT32 InitFlag, IN VOID *Context OPTIONAL, IN DEBUG_AGENT_CONTINUE Function OPTIONAL)
UINTN EFIAPI AsmReadCr3(VOID)
UINTN EFIAPI AsmReadCr2(VOID)
UINT16 EFIAPI AsmReadCs(VOID)
#define ASSERT_EFI_ERROR(StatusParameter)
#define DEBUG(Expression)
UINT32 EFIAPI AsmCpuid(IN UINT32 Index, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
UINT64 EFI_PHYSICAL_ADDRESS
#define EFI_PAGES_TO_SIZE(Pages)
VOID EFIAPI PageFaultHandlerHook(VOID)
VOID HookPageFaultHandler(IN OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry, IN OUT PAGE_FAULT_CONTEXT *PageFaultContext)
VOID AcquirePage(IN OUT PAGE_FAULT_CONTEXT *PageFaultContext, IN OUT UINT64 *Uplink)
EFI_STATUS EFIAPI _ModuleEntryPoint(SWITCH_32_TO_64_CONTEXT *EntrypointContext, SWITCH_64_TO_32_CONTEXT *ReturnContext)
VOID *EFIAPI PageFaultHandler(VOID)
VOID EFIAPI AsmDisablePaging64(IN UINT16 Cs, IN UINT32 EntryPoint, IN UINT32 Context1 OPTIONAL, IN UINT32 Context2 OPTIONAL, IN UINT32 NewStack)
VOID EFIAPI AsmReadIdtr(OUT IA32_DESCRIPTOR *Idtr)
VOID EFIAPI AsmWriteIdtr(IN CONST IA32_DESCRIPTOR *Idtr)