+\r
+#define IA32_PG_P BIT0\r
+#define IA32_PG_RW BIT1\r
+#define IA32_PG_PS BIT7\r
+\r
+UINT64 mPhyMask;\r
+BOOLEAN mPage1GSupport;\r
+VOID *mOriginalHandler;\r
+UINTN mS3NvsPageTableAddress;\r
+\r
+VOID\r
+EFIAPI\r
+PageFaultHandlerHook (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+HookPageFaultHandler (\r
+ IN INTERRUPT_GATE_DESCRIPTOR *IdtEntry\r
+ )\r
+{\r
+ UINT32 RegEax;\r
+ UINT32 RegEdx;\r
+\r
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+ mPhyMask = LShiftU64 (1, (UINT8)RegEax) - 1;\r
+ mPhyMask &= (1ull << 48) - SIZE_4KB;\r
+\r
+ mPage1GSupport = FALSE;\r
+ if (PcdGetBool(PcdUse1GPageTable)) {\r
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+ if (RegEax >= 0x80000001) {\r
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
+ if ((RegEdx & BIT26) != 0) {\r
+ mPage1GSupport = TRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Set Page Fault entry to catch >4G access\r
+ //\r
+ mOriginalHandler = (VOID *)(UINTN)(LShiftU64 (IdtEntry->Offset63To32, 32) + IdtEntry->Offset15To0 + (IdtEntry->Offset31To16 << 16));\r
+ IdtEntry->Offset15To0 = (UINT16)((UINTN)PageFaultHandlerHook);\r
+ IdtEntry->SegmentSelector = (UINT16)AsmReadCs ();\r
+ IdtEntry->Attributes = (UINT16)INTERRUPT_GATE_ATTRIBUTE;\r
+ IdtEntry->Offset31To16 = (UINT16)((UINTN)PageFaultHandlerHook >> 16);\r
+ IdtEntry->Offset63To32 = (UINT32)((UINTN)PageFaultHandlerHook >> 32);\r
+ IdtEntry->Reserved = 0;\r
+\r
+ if (mPage1GSupport) {\r
+ mS3NvsPageTableAddress = (UINTN)(AsmReadCr3 () & mPhyMask) + EFI_PAGES_TO_SIZE(2);\r
+ }else {\r
+ mS3NvsPageTableAddress = (UINTN)(AsmReadCr3 () & mPhyMask) + EFI_PAGES_TO_SIZE(6);\r
+ }\r
+}\r
+\r