OvmfPkg/XenPlatformPei: Map extra physical address

Some information available in a Xen guest can be mapped anywhere in
the physical address space and they don't need to be backed by RAM.
For example, the shared info page.

While it's easier to put those pages anywhere, it is better to avoid
mapping it where the RAM is. It might split a nice 1G guest page table
into 4k pages and thus reducing performance of the guest when it
accesses its memory. Also mapping a page like the shared info page and
then unmapping it or mapping it somewhere else would leave a hole in
the RAM that the guest would propably not be able to use anymore.

So the patch introduces a new function which can be used to 1:1
mapping of guest physical memory above 4G during the PEI phase so we
can map the Xen shared pages outside of memory that can be used by
guest, and as high as possible.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20210412133003.146438-6-anthony.perard@citrix.com>
This commit is contained in:
Anthony PERARD 2021-04-12 14:30:01 +01:00 committed by mergify[bot]
parent 9d6861494a
commit 51e0bd28bb
3 changed files with 77 additions and 0 deletions

View File

@ -127,6 +127,11 @@ XenGetE820Map (
UINT32 *Count
);
EFI_STATUS
PhysicalAddressIdentityMapping (
IN EFI_PHYSICAL_ADDRESS AddressToMap
);
extern EFI_BOOT_MODE mBootMode;
extern UINT8 mPhysMemAddressWidth;

View File

@ -17,6 +17,8 @@
//
// The Library classes this module consumes
//
#include <Library/BaseMemoryLib.h>
#include <Library/CpuLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/MemoryAllocationLib.h>
@ -25,6 +27,7 @@
#include <IndustryStandard/E820.h>
#include <Library/ResourcePublicationLib.h>
#include <Library/MtrrLib.h>
#include <IndustryStandard/PageTable.h>
#include <IndustryStandard/Xen/arch-x86/hvm/start_info.h>
#include <Library/XenHypercallLib.h>
#include <IndustryStandard/Xen/memory.h>
@ -386,3 +389,71 @@ InitializeXen (
return EFI_SUCCESS;
}
EFI_STATUS
PhysicalAddressIdentityMapping (
IN EFI_PHYSICAL_ADDRESS AddressToMap
)
{
INTN Index;
PAGE_MAP_AND_DIRECTORY_POINTER *L4, *L3;
PAGE_TABLE_ENTRY *PageTable;
DEBUG ((DEBUG_INFO, "Mapping 1:1 of address 0x%lx\n", (UINT64)AddressToMap));
// L4 / Top level Page Directory Pointers
L4 = (VOID*)(UINTN)PcdGet32 (PcdOvmfSecPageTablesBase);
Index = PML4_OFFSET (AddressToMap);
if (!L4[Index].Bits.Present) {
L3 = AllocatePages (1);
if (L3 == NULL) {
return EFI_OUT_OF_RESOURCES;
}
ZeroMem (L3, EFI_PAGE_SIZE);
L4[Index].Bits.ReadWrite = 1;
L4[Index].Bits.Accessed = 1;
L4[Index].Bits.PageTableBaseAddress = (EFI_PHYSICAL_ADDRESS)L3 >> 12;
L4[Index].Bits.Present = 1;
}
// L3 / Next level Page Directory Pointers
L3 = (VOID*)(EFI_PHYSICAL_ADDRESS)(L4[Index].Bits.PageTableBaseAddress << 12);
Index = PDP_OFFSET (AddressToMap);
if (!L3[Index].Bits.Present) {
PageTable = AllocatePages (1);
if (PageTable == NULL) {
return EFI_OUT_OF_RESOURCES;
}
ZeroMem (PageTable, EFI_PAGE_SIZE);
L3[Index].Bits.ReadWrite = 1;
L3[Index].Bits.Accessed = 1;
L3[Index].Bits.PageTableBaseAddress = (EFI_PHYSICAL_ADDRESS)PageTable >> 12;
L3[Index].Bits.Present = 1;
}
// L2 / Page Table Entries
PageTable = (VOID*)(EFI_PHYSICAL_ADDRESS)(L3[Index].Bits.PageTableBaseAddress << 12);
Index = PDE_OFFSET (AddressToMap);
if (!PageTable[Index].Bits.Present) {
PageTable[Index].Bits.ReadWrite = 1;
PageTable[Index].Bits.Accessed = 1;
PageTable[Index].Bits.Dirty = 1;
PageTable[Index].Bits.MustBe1 = 1;
PageTable[Index].Bits.PageTableBaseAddress = AddressToMap >> 21;
PageTable[Index].Bits.Present = 1;
}
CpuFlushTlb ();
return EFI_SUCCESS;
}

View File

@ -66,6 +66,7 @@
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId