diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index bff1e266b7..c608cd4719 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -224,7 +224,7 @@ gEfiMdePkgTokenSpaceGuid.PcdImageProtectionPolicy ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio ## CONSUMES -[Pcd.IA32,Pcd.X64] +[Pcd.IA32, Pcd.X64] gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES diff --git a/MdeModulePkg/Core/Dxe/SysCall/IA32/CoreBootServices.nasm b/MdeModulePkg/Core/Dxe/SysCall/IA32/CoreBootServices.nasm index af51544705..3c26b07179 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/IA32/CoreBootServices.nasm +++ b/MdeModulePkg/Core/Dxe/SysCall/IA32/CoreBootServices.nasm @@ -98,6 +98,10 @@ copy: pop eax %endmacro +ALIGN 4096 +global ASM_PFX(SysCallBase) +ASM_PFX(SysCallBase): + ;------------------------------------------------------------------------------ ; EFI_STATUS ; EFIAPI @@ -119,6 +123,9 @@ ASM_PFX(CoreBootServices): push ebp push eax + mov eax, [ASM_PFX(gCorePageTable)] + mov cr3, eax + ; Switch from User to Core data segment selectors. mov ax, ss mov ds, ax @@ -147,6 +154,9 @@ ASM_PFX(CoreBootServices): SetRing3DataSegmentSelectors + mov eax, [ASM_PFX(gUserPageTable)] + mov cr3, eax + pop eax ; Step over User Arguments [1..3] and CallBootService input. @@ -194,10 +204,17 @@ ASM_PFX(CallRing3): ; Switch to User Stack. mov ebp, ecx + mov ebx, [ASM_PFX(gUserPageTable)] + mov cr3, ebx + ; Pass control to user image sti sysexit +ALIGN 4096 +global ASM_PFX(SysCallEnd) +ASM_PFX(SysCallEnd): + ;------------------------------------------------------------------------------ ; VOID ; EFIAPI @@ -219,5 +236,16 @@ ASM_PFX(ReturnToCore): ret SECTION .data +ALIGN 4096 + +global ASM_PFX(gCorePageTable) +ASM_PFX(gCorePageTable): + resd 1 + +global ASM_PFX(gUserPageTable) +ASM_PFX(gUserPageTable): + resd 1 + +ALIGN 4096 ASM_PFX(CoreEsp): resd 1 diff --git a/MdeModulePkg/Core/Dxe/SysCall/IA32/InitializeIA32.c b/MdeModulePkg/Core/Dxe/SysCall/IA32/InitializeIA32.c index 83b34b1d55..edc6bed78f 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/IA32/InitializeIA32.c +++ b/MdeModulePkg/Core/Dxe/SysCall/IA32/InitializeIA32.c @@ -8,6 +8,86 @@ #include "DxeMain.h" #include +#include + +VOID +EFIAPI +MakeUserPageTableTemplate ( + OUT VOID **UserPageTableTemplate, + OUT UINTN *UserPageTableTemplateSize + ) +{ + UINT8 PhysicalAddressBits; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + UINTN IndexOfPdpEntries; + UINTN IndexOfPageDirectoryEntries; + UINT32 NumberOfPdpEntriesNeeded; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMap; + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; + PAGE_TABLE_ENTRY *PageDirectoryEntry; + UINTN TotalPagesNum; + UINTN PageAddress; + UINT64 AddressEncMask; + + // + // Make sure AddressEncMask is contained to smallest supported address field + // + AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64; + + PhysicalAddressBits = 32; + + // + // Calculate the table entries needed. + // + NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30)); + + TotalPagesNum = NumberOfPdpEntriesNeeded + 1; + PageAddress = (UINTN)AllocateAlignedPages (TotalPagesNum, PAGE_TABLE_POOL_ALIGNMENT); + ASSERT (PageAddress != 0); + + PageMap = (VOID *)PageAddress; + PageAddress += SIZE_4KB; + + PageDirectoryPointerEntry = PageMap; + PhysicalAddress = 0; + + for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { + // + // Each Directory Pointer entries points to a page of Page Directory entires. + // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop. + // + PageDirectoryEntry = (VOID *)PageAddress; + PageAddress += SIZE_4KB; + + // + // Fill in a Page Directory Pointer Entries + // + PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry | AddressEncMask; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 = (UINT64)PhysicalAddress | AddressEncMask; + PageDirectoryEntry->Bits.ReadWrite = 1; + PageDirectoryEntry->Bits.Present = 0; + PageDirectoryEntry->Bits.MustBe1 = 1; + } + } + + for ( ; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { + ZeroMem ( + PageDirectoryPointerEntry, + sizeof (PAGE_MAP_AND_DIRECTORY_POINTER) + ); + } + + *UserPageTableTemplate = (VOID *)PageMap; + *UserPageTableTemplateSize = ALIGN_VALUE (EFI_PAGES_TO_SIZE (TotalPagesNum), PAGE_TABLE_POOL_ALIGNMENT); + + SetUefiImageMemoryAttributes ((UINT64)(UINTN)PageMap, *UserPageTableTemplateSize, EFI_MEMORY_XP); +} VOID EFIAPI @@ -25,6 +105,13 @@ InitializeMsr ( Ebx = 0; Edx = 0; + // + // Forbid global pages. + // + Cr4.UintN = AsmReadCr4 (); + Cr4.Bits.PGE = 0; + AsmWriteCr4 (Cr4.UintN); + // // Forbid supervisor-mode accesses to any user-mode pages. // @@ -70,4 +157,6 @@ InitializeMsr ( Msr = (UINT64)(UINTN)gCoreSysCallStackTop; AsmWriteMsr64 (MSR_IA32_SYSENTER_ESP, Msr); + + gCorePageTable = AsmReadCr3 (); } diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.nasm b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.nasm index b0cb2a9b4f..0c81564554 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.nasm +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.nasm @@ -23,16 +23,33 @@ ; ; CommonExceptionHandler() ; +extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions +extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag extern ASM_PFX(CommonExceptionHandler) SECTION .data +ALIGN 4096 -extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions -extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag +global ASM_PFX(CorePageTable) +ASM_PFX(CorePageTable): + resq 1 + +global ASM_PFX(UserPageTable) +ASM_PFX(UserPageTable): + resq 1 + +global ASM_PFX(mSwitchCr3Flag) +ASM_PFX(mSwitchCr3Flag): + db 0x0 + +ALIGN 4096 +Padding: + db 0x0 SECTION .text - -ALIGN 8 +ALIGN 4096 +global ASM_PFX(ExceptionHandlerBase) +ASM_PFX(ExceptionHandlerBase): ; ; exception handler stub table @@ -88,6 +105,14 @@ HookAfterStubHeaderEnd: global ASM_PFX(CommonInterruptEntry) ASM_PFX(CommonInterruptEntry): cli + cmp byte [ASM_PFX(mSwitchCr3Flag)], 0 + jz NoCr3Switch + mov eax, cr3 + mov [ASM_PFX(UserPageTable)], eax + mov eax, [ASM_PFX(CorePageTable)] + mov cr3, eax + +NoCr3Switch: pop eax ; ; All interrupt handlers are invoked through interrupt gates, so @@ -413,8 +438,8 @@ continue: push ecx mov ecx, ds and ecx, 3 - pop ecx jnz ReturnToRing3 + pop ecx pop dword [ebp - 8] pop dword [ebp - 4] @@ -444,11 +469,18 @@ DoReturn: DoIret: iretd ReturnToRing3: + mov ecx, [ASM_PFX(UserPageTable)] + mov cr3, ecx + pop ecx mov esp, ebp pop ebp add esp, 8 iretd +ALIGN 4096 +global ASM_PFX(ExceptionHandlerEnd) +ASM_PFX(ExceptionHandlerEnd): + ;---------------------------------------; ; _AsmGetTemplateAddressMap ; ;----------------------------------------------------------------------------;