From: Dov Murik <dovmurik@linux.ibm.com>
The migration handler builds its own page tables and switches
to them. The MH pagetables are reserved as runtime memory.
When the hypervisor asks the MH to import/export a page, the HV
writes the guest physical address of the page in question to the
mailbox. The MH uses an identity mapping so that it can read/write
whatever GPA is requested by the HV. The hypervisor only asks the
MH to import/export encrypted pages. Thus, the C-Bit can be set
for every page in the identity map.
The MH also needs to read shared pages, such as the mailbox.
These are mapped at an offset. The offset must be added to
the physical address before it can be resolved.
Signed-off-by: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>
Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
---
.../ConfidentialMigrationDxe.inf | 1 +
.../ConfidentialMigration/VirtualMemory.h | 177 ++++++++++++++++++
.../ConfidentialMigrationDxe.c | 88 ++++++++-
3 files changed, 265 insertions(+), 1 deletion(-)
create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h
diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf
index 49457d5d17..8dadfd1d13 100644
--- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf
+++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf
@@ -15,6 +15,7 @@
[Sources]
ConfidentialMigrationDxe.c
+ VirtualMemory.h
[Packages]
MdePkg/MdePkg.dec
diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h b/OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h
new file mode 100644
index 0000000000..c50cb64c63
--- /dev/null
+++ b/OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h
@@ -0,0 +1,177 @@
+/** @file
+ Virtual Memory Management Services to set or clear the memory encryption bit
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ Code is derived from OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
+
+**/
+
+#ifndef __VIRTUAL_MEMORY__
+#define __VIRTUAL_MEMORY__
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Uefi.h>
+
+#define SYS_CODE64_SEL 0x38
+
+#pragma pack(1)
+
+//
+// Page-Map Level-4 Offset (PML4) and
+// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
+//
+
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory,
+ // 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching,
+ // 1 = Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed,
+ // 1 = Accessed (set by CPU)
+ UINT64 Reserved:1; // Reserved
+ UINT64 MustBeZero:2; // Must Be Zero
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} PAGE_MAP_AND_DIRECTORY_POINTER;
+
+//
+// Page Table Entry 4KB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory,
+ // 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching,
+ // 1 = Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed,
+ // 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
+ // processor on access to page
+ UINT64 PAT:1; //
+ UINT64 Global:1; // 0 = Not global page, 1 = global page
+ // TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code,
+ // 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_4K_ENTRY;
+
+//
+// Page Table Entry 2MB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory,
+ // 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching,
+ // 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed,
+ // 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
+ // processor on access to page
+ UINT64 MustBe1:1; // Must be 1
+ UINT64 Global:1; // 0 = Not global page, 1 = global page
+ // TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PAT:1; //
+ UINT64 MustBeZero:8; // Must be zero;
+ UINT64 PageTableBaseAddress:31; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code,
+ // 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_ENTRY;
+
+//
+// Page Table Entry 1GB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory,
+ // 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching,
+ // 1 = Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed,
+ // 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
+ // processor on access to page
+ UINT64 MustBe1:1; // Must be 1
+ UINT64 Global:1; // 0 = Not global page, 1 = global page
+ // TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PAT:1; //
+ UINT64 MustBeZero:17; // Must be zero;
+ UINT64 PageTableBaseAddress:22; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code,
+ // 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_1G_ENTRY;
+
+#pragma pack()
+
+#define IA32_PG_P BIT0
+#define IA32_PG_RW BIT1
+#define IA32_PG_PS BIT7
+
+#define PAGING_PAE_INDEX_MASK 0x1FF
+
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
+#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
+
+#define PAGING_L1_ADDRESS_SHIFT 12
+#define PAGING_L2_ADDRESS_SHIFT 21
+#define PAGING_L3_ADDRESS_SHIFT 30
+#define PAGING_L4_ADDRESS_SHIFT 39
+
+#define PAGING_PML4E_NUMBER 4
+
+#define PAGETABLE_ENTRY_MASK ((1UL << 9) - 1)
+#define PML4_OFFSET(x) ( (x >> 39) & PAGETABLE_ENTRY_MASK)
+#define PDP_OFFSET(x) ( (x >> 30) & PAGETABLE_ENTRY_MASK)
+#define PDE_OFFSET(x) ( (x >> 21) & PAGETABLE_ENTRY_MASK)
+#define PTE_OFFSET(x) ( (x >> 12) & PAGETABLE_ENTRY_MASK)
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
+
+#define PAGE_TABLE_POOL_ALIGNMENT BASE_2MB
+#define PAGE_TABLE_POOL_UNIT_SIZE SIZE_2MB
+#define PAGE_TABLE_POOL_UNIT_PAGES \
+ EFI_SIZE_TO_PAGES (PAGE_TABLE_POOL_UNIT_SIZE)
+#define PAGE_TABLE_POOL_ALIGN_MASK \
+ (~(EFI_PHYSICAL_ADDRESS)(PAGE_TABLE_POOL_ALIGNMENT - 1))
+
+typedef struct {
+ VOID *NextPool;
+ UINTN Offset;
+ UINTN FreePages;
+} PAGE_TABLE_POOL;
+
+#endif
diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c
index 8402fcc4fa..3df3b09732 100644
--- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c
+++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c
@@ -11,6 +11,7 @@
#include <Protocol/MpService.h>
#include <Library/BaseMemoryLib.h>
+#include "VirtualMemory.h"
//
// Functions implemented by the migration handler
//
@@ -43,6 +44,83 @@ typedef volatile struct {
UINT32 done;
} MH_COMMAND_PARAMETERS;
+//
+// Addresses for MH page table.
+//
+STATIC PAGE_TABLE_POOL *mPageTablePool = NULL;
+STATIC PHYSICAL_ADDRESS mMigrationHelperPageTables = 0;
+
+//
+// Offset for non-cbit mapping.
+//
+#define UNENC_VIRT_ADDR_BASE 0xffffff8000000000ULL
+
+
+/**
+ Allocates and fills in custom page tables for Migration Handler.
+ The MH must be able to write to any encrypted page. Thus, it
+ uses an identity map where the C-bit is set for every page. The
+ HV should never ask the MH to import/export a shared page. The
+ MH must also be able to read some shared pages. The first 1GB
+ of memory is mapped at offset UNENC_VIRT_ADDR_BASE.
+
+**/
+VOID
+PrepareMigrationHandlerPageTables (
+ VOID
+ )
+{
+ UINTN PoolPages;
+ VOID *Buffer;
+ VOID *Start;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
+ PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
+ PAGE_TABLE_1G_ENTRY *Unenc1GEntry;
+ UINT64 AddressEncMask;
+
+ PoolPages = 1 + 10;
+ Buffer = AllocateAlignedRuntimePages (PoolPages, PAGE_TABLE_POOL_ALIGNMENT);
+ mPageTablePool = Buffer;
+ mPageTablePool->NextPool = mPageTablePool;
+ mPageTablePool->FreePages = PoolPages - 1;
+ mPageTablePool->Offset = EFI_PAGES_TO_SIZE (1);
+
+ Start = (UINT8 *)mPageTablePool + mPageTablePool->Offset;
+ ZeroMem(Start, mPageTablePool->FreePages * EFI_PAGE_SIZE);
+
+ AddressEncMask = 1ULL << 47;
+
+ PageMapLevel4Entry = Start;
+ PageDirectory1GEntry = (PAGE_TABLE_1G_ENTRY*)((UINT8*)Start + EFI_PAGE_SIZE);
+ Unenc1GEntry = (PAGE_TABLE_1G_ENTRY*)((UINT8*)Start + 2 * EFI_PAGE_SIZE);
+
+ PageMapLevel4Entry = Start;
+ PageMapLevel4Entry += PML4_OFFSET(0x0ULL);
+ PageMapLevel4Entry->Uint64 = (UINT64)PageDirectory1GEntry | AddressEncMask | 0x23;
+
+ PageMapLevel4Entry = Start;
+ PageMapLevel4Entry += PML4_OFFSET(UNENC_VIRT_ADDR_BASE); // should be 511
+ PageMapLevel4Entry->Uint64 = (UINT64)Unenc1GEntry | AddressEncMask | 0x23;
+
+ UINT64 PageAddr = 0;
+ for (int i = 0; i < 512; i++, PageAddr += SIZE_1GB) {
+ PAGE_TABLE_1G_ENTRY *e = PageDirectory1GEntry + i;
+ e->Uint64 = PageAddr | AddressEncMask | 0xe3; // 1GB page
+ }
+
+ UINT64 UnencPageAddr = 0;
+ Unenc1GEntry->Uint64 = UnencPageAddr | 0xe3; // 1GB page unencrypted
+
+ mMigrationHelperPageTables = (UINT64)Start | AddressEncMask;
+}
+
+VOID
+SwitchToMigrationHelperPageTables(VOID)
+{
+ AsmWriteCr3(mMigrationHelperPageTables);
+}
+
+
VOID
EFIAPI
@@ -56,7 +134,12 @@ MigrationHandlerMain (
DebugPrint (DEBUG_INFO,"MIGRATION Handler Started\n");
- params_base = PcdGet32 (PcdConfidentialMigrationMailboxBase);
+ SwitchToMigrationHelperPageTables();
+
+ //
+ // Shared pages must be offset by UNENC_VIRT_ADDR_BASE.
+ //
+ params_base = PcdGet32 (PcdConfidentialMigrationMailboxBase) + UNENC_VIRT_ADDR_BASE;
params = (VOID *)params_base;
page_va = (VOID *)params_base + 0x1000;
@@ -134,6 +217,8 @@ LaunchMigrationHandler (
MigrationHandlerCpuIndex = NumProc - 1;
+ PrepareMigrationHandlerPageTables();
+
EFI_EVENT Event;
MpProto->GetProcessorInfo (MpProto, MigrationHandlerCpuIndex, &Tcb);
if (Tcb.StatusFlag != 7) {
@@ -154,6 +239,7 @@ LaunchMigrationHandler (
if (PcdGetBool(PcdIsConfidentialMigrationTarget)) {
DebugPrint (DEBUG_INFO,"Waiting for incoming confidential migration.\n");
DisableInterrupts ();
+ SwitchToMigrationHelperPageTables();
CpuDeadLoop ();
}
--
2.20.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#72364): https://edk2.groups.io/g/devel/message/72364
Mute This Topic: https://groups.io/mt/81036386/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
On Tue, Mar 02, 2021 at 03:48:36PM -0500, Tobin Feldman-Fitzthum wrote:
> From: Dov Murik <dovmurik@linux.ibm.com>
>
> The migration handler builds its own page tables and switches
> to them. The MH pagetables are reserved as runtime memory.
>
> When the hypervisor asks the MH to import/export a page, the HV
> writes the guest physical address of the page in question to the
> mailbox. The MH uses an identity mapping so that it can read/write
> whatever GPA is requested by the HV. The hypervisor only asks the
> MH to import/export encrypted pages. Thus, the C-Bit can be set
> for every page in the identity map.
>
> The MH also needs to read shared pages, such as the mailbox.
> These are mapped at an offset. The offset must be added to
> the physical address before it can be resolved.
>
> Signed-off-by: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>
> Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
> ---
> .../ConfidentialMigrationDxe.inf | 1 +
> .../ConfidentialMigration/VirtualMemory.h | 177 ++++++++++++++++++
> .../ConfidentialMigrationDxe.c | 88 ++++++++-
> 3 files changed, 265 insertions(+), 1 deletion(-)
> create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h
>
> diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf
> index 49457d5d17..8dadfd1d13 100644
> --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf
> +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf
> @@ -15,6 +15,7 @@
>
> [Sources]
> ConfidentialMigrationDxe.c
> + VirtualMemory.h
>
> [Packages]
> MdePkg/MdePkg.dec
> diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h b/OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h
> new file mode 100644
> index 0000000000..c50cb64c63
> --- /dev/null
> +++ b/OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h
> @@ -0,0 +1,177 @@
> +/** @file
> + Virtual Memory Management Services to set or clear the memory encryption bit
> + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
> + Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> + Code is derived from OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
> +
> +**/
> +
> +#ifndef __VIRTUAL_MEMORY__
> +#define __VIRTUAL_MEMORY__
> +
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/CacheMaintenanceLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Uefi.h>
> +
> +#define SYS_CODE64_SEL 0x38
> +
> +#pragma pack(1)
> +
> +//
> +// Page-Map Level-4 Offset (PML4) and
> +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
> +//
> +
> +typedef union {
> + struct {
> + UINT64 Present:1; // 0 = Not present in memory,
> + // 1 = Present in memory
> + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
> + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
> + UINT64 WriteThrough:1; // 0 = Write-Back caching,
> + // 1 = Write-Through caching
> + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
> + UINT64 Accessed:1; // 0 = Not accessed,
> + // 1 = Accessed (set by CPU)
> + UINT64 Reserved:1; // Reserved
> + UINT64 MustBeZero:2; // Must Be Zero
> + UINT64 Available:3; // Available for use by system software
> + UINT64 PageTableBaseAddress:40; // Page Table Base Address
> + UINT64 AvabilableHigh:11; // Available for use by system software
> + UINT64 Nx:1; // No Execute bit
> + } Bits;
> + UINT64 Uint64;
> +} PAGE_MAP_AND_DIRECTORY_POINTER;
> +
> +//
> +// Page Table Entry 4KB
> +//
> +typedef union {
> + struct {
> + UINT64 Present:1; // 0 = Not present in memory,
> + // 1 = Present in memory
> + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
> + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
> + UINT64 WriteThrough:1; // 0 = Write-Back caching,
> + // 1 = Write-Through caching
> + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
> + UINT64 Accessed:1; // 0 = Not accessed,
> + // 1 = Accessed (set by CPU)
> + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
> + // processor on access to page
> + UINT64 PAT:1; //
> + UINT64 Global:1; // 0 = Not global page, 1 = global page
> + // TLB not cleared on CR3 write
> + UINT64 Available:3; // Available for use by system software
> + UINT64 PageTableBaseAddress:40; // Page Table Base Address
> + UINT64 AvabilableHigh:11; // Available for use by system software
> + UINT64 Nx:1; // 0 = Execute Code,
> + // 1 = No Code Execution
> + } Bits;
> + UINT64 Uint64;
> +} PAGE_TABLE_4K_ENTRY;
> +
> +//
> +// Page Table Entry 2MB
> +//
> +typedef union {
> + struct {
> + UINT64 Present:1; // 0 = Not present in memory,
> + // 1 = Present in memory
> + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
> + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
> + UINT64 WriteThrough:1; // 0 = Write-Back caching,
> + // 1=Write-Through caching
> + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
> + UINT64 Accessed:1; // 0 = Not accessed,
> + // 1 = Accessed (set by CPU)
> + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
> + // processor on access to page
> + UINT64 MustBe1:1; // Must be 1
> + UINT64 Global:1; // 0 = Not global page, 1 = global page
> + // TLB not cleared on CR3 write
> + UINT64 Available:3; // Available for use by system software
> + UINT64 PAT:1; //
> + UINT64 MustBeZero:8; // Must be zero;
> + UINT64 PageTableBaseAddress:31; // Page Table Base Address
> + UINT64 AvabilableHigh:11; // Available for use by system software
> + UINT64 Nx:1; // 0 = Execute Code,
> + // 1 = No Code Execution
> + } Bits;
> + UINT64 Uint64;
> +} PAGE_TABLE_ENTRY;
> +
> +//
> +// Page Table Entry 1GB
> +//
> +typedef union {
> + struct {
> + UINT64 Present:1; // 0 = Not present in memory,
> + // 1 = Present in memory
> + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
> + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
> + UINT64 WriteThrough:1; // 0 = Write-Back caching,
> + // 1 = Write-Through caching
> + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
> + UINT64 Accessed:1; // 0 = Not accessed,
> + // 1 = Accessed (set by CPU)
> + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
> + // processor on access to page
> + UINT64 MustBe1:1; // Must be 1
> + UINT64 Global:1; // 0 = Not global page, 1 = global page
> + // TLB not cleared on CR3 write
> + UINT64 Available:3; // Available for use by system software
> + UINT64 PAT:1; //
> + UINT64 MustBeZero:17; // Must be zero;
> + UINT64 PageTableBaseAddress:22; // Page Table Base Address
> + UINT64 AvabilableHigh:11; // Available for use by system software
> + UINT64 Nx:1; // 0 = Execute Code,
> + // 1 = No Code Execution
> + } Bits;
> + UINT64 Uint64;
> +} PAGE_TABLE_1G_ENTRY;
> +
> +#pragma pack()
> +
> +#define IA32_PG_P BIT0
> +#define IA32_PG_RW BIT1
> +#define IA32_PG_PS BIT7
> +
> +#define PAGING_PAE_INDEX_MASK 0x1FF
> +
> +#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
> +#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
> +#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
> +
> +#define PAGING_L1_ADDRESS_SHIFT 12
> +#define PAGING_L2_ADDRESS_SHIFT 21
> +#define PAGING_L3_ADDRESS_SHIFT 30
> +#define PAGING_L4_ADDRESS_SHIFT 39
> +
> +#define PAGING_PML4E_NUMBER 4
> +
> +#define PAGETABLE_ENTRY_MASK ((1UL << 9) - 1)
> +#define PML4_OFFSET(x) ( (x >> 39) & PAGETABLE_ENTRY_MASK)
> +#define PDP_OFFSET(x) ( (x >> 30) & PAGETABLE_ENTRY_MASK)
> +#define PDE_OFFSET(x) ( (x >> 21) & PAGETABLE_ENTRY_MASK)
> +#define PTE_OFFSET(x) ( (x >> 12) & PAGETABLE_ENTRY_MASK)
> +#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
> +
> +#define PAGE_TABLE_POOL_ALIGNMENT BASE_2MB
> +#define PAGE_TABLE_POOL_UNIT_SIZE SIZE_2MB
> +#define PAGE_TABLE_POOL_UNIT_PAGES \
> + EFI_SIZE_TO_PAGES (PAGE_TABLE_POOL_UNIT_SIZE)
> +#define PAGE_TABLE_POOL_ALIGN_MASK \
> + (~(EFI_PHYSICAL_ADDRESS)(PAGE_TABLE_POOL_ALIGNMENT - 1))
> +
> +typedef struct {
> + VOID *NextPool;
> + UINTN Offset;
> + UINTN FreePages;
> +} PAGE_TABLE_POOL;
> +
> +#endif
> diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c
> index 8402fcc4fa..3df3b09732 100644
> --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c
> +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c
> @@ -11,6 +11,7 @@
> #include <Protocol/MpService.h>
> #include <Library/BaseMemoryLib.h>
>
> +#include "VirtualMemory.h"
> //
> // Functions implemented by the migration handler
> //
> @@ -43,6 +44,83 @@ typedef volatile struct {
> UINT32 done;
> } MH_COMMAND_PARAMETERS;
>
> +//
> +// Addresses for MH page table.
> +//
> +STATIC PAGE_TABLE_POOL *mPageTablePool = NULL;
> +STATIC PHYSICAL_ADDRESS mMigrationHelperPageTables = 0;
> +
> +//
> +// Offset for non-cbit mapping.
> +//
> +#define UNENC_VIRT_ADDR_BASE 0xffffff8000000000ULL
> +
> +
> +/**
> + Allocates and fills in custom page tables for Migration Handler.
> + The MH must be able to write to any encrypted page. Thus, it
> + uses an identity map where the C-bit is set for every page. The
> + HV should never ask the MH to import/export a shared page. The
> + MH must also be able to read some shared pages. The first 1GB
> + of memory is mapped at offset UNENC_VIRT_ADDR_BASE.
> +
> +**/
> +VOID
> +PrepareMigrationHandlerPageTables (
> + VOID
> + )
> +{
> + UINTN PoolPages;
> + VOID *Buffer;
> + VOID *Start;
> + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
> + PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
> + PAGE_TABLE_1G_ENTRY *Unenc1GEntry;
> + UINT64 AddressEncMask;
> +
> + PoolPages = 1 + 10;
> + Buffer = AllocateAlignedRuntimePages (PoolPages, PAGE_TABLE_POOL_ALIGNMENT);
> + mPageTablePool = Buffer;
> + mPageTablePool->NextPool = mPageTablePool;
> + mPageTablePool->FreePages = PoolPages - 1;
> + mPageTablePool->Offset = EFI_PAGES_TO_SIZE (1);
> +
> + Start = (UINT8 *)mPageTablePool + mPageTablePool->Offset;
> + ZeroMem(Start, mPageTablePool->FreePages * EFI_PAGE_SIZE);
> +
> + AddressEncMask = 1ULL << 47;
> +
Preferably getting the encryption bit location from SEV CPUID
information.
> + PageMapLevel4Entry = Start;
> + PageDirectory1GEntry = (PAGE_TABLE_1G_ENTRY*)((UINT8*)Start + EFI_PAGE_SIZE);
> + Unenc1GEntry = (PAGE_TABLE_1G_ENTRY*)((UINT8*)Start + 2 * EFI_PAGE_SIZE);
> +
> + PageMapLevel4Entry = Start;
> + PageMapLevel4Entry += PML4_OFFSET(0x0ULL);
> + PageMapLevel4Entry->Uint64 = (UINT64)PageDirectory1GEntry | AddressEncMask | 0x23;
> +
> + PageMapLevel4Entry = Start;
> + PageMapLevel4Entry += PML4_OFFSET(UNENC_VIRT_ADDR_BASE); // should be 511
> + PageMapLevel4Entry->Uint64 = (UINT64)Unenc1GEntry | AddressEncMask | 0x23;
> +
> + UINT64 PageAddr = 0;
> + for (int i = 0; i < 512; i++, PageAddr += SIZE_1GB) {
> + PAGE_TABLE_1G_ENTRY *e = PageDirectory1GEntry + i;
> + e->Uint64 = PageAddr | AddressEncMask | 0xe3; // 1GB page
> + }
> +
Changing encryption attributes of a page requires to flush it from
the caches, you may need to do a clflush here.
Thanks,
Ashish
> + UINT64 UnencPageAddr = 0;
> + Unenc1GEntry->Uint64 = UnencPageAddr | 0xe3; // 1GB page unencrypted
> +
> + mMigrationHelperPageTables = (UINT64)Start | AddressEncMask;
> +}
> +
> +VOID
> +SwitchToMigrationHelperPageTables(VOID)
> +{
> + AsmWriteCr3(mMigrationHelperPageTables);
> +}
> +
> +
>
> VOID
> EFIAPI
> @@ -56,7 +134,12 @@ MigrationHandlerMain (
>
> DebugPrint (DEBUG_INFO,"MIGRATION Handler Started\n");
>
> - params_base = PcdGet32 (PcdConfidentialMigrationMailboxBase);
> + SwitchToMigrationHelperPageTables();
> +
> + //
> + // Shared pages must be offset by UNENC_VIRT_ADDR_BASE.
> + //
> + params_base = PcdGet32 (PcdConfidentialMigrationMailboxBase) + UNENC_VIRT_ADDR_BASE;
> params = (VOID *)params_base;
> page_va = (VOID *)params_base + 0x1000;
>
> @@ -134,6 +217,8 @@ LaunchMigrationHandler (
>
> MigrationHandlerCpuIndex = NumProc - 1;
>
> + PrepareMigrationHandlerPageTables();
> +
> EFI_EVENT Event;
> MpProto->GetProcessorInfo (MpProto, MigrationHandlerCpuIndex, &Tcb);
> if (Tcb.StatusFlag != 7) {
> @@ -154,6 +239,7 @@ LaunchMigrationHandler (
> if (PcdGetBool(PcdIsConfidentialMigrationTarget)) {
> DebugPrint (DEBUG_INFO,"Waiting for incoming confidential migration.\n");
> DisableInterrupts ();
> + SwitchToMigrationHelperPageTables();
> CpuDeadLoop ();
> }
>
> --
> 2.20.1
>
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#72394): https://edk2.groups.io/g/devel/message/72394
Mute This Topic: https://groups.io/mt/81036386/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
On 03/03/2021 18:32, Ashish Kalra wrote:
> On Tue, Mar 02, 2021 at 03:48:36PM -0500, Tobin Feldman-Fitzthum wrote:
>> From: Dov Murik <dovmurik@linux.ibm.com>
>>
>> The migration handler builds its own page tables and switches
>> to them. The MH pagetables are reserved as runtime memory.
>>
>> When the hypervisor asks the MH to import/export a page, the HV
>> writes the guest physical address of the page in question to the
>> mailbox. The MH uses an identity mapping so that it can read/write
>> whatever GPA is requested by the HV. The hypervisor only asks the
>> MH to import/export encrypted pages. Thus, the C-Bit can be set
>> for every page in the identity map.
>>
>> The MH also needs to read shared pages, such as the mailbox.
>> These are mapped at an offset. The offset must be added to
>> the physical address before it can be resolved.
>>
>> Signed-off-by: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>
>> Signed-off-by: Dov Murik <dovmurik@linux.vnet.ibm.com>
>> ---
>> .../ConfidentialMigrationDxe.inf | 1 +
>> .../ConfidentialMigration/VirtualMemory.h | 177 ++++++++++++++++++
>> .../ConfidentialMigrationDxe.c | 88 ++++++++-
>> 3 files changed, 265 insertions(+), 1 deletion(-)
>> create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h
>>
>> diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf
>> index 49457d5d17..8dadfd1d13 100644
>> --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf
>> +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf
>> @@ -15,6 +15,7 @@
>>
>> [Sources]
>> ConfidentialMigrationDxe.c
>> + VirtualMemory.h
>>
>> [Packages]
>> MdePkg/MdePkg.dec
>> diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h b/OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h
>> new file mode 100644
>> index 0000000000..c50cb64c63
>> --- /dev/null
>> +++ b/OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h
>> @@ -0,0 +1,177 @@
>> +/** @file
>> + Virtual Memory Management Services to set or clear the memory encryption bit
>> + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
>> + Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> + Code is derived from OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
>> +
>> +**/
>> +
>> +#ifndef __VIRTUAL_MEMORY__
>> +#define __VIRTUAL_MEMORY__
>> +
>> +#include <Library/BaseLib.h>
>> +#include <Library/BaseMemoryLib.h>
>> +#include <Library/CacheMaintenanceLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/MemoryAllocationLib.h>
>> +#include <Uefi.h>
>> +
>> +#define SYS_CODE64_SEL 0x38
>> +
>> +#pragma pack(1)
>> +
>> +//
>> +// Page-Map Level-4 Offset (PML4) and
>> +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
>> +//
>> +
>> +typedef union {
>> + struct {
>> + UINT64 Present:1; // 0 = Not present in memory,
>> + // 1 = Present in memory
>> + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
>> + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
>> + UINT64 WriteThrough:1; // 0 = Write-Back caching,
>> + // 1 = Write-Through caching
>> + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
>> + UINT64 Accessed:1; // 0 = Not accessed,
>> + // 1 = Accessed (set by CPU)
>> + UINT64 Reserved:1; // Reserved
>> + UINT64 MustBeZero:2; // Must Be Zero
>> + UINT64 Available:3; // Available for use by system software
>> + UINT64 PageTableBaseAddress:40; // Page Table Base Address
>> + UINT64 AvabilableHigh:11; // Available for use by system software
>> + UINT64 Nx:1; // No Execute bit
>> + } Bits;
>> + UINT64 Uint64;
>> +} PAGE_MAP_AND_DIRECTORY_POINTER;
>> +
>> +//
>> +// Page Table Entry 4KB
>> +//
>> +typedef union {
>> + struct {
>> + UINT64 Present:1; // 0 = Not present in memory,
>> + // 1 = Present in memory
>> + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
>> + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
>> + UINT64 WriteThrough:1; // 0 = Write-Back caching,
>> + // 1 = Write-Through caching
>> + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
>> + UINT64 Accessed:1; // 0 = Not accessed,
>> + // 1 = Accessed (set by CPU)
>> + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
>> + // processor on access to page
>> + UINT64 PAT:1; //
>> + UINT64 Global:1; // 0 = Not global page, 1 = global page
>> + // TLB not cleared on CR3 write
>> + UINT64 Available:3; // Available for use by system software
>> + UINT64 PageTableBaseAddress:40; // Page Table Base Address
>> + UINT64 AvabilableHigh:11; // Available for use by system software
>> + UINT64 Nx:1; // 0 = Execute Code,
>> + // 1 = No Code Execution
>> + } Bits;
>> + UINT64 Uint64;
>> +} PAGE_TABLE_4K_ENTRY;
>> +
>> +//
>> +// Page Table Entry 2MB
>> +//
>> +typedef union {
>> + struct {
>> + UINT64 Present:1; // 0 = Not present in memory,
>> + // 1 = Present in memory
>> + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
>> + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
>> + UINT64 WriteThrough:1; // 0 = Write-Back caching,
>> + // 1=Write-Through caching
>> + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
>> + UINT64 Accessed:1; // 0 = Not accessed,
>> + // 1 = Accessed (set by CPU)
>> + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
>> + // processor on access to page
>> + UINT64 MustBe1:1; // Must be 1
>> + UINT64 Global:1; // 0 = Not global page, 1 = global page
>> + // TLB not cleared on CR3 write
>> + UINT64 Available:3; // Available for use by system software
>> + UINT64 PAT:1; //
>> + UINT64 MustBeZero:8; // Must be zero;
>> + UINT64 PageTableBaseAddress:31; // Page Table Base Address
>> + UINT64 AvabilableHigh:11; // Available for use by system software
>> + UINT64 Nx:1; // 0 = Execute Code,
>> + // 1 = No Code Execution
>> + } Bits;
>> + UINT64 Uint64;
>> +} PAGE_TABLE_ENTRY;
>> +
>> +//
>> +// Page Table Entry 1GB
>> +//
>> +typedef union {
>> + struct {
>> + UINT64 Present:1; // 0 = Not present in memory,
>> + // 1 = Present in memory
>> + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
>> + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
>> + UINT64 WriteThrough:1; // 0 = Write-Back caching,
>> + // 1 = Write-Through caching
>> + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
>> + UINT64 Accessed:1; // 0 = Not accessed,
>> + // 1 = Accessed (set by CPU)
>> + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
>> + // processor on access to page
>> + UINT64 MustBe1:1; // Must be 1
>> + UINT64 Global:1; // 0 = Not global page, 1 = global page
>> + // TLB not cleared on CR3 write
>> + UINT64 Available:3; // Available for use by system software
>> + UINT64 PAT:1; //
>> + UINT64 MustBeZero:17; // Must be zero;
>> + UINT64 PageTableBaseAddress:22; // Page Table Base Address
>> + UINT64 AvabilableHigh:11; // Available for use by system software
>> + UINT64 Nx:1; // 0 = Execute Code,
>> + // 1 = No Code Execution
>> + } Bits;
>> + UINT64 Uint64;
>> +} PAGE_TABLE_1G_ENTRY;
>> +
>> +#pragma pack()
>> +
>> +#define IA32_PG_P BIT0
>> +#define IA32_PG_RW BIT1
>> +#define IA32_PG_PS BIT7
>> +
>> +#define PAGING_PAE_INDEX_MASK 0x1FF
>> +
>> +#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
>> +#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
>> +#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
>> +
>> +#define PAGING_L1_ADDRESS_SHIFT 12
>> +#define PAGING_L2_ADDRESS_SHIFT 21
>> +#define PAGING_L3_ADDRESS_SHIFT 30
>> +#define PAGING_L4_ADDRESS_SHIFT 39
>> +
>> +#define PAGING_PML4E_NUMBER 4
>> +
>> +#define PAGETABLE_ENTRY_MASK ((1UL << 9) - 1)
>> +#define PML4_OFFSET(x) ( (x >> 39) & PAGETABLE_ENTRY_MASK)
>> +#define PDP_OFFSET(x) ( (x >> 30) & PAGETABLE_ENTRY_MASK)
>> +#define PDE_OFFSET(x) ( (x >> 21) & PAGETABLE_ENTRY_MASK)
>> +#define PTE_OFFSET(x) ( (x >> 12) & PAGETABLE_ENTRY_MASK)
>> +#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
>> +
>> +#define PAGE_TABLE_POOL_ALIGNMENT BASE_2MB
>> +#define PAGE_TABLE_POOL_UNIT_SIZE SIZE_2MB
>> +#define PAGE_TABLE_POOL_UNIT_PAGES \
>> + EFI_SIZE_TO_PAGES (PAGE_TABLE_POOL_UNIT_SIZE)
>> +#define PAGE_TABLE_POOL_ALIGN_MASK \
>> + (~(EFI_PHYSICAL_ADDRESS)(PAGE_TABLE_POOL_ALIGNMENT - 1))
>> +
>> +typedef struct {
>> + VOID *NextPool;
>> + UINTN Offset;
>> + UINTN FreePages;
>> +} PAGE_TABLE_POOL;
>> +
>> +#endif
>> diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c
>> index 8402fcc4fa..3df3b09732 100644
>> --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c
>> +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c
>> @@ -11,6 +11,7 @@
>> #include <Protocol/MpService.h>
>> #include <Library/BaseMemoryLib.h>
>>
>> +#include "VirtualMemory.h"
>> //
>> // Functions implemented by the migration handler
>> //
>> @@ -43,6 +44,83 @@ typedef volatile struct {
>> UINT32 done;
>> } MH_COMMAND_PARAMETERS;
>>
>> +//
>> +// Addresses for MH page table.
>> +//
>> +STATIC PAGE_TABLE_POOL *mPageTablePool = NULL;
>> +STATIC PHYSICAL_ADDRESS mMigrationHelperPageTables = 0;
>> +
>> +//
>> +// Offset for non-cbit mapping.
>> +//
>> +#define UNENC_VIRT_ADDR_BASE 0xffffff8000000000ULL
>> +
>> +
>> +/**
>> + Allocates and fills in custom page tables for Migration Handler.
>> + The MH must be able to write to any encrypted page. Thus, it
>> + uses an identity map where the C-bit is set for every page. The
>> + HV should never ask the MH to import/export a shared page. The
>> + MH must also be able to read some shared pages. The first 1GB
>> + of memory is mapped at offset UNENC_VIRT_ADDR_BASE.
>> +
>> +**/
>> +VOID
>> +PrepareMigrationHandlerPageTables (
>> + VOID
>> + )
>> +{
>> + UINTN PoolPages;
>> + VOID *Buffer;
>> + VOID *Start;
>> + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
>> + PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
>> + PAGE_TABLE_1G_ENTRY *Unenc1GEntry;
>> + UINT64 AddressEncMask;
>> +
>> + PoolPages = 1 + 10;
>> + Buffer = AllocateAlignedRuntimePages (PoolPages, PAGE_TABLE_POOL_ALIGNMENT);
>> + mPageTablePool = Buffer;
>> + mPageTablePool->NextPool = mPageTablePool;
>> + mPageTablePool->FreePages = PoolPages - 1;
>> + mPageTablePool->Offset = EFI_PAGES_TO_SIZE (1);
>> +
>> + Start = (UINT8 *)mPageTablePool + mPageTablePool->Offset;
>> + ZeroMem(Start, mPageTablePool->FreePages * EFI_PAGE_SIZE);
>> +
>> + AddressEncMask = 1ULL << 47;
>> +
>
> Preferably getting the encryption bit location from SEV CPUID
> information.
You're right; I'll fix.
>
>> + PageMapLevel4Entry = Start;
>> + PageDirectory1GEntry = (PAGE_TABLE_1G_ENTRY*)((UINT8*)Start + EFI_PAGE_SIZE);
>> + Unenc1GEntry = (PAGE_TABLE_1G_ENTRY*)((UINT8*)Start + 2 * EFI_PAGE_SIZE);
>> +
>> + PageMapLevel4Entry = Start;
>> + PageMapLevel4Entry += PML4_OFFSET(0x0ULL);
>> + PageMapLevel4Entry->Uint64 = (UINT64)PageDirectory1GEntry | AddressEncMask | 0x23;
>> +
>> + PageMapLevel4Entry = Start;
>> + PageMapLevel4Entry += PML4_OFFSET(UNENC_VIRT_ADDR_BASE); // should be 511
>> + PageMapLevel4Entry->Uint64 = (UINT64)Unenc1GEntry | AddressEncMask | 0x23;
>> +
>> + UINT64 PageAddr = 0;
>> + for (int i = 0; i < 512; i++, PageAddr += SIZE_1GB) {
>> + PAGE_TABLE_1G_ENTRY *e = PageDirectory1GEntry + i;
>> + e->Uint64 = PageAddr | AddressEncMask | 0xe3; // 1GB page
>> + }
>> +
>
> Changing encryption attributes of a page requires to flush it from
> the caches, you may need to do a clflush here.
Thanks for pointing that out. I think I didn't see that in the code that
builds the page tables for encrypted memory (which inspired most of this
function), but maybe I missed it.
Thanks,
Dov
>
> Thanks,
> Ashish
>
>> + UINT64 UnencPageAddr = 0;
>> + Unenc1GEntry->Uint64 = UnencPageAddr | 0xe3; // 1GB page unencrypted
>> +
>> + mMigrationHelperPageTables = (UINT64)Start | AddressEncMask;
>> +}
>> +
>> +VOID
>> +SwitchToMigrationHelperPageTables(VOID)
>> +{
>> + AsmWriteCr3(mMigrationHelperPageTables);
>> +}
>> +
>> +
>>
>> VOID
>> EFIAPI
>> @@ -56,7 +134,12 @@ MigrationHandlerMain (
>>
>> DebugPrint (DEBUG_INFO,"MIGRATION Handler Started\n");
>>
>> - params_base = PcdGet32 (PcdConfidentialMigrationMailboxBase);
>> + SwitchToMigrationHelperPageTables();
>> +
>> + //
>> + // Shared pages must be offset by UNENC_VIRT_ADDR_BASE.
>> + //
>> + params_base = PcdGet32 (PcdConfidentialMigrationMailboxBase) + UNENC_VIRT_ADDR_BASE;
>> params = (VOID *)params_base;
>> page_va = (VOID *)params_base + 0x1000;
>>
>> @@ -134,6 +217,8 @@ LaunchMigrationHandler (
>>
>> MigrationHandlerCpuIndex = NumProc - 1;
>>
>> + PrepareMigrationHandlerPageTables();
>> +
>> EFI_EVENT Event;
>> MpProto->GetProcessorInfo (MpProto, MigrationHandlerCpuIndex, &Tcb);
>> if (Tcb.StatusFlag != 7) {
>> @@ -154,6 +239,7 @@ LaunchMigrationHandler (
>> if (PcdGetBool(PcdIsConfidentialMigrationTarget)) {
>> DebugPrint (DEBUG_INFO,"Waiting for incoming confidential migration.\n");
>> DisableInterrupts ();
>> + SwitchToMigrationHelperPageTables();
>> CpuDeadLoop ();
>> }
>>
>> --
>> 2.20.1
>>
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#72400): https://edk2.groups.io/g/devel/message/72400
Mute This Topic: https://groups.io/mt/81036386/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2026 Red Hat, Inc.