diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index cdf04642a8..c2770575de 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -229,6 +229,7 @@ typedef struct { VOID *HiiData; BOOLEAN IsUserImage; + UINTN UserPageTable; } LOADED_IMAGE_PRIVATE_DATA; typedef struct { @@ -288,6 +289,10 @@ extern VOID *gCoreSysCallStackTop; extern VOID *gRing3CallStackBase; extern VOID *gRing3CallStackTop; extern VOID *gRing3EntryPoint; +extern VOID *gUserPageTableTemplate; +extern UINTN gUserPageTableTemplateSize; +extern UINTN gUserPageTable; +extern UINTN gCorePageTable; // // Service Initialization Functions @@ -2777,4 +2782,10 @@ FreeProtocolsList ( VOID ); +VOID +EFIAPI +MakeUserPageTableTemplate ( + VOID + ); + #endif diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index 7262cafecd..49327a9b09 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -150,6 +150,7 @@ gUefiImageLoaderImageContextGuid ## CONSUMES ## HOB gEfiGlobalVariableGuid ## SOMETIMES_CONSUMES ## SysCall gEarlyPL011BaseAddressGuid ## CONSUMES + gEfiHobPageTableInfoGuid ## CONSUMES ## HOB [Ppis] gEfiVectorHandoffInfoPpiGuid ## UNDEFINED # HOB diff --git a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c index e05c21392f..8c69e4da29 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c +++ b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c @@ -328,6 +328,8 @@ DxeMain ( ProtectUefiImage (&mCurrentImage->Info, UefiImageOriginFv, &ImageContext, mCurrentImage->IsUserImage); + MakeUserPageTableTemplate (); + // // Call constructor for all libraries // diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/Image/Image.c index e9d6776888..575fa12788 100644 --- a/MdeModulePkg/Core/Dxe/Image/Image.c +++ b/MdeModulePkg/Core/Dxe/Image/Image.c @@ -1108,6 +1108,7 @@ CoreLoadImageCommon ( UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext; UINT8 ImageOrigin; EFI_FV_FILE_ATTRIBUTES FileAttributes; + VOID *UserPageTable; SecurityStatus = EFI_SUCCESS; @@ -1348,6 +1349,14 @@ CoreLoadImageCommon ( Image->Info.ParentHandle = ParentImageHandle; Image->IsUserImage = (FileAttributes & EFI_FV_FILE_ATTRIB_USER) != 0; + if ((gRing3Data != NULL) && Image->IsUserImage) { + UserPageTable = AllocatePages (EFI_SIZE_TO_PAGES (gUserPageTableTemplateSize)); + CopyMem (UserPageTable, gUserPageTableTemplate, gUserPageTableTemplateSize); + + Image->UserPageTable = (UINTN)UserPageTable; + gUserPageTable = Image->UserPageTable; + } + if (NumberOfPages != NULL) { Image->NumberOfPages = *NumberOfPages; } else { diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c index 1dc47f9d00..d9ada48738 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c @@ -82,6 +82,10 @@ SetUefiImageMemoryAttributes ( ASSERT (gCpu != NULL); gCpu->SetMemoryAttributes (gCpu, BaseAddress, Length, FinalAttributes); + + if ((Attributes & EFI_MEMORY_USER) != 0) { + gCpu->SetUserMemoryAttributes (gCpu, gUserPageTable, BaseAddress, Length, FinalAttributes); + } } /** diff --git a/MdeModulePkg/Core/Dxe/SysCall/Initialization.c b/MdeModulePkg/Core/Dxe/SysCall/Initialization.c index 5ac1a7530b..dd2c9ccea3 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/Initialization.c +++ b/MdeModulePkg/Core/Dxe/SysCall/Initialization.c @@ -59,6 +59,12 @@ InitializeRing3 ( CopyMem ((VOID *)gRing3Data, (VOID *)Image->Info.SystemTable, sizeof (EFI_SYSTEM_TABLE)); + SetUefiImageMemoryAttributes ( + (UINTN)gRing3Data, + ALIGN_VALUE (sizeof (RING3_DATA), EFI_PAGE_SIZE), + EFI_MEMORY_XP | EFI_MEMORY_USER + ); + if (PcdGetBool (PcdSerialUseMmio)) { Status = CoreAllocatePages ( AllocateAnyPages, @@ -124,6 +130,12 @@ InitializeRing3 ( gRing3Interfaces = (VOID *)(UINTN)Physical; + SetUefiImageMemoryAttributes ( + (UINTN)gRing3Interfaces, + EFI_PAGES_TO_SIZE (RING3_INTERFACES_PAGES), + EFI_MEMORY_XP | EFI_MEMORY_USER + ); + SizeOfStack = EFI_SIZE_TO_PAGES (USER_STACK_SIZE) * EFI_PAGE_SIZE; // @@ -141,6 +153,9 @@ InitializeRing3 ( gCoreSysCallStackTop = TopOfStack; SetUefiImageMemoryAttributes ((UINTN)gCoreSysCallStackBase, SizeOfStack, EFI_MEMORY_XP); + // + // gCpu->SetUserMemoryAttributes (gCpu, gUserPageTable, (UINTN)gCoreSysCallStackBase, SizeOfStack, EFI_MEMORY_XP); + // DEBUG ((DEBUG_ERROR, "Core: gCoreSysCallStackTop = %p\n", gCoreSysCallStackTop)); // diff --git a/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm b/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm index ca65415006..8a36fd849b 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm +++ b/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm @@ -123,8 +123,13 @@ copy: ; ; (On User Stack) Argument 4, 5, ... ;------------------------------------------------------------------------------ +ALIGN 4096 + global ASM_PFX(CoreBootServices) ASM_PFX(CoreBootServices): + mov rax, [ASM_PFX(gCorePageTable)] + mov cr3, rax + ; Switch from User to Core data segment selectors. mov ax, ss mov ds, ax @@ -175,6 +180,8 @@ ASM_PFX(CoreBootServices): pop rbp pop rsp + mov rdx, [ASM_PFX(gUserPageTable)] + mov cr3, rdx ; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX. o64 sysret ; SYSRET copies the value in RCX into RIP and loads RFLAGS from R11. @@ -190,9 +197,9 @@ o64 sysret ;------------------------------------------------------------------------------ global ASM_PFX(CallRing3) ASM_PFX(CallRing3): + cli pushfq pop r11 - cli ; Save nonvolatile registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15. push rbx push rbp @@ -221,6 +228,8 @@ ASM_PFX(CallRing3): mov rsp, r8 mov rbp, rsp + mov r8, [ASM_PFX(gUserPageTable)] + mov cr3, r8 ; Pass control to user image o64 sysret @@ -248,5 +257,15 @@ ASM_PFX(ReturnToCore): ret SECTION .data +ALIGN 4096 + +global ASM_PFX(gCorePageTable) +ASM_PFX(gCorePageTable): + resq 1 + +global ASM_PFX(gUserPageTable) +ASM_PFX(gUserPageTable): + resq 1 + ASM_PFX(CoreRsp): resq 1 diff --git a/MdeModulePkg/Core/Dxe/SysCall/X64/InitializeMsr.c b/MdeModulePkg/Core/Dxe/SysCall/X64/InitializeMsr.c index 3126f09d12..7c0b84783f 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/X64/InitializeMsr.c +++ b/MdeModulePkg/Core/Dxe/SysCall/X64/InitializeMsr.c @@ -8,6 +8,202 @@ #include "DxeMain.h" #include +#include + +VOID *gUserPageTableTemplate; +UINTN gUserPageTableTemplateSize; + +VOID +EFIAPI +MakeUserPageTableTemplate ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + EFI_PAGE_TABLE_INFO *PageTableInfo; + UINTN BigPageAddress; + EFI_PHYSICAL_ADDRESS PageAddress; + UINTN IndexOfPml5Entries; + UINTN IndexOfPml4Entries; + UINTN IndexOfPdpEntries; + UINTN IndexOfPageDirectoryEntries; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel5Entry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMap; + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; + PAGE_TABLE_ENTRY *PageDirectoryEntry; + PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; + + GuidHob = GetFirstGuidHob (&gEfiHobPageTableInfoGuid); + if (GuidHob == NULL) { + DEBUG ((DEBUG_ERROR, "Core: Could not retrieve PageTableInfo HOB.\n")); + CpuDeadLoop (); + } + + PageTableInfo = (EFI_PAGE_TABLE_INFO *)(GET_GUID_HOB_DATA (GuidHob)); + + BigPageAddress = (UINTN)AllocateAlignedPages (PageTableInfo->TotalPagesNum, PAGE_TABLE_POOL_ALIGNMENT); + if (BigPageAddress == 0) { + DEBUG ((DEBUG_ERROR, "Core: Could not allocate buffer for User page table.\n")); + CpuDeadLoop (); + } + + // + // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. + // + PageMap = (VOID *)BigPageAddress; + if (PageTableInfo->Page5LevelEnabled) { + // + // By architecture only one PageMapLevel5 exists - so lets allocate storage for it. + // + PageMapLevel5Entry = PageMap; + BigPageAddress += SIZE_4KB; + } + + PageAddress = 0; + + for ( IndexOfPml5Entries = 0 + ; IndexOfPml5Entries < PageTableInfo->NumberOfPml5EntriesNeeded + ; IndexOfPml5Entries++) + { + // + // Each PML5 entry points to a page of PML4 entires. + // So lets allocate space for them and fill them in in the IndexOfPml4Entries loop. + // When 5-Level Paging is disabled, below allocation happens only once. + // + PageMapLevel4Entry = (VOID *)BigPageAddress; + BigPageAddress += SIZE_4KB; + + if (PageTableInfo->Page5LevelEnabled) { + // + // Make a PML5 Entry + // + PageMapLevel5Entry->Uint64 = (UINT64)(UINTN)PageMapLevel4Entry | PageTableInfo->AddressEncMask; + PageMapLevel5Entry->Bits.ReadWrite = 1; + PageMapLevel5Entry->Bits.UserSupervisor = 1; + PageMapLevel5Entry->Bits.Present = 1; + PageMapLevel5Entry++; + } + + for ( IndexOfPml4Entries = 0 + ; IndexOfPml4Entries < (PageTableInfo->NumberOfPml5EntriesNeeded == 1 ? PageTableInfo->NumberOfPml4EntriesNeeded : 512) + ; IndexOfPml4Entries++, PageMapLevel4Entry++) + { + // + // Each PML4 entry points to a page of Page Directory Pointer entires. + // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop. + // + PageDirectoryPointerEntry = (VOID *)BigPageAddress; + BigPageAddress += SIZE_4KB; + + // + // Make a PML4 Entry + // + PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry | PageTableInfo->AddressEncMask; + PageMapLevel4Entry->Bits.ReadWrite = 1; + PageMapLevel4Entry->Bits.UserSupervisor = 1; + PageMapLevel4Entry->Bits.Present = 1; + + if (PageTableInfo->Page1GSupport) { + PageDirectory1GEntry = (VOID *)PageDirectoryPointerEntry; + + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) { + // + // Fill in the Page Directory entries + // + PageDirectory1GEntry->Uint64 = (UINT64)PageAddress | PageTableInfo->AddressEncMask; + PageDirectory1GEntry->Bits.ReadWrite = 1; + PageDirectory1GEntry->Bits.Present = 1; + PageDirectory1GEntry->Bits.MustBe1 = 1; + } + } else { + for ( IndexOfPdpEntries = 0 + ; IndexOfPdpEntries < (PageTableInfo->NumberOfPml4EntriesNeeded == 1 ? PageTableInfo->NumberOfPdpEntriesNeeded : 512) + ; 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 *)BigPageAddress; + BigPageAddress += SIZE_4KB; + + // + // Fill in a Page Directory Pointer Entries + // + PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry | PageTableInfo->AddressEncMask; + PageDirectoryPointerEntry->Bits.ReadWrite = 1; + PageDirectoryPointerEntry->Bits.UserSupervisor = 1; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 = (UINT64)PageAddress | PageTableInfo->AddressEncMask; + PageDirectoryEntry->Bits.ReadWrite = 1; + PageDirectoryEntry->Bits.Present = 0; + PageDirectoryEntry->Bits.MustBe1 = 1; + } + } + + // + // Fill with null entry for unused PDPTE + // + ZeroMem (PageDirectoryPointerEntry, (512 - IndexOfPdpEntries) * sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)); + } + } + + // + // For the PML4 entries we are not using fill in a null entry. + // + ZeroMem (PageMapLevel4Entry, (512 - IndexOfPml4Entries) * sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)); + } + + if (PageTableInfo->Page5LevelEnabled) { + // + // For the PML5 entries we are not using fill in a null entry. + // + ZeroMem (PageMapLevel5Entry, (512 - IndexOfPml5Entries) * sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)); + } + + gUserPageTableTemplate = (VOID *)PageMap; + gUserPageTableTemplateSize = ALIGN_VALUE (EFI_PAGES_TO_SIZE (PageTableInfo->TotalPagesNum), PAGE_TABLE_POOL_ALIGNMENT); + gUserPageTable = (UINTN)gUserPageTableTemplate; + + SetUefiImageMemoryAttributes ((UINT64)PageMap, gUserPageTableTemplateSize, EFI_MEMORY_XP); + // + // Map CoreBootServices + // + gCpu->SetUserMemoryAttributes ( + gCpu, + (UINTN)PageMap, + (EFI_PHYSICAL_ADDRESS)(UINTN)CoreBootServices, + SIZE_4KB, + EFI_MEMORY_RO + ); + + gCpu->SetUserMemoryAttributes ( + gCpu, + (UINTN)PageMap, + (EFI_PHYSICAL_ADDRESS)(UINTN)&gCorePageTable, + SIZE_4KB, + EFI_MEMORY_RO | EFI_MEMORY_XP + ); + // + // Map ExceptionHandlerAsm: AsmIdtVectorBegin - AsmGetTemplateAddressMap + // mCorePageTable, gCoreSysCallStackTop + // + // gCpu->SetUserMemoryAttributes (gCpu, (UINTN)PageMap, BaseAddress, SIZE_4KB, EFI_MEMORY_RO); + + gCpu->SetUserMemoryAttributes ( + gCpu, + (UINTN)PageMap, + FixedPcdGet32 (PcdOvmfWorkAreaBase), + FixedPcdGet32 (PcdOvmfWorkAreaSize), + EFI_MEMORY_XP | EFI_MEMORY_USER + ); +} VOID EFIAPI @@ -26,6 +222,9 @@ InitializeMsr ( Ebx = 0; Edx = 0; + // The Intel-64 and IA-32 architectures also allow for global pages when the PGE flag (bit 7) is 1 in CR4. + // PGE must be zero. + // // Forbid supervisor-mode accesses to any user-mode pages. // @@ -76,4 +275,6 @@ InitializeMsr ( // Msr = (UINT64)BIT9; AsmWriteMsr64 (MSR_IA32_FMASK, Msr); + + gCorePageTable = AsmReadCr3 (); } diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf index e231e7bd6f..8a4d0eeab4 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -90,6 +90,7 @@ ## SOMETIMES_PRODUCES ## HOB gEfiMemoryTypeInformationGuid gUefiImageLoaderImageContextGuid + gEfiHobPageTableInfoGuid [FeaturePcd.IA32] gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c index d014c95348..c35e6353d5 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c @@ -705,6 +705,7 @@ CreateIdentityMappingPageTables ( PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; UINT64 AddressEncMask; IA32_CR4 Cr4; + EFI_PAGE_TABLE_INFO PageTableInfo; // // Set PageMapLevel5Entry to suppress incorrect compiler/analyzer warnings @@ -828,6 +829,16 @@ CreateIdentityMappingPageTables ( (UINT64)TotalPagesNum )); + PageTableInfo.NumberOfPml5EntriesNeeded = NumberOfPml5EntriesNeeded; + PageTableInfo.NumberOfPml4EntriesNeeded = NumberOfPml4EntriesNeeded; + PageTableInfo.NumberOfPdpEntriesNeeded = NumberOfPdpEntriesNeeded; + PageTableInfo.TotalPagesNum = TotalPagesNum; + PageTableInfo.Page5LevelEnabled = Page5LevelEnabled; + PageTableInfo.Page1GSupport = Page1GSupport; + PageTableInfo.AddressEncMask = AddressEncMask; + + BuildGuidDataHob (&gEfiHobPageTableInfoGuid, &PageTableInfo, sizeof (EFI_PAGE_TABLE_INFO)); + BigPageAddress = (UINTN)AllocatePageTableMemory (TotalPagesNum); ASSERT (BigPageAddress != 0); diff --git a/MdePkg/Include/Guid/MemoryAllocationHob.h b/MdePkg/Include/Guid/MemoryAllocationHob.h index e4c57bf1ac..9ebbd13992 100644 --- a/MdePkg/Include/Guid/MemoryAllocationHob.h +++ b/MdePkg/Include/Guid/MemoryAllocationHob.h @@ -21,8 +21,12 @@ #define EFI_HOB_MEMORY_ALLOC_MODULE_GUID \ {0xf8e21975, 0x899, 0x4f58, {0xa4, 0xbe, 0x55, 0x25, 0xa9, 0xc6, 0xd7, 0x7a} } +#define EFI_HOB_PAGE_TABLE_INFO_GUID \ + {0xac992fe9, 0xb0cc, 0x45df, {0xae, 0xcf, 0x51, 0x5a, 0xd2, 0xc4, 0xe8, 0xb3} } + extern EFI_GUID gEfiHobMemoryAllocBspStoreGuid; extern EFI_GUID gEfiHobMemoryAllocStackGuid; extern EFI_GUID gEfiHobMemoryAllocModuleGuid; +extern EFI_GUID gEfiHobPageTableInfoGuid; #endif diff --git a/MdePkg/Include/Library/MemoryAllocationLib.h b/MdePkg/Include/Library/MemoryAllocationLib.h index 59d4b29c44..da7ac36b2f 100644 --- a/MdePkg/Include/Library/MemoryAllocationLib.h +++ b/MdePkg/Include/Library/MemoryAllocationLib.h @@ -14,6 +14,16 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #ifndef __MEMORY_ALLOCATION_LIB_H__ #define __MEMORY_ALLOCATION_LIB_H__ +typedef struct { + UINT32 NumberOfPml5EntriesNeeded; + UINT32 NumberOfPml4EntriesNeeded; + UINT32 NumberOfPdpEntriesNeeded; + UINTN TotalPagesNum; + BOOLEAN Page5LevelEnabled; + BOOLEAN Page1GSupport; + UINT64 AddressEncMask; +} EFI_PAGE_TABLE_INFO; + /** Allocates one or more 4KB pages of type EfiBootServicesData. diff --git a/MdePkg/Include/Protocol/Cpu.h b/MdePkg/Include/Protocol/Cpu.h index ccaec43cb4..cf263ce019 100644 --- a/MdePkg/Include/Protocol/Cpu.h +++ b/MdePkg/Include/Protocol/Cpu.h @@ -258,6 +258,16 @@ EFI_STATUS OUT UINT64 *Attributes ); +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_SET_USER_MEMORY_ATTRIBUTES)( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINTN UserPageTable, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + /// /// The EFI_CPU_ARCH_PROTOCOL is used to abstract processor-specific functions from the DXE /// Foundation. This includes flushing caches, enabling and disabling interrupts, hooking interrupt @@ -288,6 +298,7 @@ struct _EFI_CPU_ARCH_PROTOCOL { /// UINT32 DmaBufferAlignment; EFI_CPU_GET_MEMORY_ATTRIBUTES GetMemoryAttributes; + EFI_CPU_SET_USER_MEMORY_ATTRIBUTES SetUserMemoryAttributes; }; extern EFI_GUID gEfiCpuArchProtocolGuid; diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index 84f416b466..fc0ef3deef 100644 --- a/MdePkg/MdePkg.dec +++ b/MdePkg/MdePkg.dec @@ -781,6 +781,9 @@ ## Include/Guid/MemoryAllocationHob.h gEfiHobMemoryAllocBspStoreGuid = { 0x564B33CD, 0xC92A, 0x4593, { 0x90, 0xBF, 0x24, 0x73, 0xE4, 0x3C, 0x63, 0x22 }} + ## Include/Guid/MemoryAllocationHob.h + gEfiHobPageTableInfoGuid = { 0xAC992FE9, 0xB0CC, 0x45DF, { 0xAE, 0xCF, 0x51, 0x5A, 0xD2, 0xC4, 0xE8, 0xB3 }} + ## Include/Guid/EventLegacyBios.h gEfiEventLegacyBootGuid = { 0x2A571201, 0x4966, 0x47F6, { 0x8B, 0x86, 0xF3, 0x1E, 0x41, 0xF3, 0x2F, 0x10 }} diff --git a/OvmfPkg/Include/IndustryStandard/PageTable.h b/OvmfPkg/Include/IndustryStandard/PageTable.h index a75b3fcfe7..d9a1195c04 100644 --- a/OvmfPkg/Include/IndustryStandard/PageTable.h +++ b/OvmfPkg/Include/IndustryStandard/PageTable.h @@ -158,4 +158,6 @@ typedef union { #define PTE_OFFSET(x) ( (x >> 12) & PAGETABLE_ENTRY_MASK) #define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull +#define PAGE_TABLE_POOL_ALIGNMENT BASE_2MB + #endif diff --git a/UefiCpuPkg/Library/CpuArchLib/CpuDxe.c b/UefiCpuPkg/Library/CpuArchLib/CpuDxe.c index f9fbe05c8d..b7ee3cd877 100644 --- a/UefiCpuPkg/Library/CpuArchLib/CpuDxe.c +++ b/UefiCpuPkg/Library/CpuArchLib/CpuDxe.c @@ -32,7 +32,8 @@ EFI_CPU_ARCH_PROTOCOL gCpuImpl = { CpuSetMemoryAttributes, 1, // NumberOfTimers 4, // DmaBufferAlignment - CpuGetMemoryAttributes + CpuGetMemoryAttributes, + CpuSetUserMemoryAttributes }; EFI_HOB_PLATFORM_INFO *mPlatformInfoHob2 = NULL; diff --git a/UefiCpuPkg/Library/CpuArchLib/CpuDxe.h b/UefiCpuPkg/Library/CpuArchLib/CpuDxe.h index 731dbd6d13..1ec897f1d9 100644 --- a/UefiCpuPkg/Library/CpuArchLib/CpuDxe.h +++ b/UefiCpuPkg/Library/CpuArchLib/CpuDxe.h @@ -229,6 +229,16 @@ CpuGetMemoryAttributes ( OUT UINT64 *Attributes ); +EFI_STATUS +EFIAPI +CpuSetUserMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINTN UserPageTable, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + /** Initialize Global Descriptor Table. diff --git a/UefiCpuPkg/Library/CpuArchLib/CpuPageTable.c b/UefiCpuPkg/Library/CpuArchLib/CpuPageTable.c index f889efe3d0..ddc4da3c82 100644 --- a/UefiCpuPkg/Library/CpuArchLib/CpuPageTable.c +++ b/UefiCpuPkg/Library/CpuArchLib/CpuPageTable.c @@ -429,6 +429,35 @@ CpuGetMemoryAttributes ( return EFI_SUCCESS; } +EFI_STATUS +EFIAPI +CpuSetUserMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINTN UserPageTable, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +{ + UINT64 MemoryAttributes; + PAGE_TABLE_LIB_PAGING_CONTEXT PagingContext; + + MemoryAttributes = Attributes & EFI_MEMORY_ATTRIBUTE_MASK; + + GetCurrentPagingContext (&PagingContext); + + if (PagingContext.MachineType == IMAGE_FILE_MACHINE_I386) { + PagingContext.ContextData.Ia32.PageTableBase = (UINT32)UserPageTable; + } else { + PagingContext.ContextData.X64.PageTableBase = (UINT64)UserPageTable; + } + + // + // Set memory attribute by page table + // + return AssignMemoryPageAttributes (&PagingContext, BaseAddress, Length, MemoryAttributes, AllocatePages); +} + /** Modify memory attributes of page entry.