Re: [edk2-devel] [PATCH 0/2] AmdSev: Harden SEV Kernel hashes verifier
On 6/26/24 10:33 AM, Aithal, Srikanth wrote: On 6/26/2024 7:28 PM, Tobin Feldman-Fitzthum wrote: On 6/26/24 4:08 AM, Aithal, Srikanth wrote: Hello, SEV/SEVES guest boot fails with AMDSEV OVMF package built using upstream edk2 master [commit head: 2fbaaa96d11ad61a9133df1728e3fe965d1457a5]. SEV/SEVES guest boot with AMDSEV package gets stuck at below point: Plain Text 2024-06-26 04: 38: 02: Hello, SEV/SEVES guest boot fails with AMDSEV OVMF package built using upstream edk2 master [commit head: 2fbaaa96d11ad61a9133df1728e3fe965d1457a5]. SEV/SEVES guest boot with AMDSEV package gets stuck at below point: Plain Text |2024-06-26 04:38:02: FetchBlob: loading 14332416 bytes for "kernel" 2024-06-26 04:38:02: Select Item: 0x18 2024-06-26 04:38:02: Select Item: 0x11 2024-06-26 04:38:02: VerifyBlob: Found GUID 4DE79437-ABD2-427F-B835-D5B172D2045B in table 2024-06-26 04:38:02: VerifyBlob: Hash comparison succeeded for "kernel" 2024-06-26 04:38:02: Select Item: 0xB 2024-06-26 04:38:02: VerifyBlob: Found GUID 44BAF731-3A2F-4BD7-9AF1-41E29169781D in table 2024-06-26 04:38:02: VerifyBlob: Blob Specified in Hash Table was not Provided --> Hung here | Can you send qemu command that produces this case? It looks like what is happening is that the initrd is specified in the hash table, but is not provided to the guest. You might try with and without the -initrd option and compare. It's possible that when -initrd is not provided, QEMU will still put something in the table, which this patch might not account for. -Tobin my qemu command line to recreate the issue: qemu-system-x86_64 \ -machine q35,confidential-guest-support=sev0,vmport=off \ -object sev-guest,id=sev0,cbitpos=51,reduced-phys-bits=1,kernel-hashes=on \ -name guest=vm,debug-threads=on \ -drive if=pflash,format=raw,unit=0,file=/VT_BUILD/OVMF_AmdSev/OVMF.fd,readonly \ -cpu host \ -m 4096 \ -kernel '/VT_BUILD/usr/local/bzImage' \ -append 'root=/dev/sda rw console=ttyS0,115200n8 earlyprintk=ttyS0,115200 net.ifnames=0 biosdevname=0 movable_node swiotlb=65536' \ -smp 1,cores=1,threads=1,dies=1,sockets=1 \ -drive file=/VT_BUILD/images/22.04-server.qcow2,index=0,media=disk,format=qcow2 \ --enable-kvm \ --nographic Yes, if I pass -initrd explicitly the Hash verify step passes properly FetchBlob: loading 14332416 bytes for "kernel" Select Item: 0x18 Select Item: 0x11 VerifyBlob: Found GUID 4DE79437-ABD2-427F-B835-D5B172D2045B in table VerifyBlob: Hash comparison succeeded for "kernel" Select Item: 0xB FetchBlob: loading 75379943 bytes for "initrd" Select Item: 0x12 VerifyBlob: Found GUID 44BAF731-3A2F-4BD7-9AF1-41E29169781D in table VerifyBlob: Hash comparison succeeded for "initrd" Select Item: 0x14 FetchBlob: loading 120 bytes for "cmdline" Select Item: 0x15 VerifyBlob: Found GUID 97D02DD8-BD20-4C94-AA78-E7714D36AB2A in table VerifyBlob: Hash comparison succeeded for "cmdline" Ok, I'll submit a little tweak this afternoon that should fix your case. -Tobin This was working until yesterday [commit head: be38c01], where we can see boot was proceeding Plain Text |2024-06-25 03:13:23: VerifyBlob: Found GUID 4DE79437-ABD2-427F-B835-D5B172D2045B in table 2024-06-25 03:13:23: VerifyBlob: Hash comparison succeeded for "kernel" 2024-06-25 03:13:23: Select Item: 0xB 2024-06-25 03:13:23: VerifyBlob: Found GUID 44BAF731-3A2F-4BD7-9AF1-41E29169781D in table 2024-06-25 03:13:23: VerifyBlob: Hash comparison succeeded for "initrd" 2024-06-25 03:13:23: Select Item: 0x14 2024-06-25 03:13:23: FetchBlob: loading 120 bytes for "cmdline" 2024-06-25 03:13:23: Select Item: 0x15 2024-06-25 03:13:23: VerifyBlob: Found GUID 97D02DD8-BD20-4C94-AA78-E7714D36AB2A in table 2024-06-25 03:13:23: VerifyBlob: Hash comparison succeeded for "cmdline"| After this patch got merged the regression is seen. Thanks, Srikanth Aithal On 5/7/2024 1:57 AM, Tobin Feldman-Fitzthum via groups.io wrote: The AmdSev package has a so-called BlobVerifier, which is meant to extend the TCB of a confidential guest (SEV or SNP) to include components provided via fw_cfg such as initrd, kernel, kernel params. This series fixes a few implementation errors in the blob verifier. One common theme is that the verifier currently fails to halt the boot when an invalid blob is detected. This can lead to a confidential guest having a launch measurement that does not reflect the guest TCB. This series could also help us move towards consolidating the AmdSev package back into the OvmfPkg although more discussion will be needed on this. Thank you for Ryan Savino at AMD for pointing out some of these issues. Tobin Feldman-Fitzthum (2): AmdSev: Rework Blob Verifier AmdSev: Halt on failed blob allocation .../BlobVerifierSevHashes.c | 56 --- OvmfPkg/Include/Library/BlobVerifierLib.h | 14 +++--
Re: [edk2-devel] [PATCH 0/2] AmdSev: Harden SEV Kernel hashes verifier
On 6/26/24 4:08 AM, Aithal, Srikanth wrote: Hello, SEV/SEVES guest boot fails with AMDSEV OVMF package built using upstream edk2 master [commit head: 2fbaaa96d11ad61a9133df1728e3fe965d1457a5]. SEV/SEVES guest boot with AMDSEV package gets stuck at below point: Plain Text 2024-06-26 04: 38: 02: Hello, SEV/SEVES guest boot fails with AMDSEV OVMF package built using upstream edk2 master [commit head: 2fbaaa96d11ad61a9133df1728e3fe965d1457a5]. SEV/SEVES guest boot with AMDSEV package gets stuck at below point: Plain Text |2024-06-26 04:38:02: FetchBlob: loading 14332416 bytes for "kernel" 2024-06-26 04:38:02: Select Item: 0x18 2024-06-26 04:38:02: Select Item: 0x11 2024-06-26 04:38:02: VerifyBlob: Found GUID 4DE79437-ABD2-427F-B835-D5B172D2045B in table 2024-06-26 04:38:02: VerifyBlob: Hash comparison succeeded for "kernel" 2024-06-26 04:38:02: Select Item: 0xB 2024-06-26 04:38:02: VerifyBlob: Found GUID 44BAF731-3A2F-4BD7-9AF1-41E29169781D in table 2024-06-26 04:38:02: VerifyBlob: Blob Specified in Hash Table was not Provided --> Hung here | Can you send qemu command that produces this case? It looks like what is happening is that the initrd is specified in the hash table, but is not provided to the guest. You might try with and without the -initrd option and compare. It's possible that when -initrd is not provided, QEMU will still put something in the table, which this patch might not account for. -Tobin This was working until yesterday [commit head: be38c01], where we can see boot was proceeding Plain Text |2024-06-25 03:13:23: VerifyBlob: Found GUID 4DE79437-ABD2-427F-B835-D5B172D2045B in table 2024-06-25 03:13:23: VerifyBlob: Hash comparison succeeded for "kernel" 2024-06-25 03:13:23: Select Item: 0xB 2024-06-25 03:13:23: VerifyBlob: Found GUID 44BAF731-3A2F-4BD7-9AF1-41E29169781D in table 2024-06-25 03:13:23: VerifyBlob: Hash comparison succeeded for "initrd" 2024-06-25 03:13:23: Select Item: 0x14 2024-06-25 03:13:23: FetchBlob: loading 120 bytes for "cmdline" 2024-06-25 03:13:23: Select Item: 0x15 2024-06-25 03:13:23: VerifyBlob: Found GUID 97D02DD8-BD20-4C94-AA78-E7714D36AB2A in table 2024-06-25 03:13:23: VerifyBlob: Hash comparison succeeded for "cmdline"| After this patch got merged the regression is seen. Thanks, Srikanth Aithal On 5/7/2024 1:57 AM, Tobin Feldman-Fitzthum via groups.io wrote: The AmdSev package has a so-called BlobVerifier, which is meant to extend the TCB of a confidential guest (SEV or SNP) to include components provided via fw_cfg such as initrd, kernel, kernel params. This series fixes a few implementation errors in the blob verifier. One common theme is that the verifier currently fails to halt the boot when an invalid blob is detected. This can lead to a confidential guest having a launch measurement that does not reflect the guest TCB. This series could also help us move towards consolidating the AmdSev package back into the OvmfPkg although more discussion will be needed on this. Thank you for Ryan Savino at AMD for pointing out some of these issues. Tobin Feldman-Fitzthum (2): AmdSev: Rework Blob Verifier AmdSev: Halt on failed blob allocation .../BlobVerifierSevHashes.c | 56 --- OvmfPkg/Include/Library/BlobVerifierLib.h | 14 +++-- .../BlobVerifierLibNull/BlobVerifierNull.c| 13 +++-- .../QemuKernelLoaderFsDxe.c | 9 ++- 4 files changed, 69 insertions(+), 23 deletions(-) -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#119720): https://edk2.groups.io/g/devel/message/119720 Mute This Topic: https://groups.io/mt/105977013/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [PATCH 1/2] AmdSev: Rework Blob Verifier
The Blob Verifier checks boot artifacts against a hash table injected by the hypervisor and measured by hardware. Update the Blob Verifier to enter a dead loop if the artifacts do not match. Signed-off-by: Tobin Feldman-Fitzthum --- .../BlobVerifierSevHashes.c | 39 +++ 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c b/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c index 2e58794c3c..ee8bca509a 100644 --- a/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c +++ b/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c @@ -77,13 +77,17 @@ FindBlobEntryGuid ( /** Verify blob from an external source. + If a non-secure configuration is detected this function will enter a + dead loop to prevent a boot. + @param[in] BlobName The name of the blob @param[in] BufThe data of the blob @param[in] BufSizeThe size of the blob in bytes - @retval EFI_SUCCESS The blob was verified successfully. - @retval EFI_ACCESS_DENIED The blob could not be verified, and therefore -should be considered non-secure. + @retval EFI_SUCCESS The blob was verified successfully or was not +found in the hash table. + @retval EFI_ACCESS_DENIED Kernel hashes not supported, but the boot +can continue safely. **/ EFI_STATUS EFIAPI @@ -99,8 +103,8 @@ VerifyBlob ( if ((mHashesTable == NULL) || (mHashesTableSize == 0)) { DEBUG (( - DEBUG_ERROR, - "%a: Verifier called but no hashes table discoverd in MEMFD\n", + DEBUG_WARN, + "%a: No hashes table discovered in MEMFD\n", __func__ )); return EFI_ACCESS_DENIED; @@ -114,7 +118,8 @@ VerifyBlob ( __func__, BlobName )); -return EFI_ACCESS_DENIED; + +CpuDeadLoop (); } // @@ -136,10 +141,22 @@ VerifyBlob ( DEBUG ((DEBUG_INFO, "%a: Found GUID %g in table\n", __func__, Guid)); +if (BufSize == 0) { + DEBUG (( +DEBUG_ERROR, +"%a: Blob Specified in Hash Table was not Provided", +__func__, +EntrySize, +SHA256_DIGEST_SIZE +)); + + CpuDeadLoop (); +} + EntrySize = Entry->Len - sizeof Entry->Guid - sizeof Entry->Len; if (EntrySize != SHA256_DIGEST_SIZE) { DEBUG (( -DEBUG_ERROR, +DEBUG_WARN, "%a: Hash has the wrong size %d != %d\n", __func__, EntrySize, @@ -170,18 +187,24 @@ VerifyBlob ( __func__, BlobName )); + + CpuDeadLoop (); } return Status; } + // + // If the GUID is not in the hash table, execution can still continue. + // This blob will not be measured, but at least one blob must be. + // DEBUG (( DEBUG_ERROR, "%a: Hash GUID %g not found in table\n", __func__, Guid )); - return EFI_ACCESS_DENIED; + return EFI_SUCCESS; } /** -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#118662): https://edk2.groups.io/g/devel/message/118662 Mute This Topic: https://groups.io/mt/105977014/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [PATCH 2/2] AmdSev: Halt on failed blob allocation
A malicious host may be able to undermine the fw_cfg interface such that loading a blob fails. In this case rather than continuing to the next boot option, the blob verifier should halt. For non-confidential guests, the error should be non-fatal. Signed-off-by: Tobin Feldman-Fitzthum --- .../BlobVerifierSevHashes.c | 17 - OvmfPkg/Include/Library/BlobVerifierLib.h | 14 ++ .../BlobVerifierLibNull/BlobVerifierNull.c | 13 - .../QemuKernelLoaderFsDxe.c | 9 - 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c b/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c index ee8bca509a..c550518d73 100644 --- a/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c +++ b/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c @@ -83,6 +83,7 @@ FindBlobEntryGuid ( @param[in] BlobName The name of the blob @param[in] BufThe data of the blob @param[in] BufSizeThe size of the blob in bytes + @param[in] FetchStatusThe status of the previous blob fetch @retval EFI_SUCCESS The blob was verified successfully or was not found in the hash table. @@ -94,13 +95,27 @@ EFIAPI VerifyBlob ( IN CONST CHAR16 *BlobName, IN CONST VOID*Buf, - IN UINT32BufSize + IN UINT32BufSize, + IN EFI_STATUSFetchStatus ) { CONST GUID *Guid; INT32 Remaining; HASH_TABLE *Entry; + // Enter a dead loop if the fetching of this blob + // failed. This prevents a malicious host from + // circumventing the following checks. + if (EFI_ERROR (FetchStatus)) { +DEBUG (( + DEBUG_ERROR, + "%a: Fetching blob failed.\n", + __func__ + )); + +CpuDeadLoop (); + } + if ((mHashesTable == NULL) || (mHashesTableSize == 0)) { DEBUG (( DEBUG_WARN, diff --git a/OvmfPkg/Include/Library/BlobVerifierLib.h b/OvmfPkg/Include/Library/BlobVerifierLib.h index 7e1af27574..efe26734b1 100644 --- a/OvmfPkg/Include/Library/BlobVerifierLib.h +++ b/OvmfPkg/Include/Library/BlobVerifierLib.h @@ -19,20 +19,26 @@ /** Verify blob from an external source. + If a non-secure configuration is detected this function will enter a + dead loop to prevent a boot. + @param[in] BlobName The name of the blob @param[in] BufThe data of the blob @param[in] BufSizeThe size of the blob in bytes + @param[in] FetchStatusThe status of fetching this blob - @retval EFI_SUCCESS The blob was verified successfully. - @retval EFI_ACCESS_DENIED The blob could not be verified, and therefore -should be considered non-secure. + @retval EFI_SUCCESS The blob was verified successfully or was not +found in the hash table. + @retval EFI_ACCESS_DENIED Kernel hashes not supported but the boot can +continue safely. **/ EFI_STATUS EFIAPI VerifyBlob ( IN CONST CHAR16 *BlobName, IN CONST VOID*Buf, - IN UINT32BufSize + IN UINT32BufSize, + IN EFI_STATUSFetchStatus ); #endif diff --git a/OvmfPkg/Library/BlobVerifierLibNull/BlobVerifierNull.c b/OvmfPkg/Library/BlobVerifierLibNull/BlobVerifierNull.c index e817c3cc95..db5320571c 100644 --- a/OvmfPkg/Library/BlobVerifierLibNull/BlobVerifierNull.c +++ b/OvmfPkg/Library/BlobVerifierLibNull/BlobVerifierNull.c @@ -16,18 +16,21 @@ @param[in] BlobName The name of the blob @param[in] BufThe data of the blob @param[in] BufSizeThe size of the blob in bytes + @param[in] FetchStatusThe status of the fetch of this blob - @retval EFI_SUCCESS The blob was verified successfully. - @retval EFI_ACCESS_DENIED The blob could not be verified, and therefore -should be considered non-secure. + @retval EFI_SUCCESS The blob was verified successfully or was not +found in the hash table. + @retval EFI_ACCESS_DENIED Kernel hashes not supported but the boot can +continue safely. **/ EFI_STATUS EFIAPI VerifyBlob ( IN CONST CHAR16 *BlobName, IN CONST VOID*Buf, - IN UINT32BufSize + IN UINT32BufSize, + IN EFI_STATUSFetchStatus ) { - return EFI_SUCCESS; + return FetchStatus; } diff --git a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c index 3c12085f6c..cf58c97cd2 100644 --- a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c +++ b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c @@ -1042,6 +1042,7 @@ QemuKernelLoaderFsDxeEntrypoint ( KERNEL_BLOB *C
[edk2-devel] [PATCH 0/2] AmdSev: Harden SEV Kernel hashes verifier
The AmdSev package has a so-called BlobVerifier, which is meant to extend the TCB of a confidential guest (SEV or SNP) to include components provided via fw_cfg such as initrd, kernel, kernel params. This series fixes a few implementation errors in the blob verifier. One common theme is that the verifier currently fails to halt the boot when an invalid blob is detected. This can lead to a confidential guest having a launch measurement that does not reflect the guest TCB. This series could also help us move towards consolidating the AmdSev package back into the OvmfPkg although more discussion will be needed on this. Thank you for Ryan Savino at AMD for pointing out some of these issues. Tobin Feldman-Fitzthum (2): AmdSev: Rework Blob Verifier AmdSev: Halt on failed blob allocation .../BlobVerifierSevHashes.c | 56 --- OvmfPkg/Include/Library/BlobVerifierLib.h | 14 +++-- .../BlobVerifierLibNull/BlobVerifierNull.c| 13 +++-- .../QemuKernelLoaderFsDxe.c | 9 ++- 4 files changed, 69 insertions(+), 23 deletions(-) -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#118661): https://edk2.groups.io/g/devel/message/118661 Mute This Topic: https://groups.io/mt/105977013/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 8/9] OvmfPkg/AmdSev: Add Migration Handler entry point
The Migration Handler runs in the mirror VM. The MH is started directly by the hypervisor. SetupMigrationHandler runs in the main VM and sets up the migration entry point. The HV starts execution of the mirror vCPU at the entry point, which trampolines to MigrationHandlerMain Signed-off-by: Tobin Feldman-Fitzthum --- OvmfPkg/OvmfPkg.dec | 3 ++ OvmfPkg/AmdSev/AmdSevX64.fdf | 3 ++ .../ConfidentialMigrationDxe.inf | 2 + .../ConfidentialMigrationPei.inf | 2 + .../ConfidentialMigrationDxe.c| 48 + .../ConfidentialMigrationPei.c| 6 +++ .../MigrationEntryPoint.nasm | 51 +++ 7 files changed, 115 insertions(+) create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/MigrationEntryPoint.nasm diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 1252582c99..c6e07accf6 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -336,6 +336,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase|0x0|UINT32|0x4b gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxSize|0x0|UINT32|0x4c + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationEntryBase|0x0|UINT32|0x4d + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationEntrySize|0x0|UINT32|0x4e + [PcdsDynamic, PcdsDynamicEx] gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf index a8e296e641..8687fadfcc 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.fdf +++ b/OvmfPkg/AmdSev/AmdSevX64.fdf @@ -74,6 +74,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.P 0x02|0x003000 gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase|gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxSize +0x023000|0x001000 +gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationEntryBase|gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationEntrySize + 0x12|0x0E gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize FV = PEIFV diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf index 42875095fc..b879037586 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf @@ -16,6 +16,7 @@ [Sources] ConfidentialMigrationDxe.c VirtualMemory.h + MigrationEntryPoint.nasm [Packages] MdePkg/MdePkg.dec @@ -31,6 +32,7 @@ gUefiOvmfPkgTokenSpaceGuid.PcdIsConfidentialMigrationTarget gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationEntryBase [Depex] TRUE diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf index 918cf22abd..6233b82cc2 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf @@ -30,6 +30,8 @@ [FixedPcd] gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxSize + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationEntryBase + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationEntrySize [Depex] TRUE diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c index 2de35a7bb1..5e96206d17 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c @@ -38,11 +38,23 @@ typedef volatile struct { UINT32 Done; } MH_COMMAND_PARAMETERS; +// +// Addresses to be used in the entry point +// +typedef struct { + UINT32 Cr3; + UINT64 StackBase; + UINT64 MhBase; +} ENTRY_ADDRS; + // // Offset for non-cbit mapping. // #define UNENC_VIRT_ADDR_BASE0xff80ULL +void MigrationHandlerEntryPoint(void); +void MigrationHandlerEntryPoint64(void); + STATIC PAGE_TABLE_POOL *mPageTablePool = NULL; PHYSICAL_ADDRESS mMigrationHandlerPageTables = 0; PHYSICAL_ADDRESS mMigrationHandlerStackBase = 0; @@ -193,6 +205,16 @@ SetupMigrationHandler ( IN EFI_SYSTEM_TABLE *SystemTable ) { + UINT32LongModeOffset; + UINT32EntryAddrsOffset; + UINT32GdtOffset; + IA32_DESCRIPTOR GdtPtr; + UINT64EntryPoint; + ENTRY_ADDRS *EntryData; + + LongModeOffset = 0x200; + EntryAddrsOffset = 0x400; + GdtOffset = 0x600; if (!PcdGetBool(PcdStartConfidentialMigrationHandler)) { return 0; @@ -205,6 +227,32
[edk2-devel] [RFC PATCH 9/9] OvmfPkg/ResetVector: Expose Migration Handler Entry Addresses
Exposes the address of the Migration Handler entry point via a GUIDed struct. To support migration, the HV should find this struct and start one vCPU at the entry point address. Signed-off-by: Tobin Feldman-Fitzthum --- OvmfPkg/ResetVector/ResetVector.inf | 1 + OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 13 + OvmfPkg/ResetVector/ResetVector.nasmb| 1 + 3 files changed, 15 insertions(+) diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf index d028c92d8c..642757796c 100644 --- a/OvmfPkg/ResetVector/ResetVector.inf +++ b/OvmfPkg/ResetVector/ResetVector.inf @@ -49,3 +49,4 @@ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableSize + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationEntryBase diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm index 7ec3c6e980..fc38bd927d 100644 --- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm +++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm @@ -86,6 +86,19 @@ sevSecretBlockStart: DB 0x80, 0x81, 0x12, 0x7C, 0x90, 0xD3, 0xD2, 0x94 sevSecretBlockEnd: +; +; The IP of the migration handler. The hypervisor should start +; the mirror with this address. +; +; GUID = 5c7db037-ab87-4282-b33c-7894f01471ec +; +sevMigrationBlockStart: +DD SEV_MIGRATION_ENTRY_IP +DW sevMigrationBlockStart - sevMigrationBlockEnd +DB 0x5C, 0x7D, 0xB0, 0x37, 0x87, 0xAB, 0x82, 0x42 +DB 0xB3, 0x3C, 0x78, 0x94, 0xF0, 0x14, 0x71, 0xEC +sevMigrationBlockEnd: + ; ; SEV-ES Processor Reset support ; diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb index acec46a324..344713bfbb 100644 --- a/OvmfPkg/ResetVector/ResetVector.nasmb +++ b/OvmfPkg/ResetVector/ResetVector.nasmb @@ -91,5 +91,6 @@ %define SEV_LAUNCH_SECRET_SIZE FixedPcdGet32 (PcdSevLaunchSecretSize) %define SEV_FW_HASH_BLOCK_BASE FixedPcdGet32 (PcdQemuHashTableBase) %define SEV_FW_HASH_BLOCK_SIZE FixedPcdGet32 (PcdQemuHashTableSize) + %define SEV_MIGRATION_ENTRY_IP FixedPcdGet32 (PcdConfidentialMigrationEntryBase) %include "Ia16/ResetVectorVtf0.asm" -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#79525): https://edk2.groups.io/g/devel/message/79525 Mute This Topic: https://groups.io/mt/84982990/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 4/9] OvmfPkg/AmdSev: MH support for mailbox protocol
The migration handler communicates with the hypervisor via a shared mailbox page. The MH can perform four functions at the behest of the HV: init, save page, restore page, and reset. Signed-off-by: Tobin Feldman-Fitzthum --- .../ConfidentialMigrationDxe.inf | 1 + .../ConfidentialMigrationDxe.c| 74 +++ 2 files changed, 75 insertions(+) diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf index 6e3fa7e51c..cb5609271c 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf @@ -29,6 +29,7 @@ [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdIsConfidentialMigrationTarget gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase [Depex] TRUE diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c index f0dfbd279e..a981aaeac7 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c @@ -6,14 +6,88 @@ **/ #include +#include #include +// +// Functions implemented by the migration handler +// +#define MH_FUNC_INIT 0 +#define MH_FUNC_SAVE_PAGE 1 +#define MH_FUNC_RESTORE_PAGE 2 +#define MH_FUNC_RESET 3 + +// +// Return codes for MH functions +// +#define MH_SUCCESS0 +#define MH_INVALID_FUNC (-1) +#define MH_AUTH_ERR (-2) + +// +// Mailbox for communication with hypervisor +// +typedef volatile struct { + UINT64 Nr; + UINT64 Gpa; + UINT32 DoPrefetch; + UINT32 Ret; + UINT32 Go; + UINT32 Done; +} MH_COMMAND_PARAMETERS; + + VOID EFIAPI MigrationHandlerMain () { + UINT64 MailboxStart; + MH_COMMAND_PARAMETERS*Params; + VOID *PageVa; + DebugPrint (DEBUG_INFO,"Migration Handler Started\n"); + MailboxStart = PcdGet32 (PcdConfidentialMigrationMailboxBase); + Params = (VOID *)MailboxStart; + PageVa = (VOID *)(MailboxStart + 0x1000); + + DisableInterrupts (); + Params->Go = 0; + + while (1) { +while (!Params->Go) { + CpuPause (); +} +Params->Done = 0; + +switch (Params->Nr) { +case MH_FUNC_INIT: + Params->Ret = MH_SUCCESS; + break; + +case MH_FUNC_SAVE_PAGE: + CopyMem (PageVa, (VOID *)Params->Gpa, 4096); + Params->Ret = MH_SUCCESS; + break; + +case MH_FUNC_RESTORE_PAGE: + CopyMem ((VOID *)Params->Gpa, PageVa, 4096); + Params->Ret = MH_SUCCESS; + break; + +case MH_FUNC_RESET: + Params->Ret = MH_SUCCESS; + break; + +default: + Params->Ret = MH_INVALID_FUNC; + break; +} + +Params->Go = 0; +Params->Done = 1; + + } } /** -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#79521): https://edk2.groups.io/g/devel/message/79521 Mute This Topic: https://groups.io/mt/84982983/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 7/9] OvmfPkg/AmdSev: Don't overwrite MH stack
The Migration Handler uses its own stack and should avoid overwriting the stack when importing pages. Signed-off-by: Tobin Feldman-Fitzthum --- .../ConfidentialMigrationDxe.c | 17 +++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c index ee1466eb00..2de35a7bb1 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c @@ -45,6 +45,8 @@ typedef volatile struct { STATIC PAGE_TABLE_POOL *mPageTablePool = NULL; PHYSICAL_ADDRESS mMigrationHandlerPageTables = 0; +PHYSICAL_ADDRESS mMigrationHandlerStackBase = 0; +UINT32mMigrationHandlerStackSize = 4; /** Allocates and fills in custom page tables for Migration Handler. @@ -112,6 +114,8 @@ MigrationHandlerMain () UINT64 MailboxEnd; UINT64 PagetableStart; UINT64 PagetableEnd; + UINT64 StackStart; + UINT64 StackEnd; MH_COMMAND_PARAMETERS*Params; VOID *PageVa; @@ -126,6 +130,9 @@ MigrationHandlerMain () PagetableStart = mMigrationHandlerPageTables; PagetableEnd = PagetableStart + 11 * EFI_PAGE_SIZE; + StackStart = mMigrationHandlerStackBase; + StackEnd = StackStart + mMigrationHandlerStackSize; + DisableInterrupts (); Params->Go = 0; @@ -147,10 +154,11 @@ MigrationHandlerMain () case MH_FUNC_RESTORE_PAGE: // - // Don't import a page that covers the mailbox or pagetables. + // Don't import a page that covers the mailbox, pagetables, or stack. // if (!((Params->Gpa >= MailboxStart && Params->Gpa < MailboxEnd) || - (Params->Gpa >= PagetableStart && Params->Gpa < PagetableEnd))) { + (Params->Gpa >= PagetableStart && Params->Gpa < PagetableEnd) || + (Params->Gpa >= StackStart && Params->Gpa < StackEnd))) { CopyMem ((VOID *)Params->Gpa, PageVa, 4096); } @@ -190,6 +198,11 @@ SetupMigrationHandler ( return 0; } + // + // Setup stack and pagetables for Migration Handler + // + mMigrationHandlerStackBase = (UINTN)AllocateAlignedRuntimePages (mMigrationHandlerStackSize, PAGE_TABLE_POOL_ALIGNMENT); + PrepareMigrationHandlerPageTables (); // -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#79524): https://edk2.groups.io/g/devel/message/79524 Mute This Topic: https://groups.io/mt/84982987/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 6/9] OvmfPkg/AmdSev: Don't overwrite mailbox or pagetables
While restoring pages, the MH should avoid overwriting its pagetables or the mailbox it uses to communicate with the HV. Signed-off-by: Tobin Feldman-Fitzthum --- .../ConfidentialMigrationDxe.c | 17 - 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c index 34d449fe10..ee1466eb00 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c @@ -109,6 +109,9 @@ EFIAPI MigrationHandlerMain () { UINT64 MailboxStart; + UINT64 MailboxEnd; + UINT64 PagetableStart; + UINT64 PagetableEnd; MH_COMMAND_PARAMETERS*Params; VOID *PageVa; @@ -118,6 +121,11 @@ MigrationHandlerMain () Params = (VOID *)(MailboxStart + UNENC_VIRT_ADDR_BASE); PageVa = (VOID *)(MailboxStart + UNENC_VIRT_ADDR_BASE + 0x1000); + MailboxEnd = MailboxStart + 2 * EFI_PAGE_SIZE; + + PagetableStart = mMigrationHandlerPageTables; + PagetableEnd = PagetableStart + 11 * EFI_PAGE_SIZE; + DisableInterrupts (); Params->Go = 0; @@ -138,7 +146,14 @@ MigrationHandlerMain () break; case MH_FUNC_RESTORE_PAGE: - CopyMem ((VOID *)Params->Gpa, PageVa, 4096); + // + // Don't import a page that covers the mailbox or pagetables. + // + if (!((Params->Gpa >= MailboxStart && Params->Gpa < MailboxEnd) || + (Params->Gpa >= PagetableStart && Params->Gpa < PagetableEnd))) { + +CopyMem ((VOID *)Params->Gpa, PageVa, 4096); + } Params->Ret = MH_SUCCESS; break; -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#79523): https://edk2.groups.io/g/devel/message/79523 Mute This Topic: https://groups.io/mt/84982986/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 5/9] OvmfPkg/AmdSev: Build page table for migration handler
From: Dov Murik 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 Signed-off-by: Dov Murik --- .../ConfidentialMigrationDxe.inf | 1 + .../ConfidentialMigration/VirtualMemory.h | 177 ++ .../ConfidentialMigrationDxe.c| 73 +++- 3 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf index cb5609271c..42875095fc 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 00..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. + Copyright (c) 2017, AMD Incorporated. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + Code is derived from OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h + +**/ + +#ifndef __VIRTUAL_MEMORY__ +#define __VIRTUAL_MEMORY__ + +#include +#include +#include +#include +#include +#include + +#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; + UINT64Uint64; +} 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; + UINT64Uint64; +} PAGE_TABLE_4K_ENTRY; + +// +// Page Table Entry 2MB +// +typedef union { + struct { +UINT64 Prese
[edk2-devel] [RFC PATCH 3/9] OvmfPkg/AmdSev: Setup Migration Handler Mailbox
The migration handler communicates with the hypervisor using a special mailbox, a page of shared memory where pending commands can be written. Another shared page is used to pass the incoming or outgoing guest memory pages. These pages are set aside in MEMFD, which this patch expands, and reserved as runtime memory in ConfidentialMigrationPei, which this patch introduces. Signed-off-by: Tobin Feldman-Fitzthum --- OvmfPkg/OvmfPkg.dec | 5 +++ OvmfPkg/AmdSev/AmdSevX64.dsc | 1 + OvmfPkg/AmdSev/AmdSevX64.fdf | 12 --- .../ConfidentialMigrationPei.inf | 35 +++ .../ConfidentialMigrationPei.c| 25 + 5 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.c diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index cfc645619d..1252582c99 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -331,6 +331,11 @@ gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|0x0|UINT32|0x47 gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableSize|0x0|UINT32|0x48 + ## Area used by the confidential migration handler to communicate with + # the hypervisor. + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase|0x0|UINT32|0x4b + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxSize|0x0|UINT32|0x4c + [PcdsDynamic, PcdsDynamicEx] gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc index 982ecaf70e..cd6189f330 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.dsc +++ b/OvmfPkg/AmdSev/AmdSevX64.dsc @@ -623,6 +623,7 @@ UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf UefiCpuPkg/CpuMpPei/CpuMpPei.inf OvmfPkg/AmdSev/SecretPei/SecretPei.inf + OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf !if $(TPM_ENABLE) == TRUE OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf index 9bf17b8d51..a8e296e641 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.fdf +++ b/OvmfPkg/AmdSev/AmdSevX64.fdf @@ -36,10 +36,10 @@ FV = SECFV [FD.MEMFD] BaseAddress = $(MEMFD_BASE_ADDRESS) -Size = 0xD0 +Size = 0xE0 ErasePolarity = 1 BlockSize = 0x1 -NumBlocks = 0xD0 +NumBlocks = 0xE0 0x00|0x006000 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize @@ -71,11 +71,14 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.P 0x01|0x01 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize -0x02|0x0E +0x02|0x003000 +gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase|gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxSize + +0x12|0x0E gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize FV = PEIFV -0x10|0xC0 +0x20|0xC0 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize FV = DXEFV @@ -148,6 +151,7 @@ INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf INF UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf INF UefiCpuPkg/CpuMpPei/CpuMpPei.inf INF OvmfPkg/AmdSev/SecretPei/SecretPei.inf +INF OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf !if $(TPM_ENABLE) == TRUE INF OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf new file mode 100644 index 00..918cf22abd --- /dev/null +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf @@ -0,0 +1,35 @@ +## @file +# PEI support for confidential migration. +# +# Copyright (C) 2021 IBM Corporation. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION= 0x00010005 + BASE_NAME = ConfidentialMigration + FILE_GUID = a747792e-71a1-4c24-84a9-a76a0a279878 + MODULE_TYPE= PEIM + VERSION_STRING = 1.0 + ENTRY_POINT= InitializeConfidentialMigrationPei + +[Sources] + ConfidentialMigrationPei.c + +[Packages] + OvmfPkg/OvmfPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + HobLib + PeimEntryPoint + PcdLib + +[FixedPcd] + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxSize + +[Depex] + TRUE diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.c b/OvmfPkg/AmdSev/ConfidentialMigration
[edk2-devel] [RFC PATCH 2/9] OvmfPkg/PlatfomPei: Set Confidential Migration PCD
Confidential Migration relies on two boolean PCDs set from FW_CFG Signed-off-by: Tobin Feldman-Fitzthum --- OvmfPkg/PlatformPei/PlatformPei.inf | 2 ++ OvmfPkg/PlatformPei/Platform.c | 10 ++ 2 files changed, 12 insertions(+) diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf index 89d1f76368..2d92184c19 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -89,6 +89,8 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase + gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler + gUefiOvmfPkgTokenSpaceGuid.PcdIsConfidentialMigrationTarget gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c index d3a20122a2..f0963aaba9 100644 --- a/OvmfPkg/PlatformPei/Platform.c +++ b/OvmfPkg/PlatformPei/Platform.c @@ -272,6 +272,15 @@ NoexecDxeInitialization ( UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdSetNxForStack); } +VOID +ConfidentialMigrationInitialization ( + VOID + ) +{ + UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdStartConfidentialMigrationHandler); + UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdIsConfidentialMigrationTarget); +} + VOID PciExBarInitialization ( VOID @@ -742,6 +751,7 @@ InitializePlatform ( InstallClearCacheCallback (); AmdSevInitialize (); + ConfidentialMigrationInitialization (); MiscInitialization (); InstallFeatureControlCallback (); -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#79519): https://edk2.groups.io/g/devel/message/79519 Mute This Topic: https://groups.io/mt/84982980/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 1/9] OvmfPkg/AmdSev: Base for Confidential Migration Handler
Base enablement of DXE driver that supports confidential migration. Signed-off-by: Tobin Feldman-Fitzthum --- OvmfPkg/OvmfPkg.dec | 5 ++ OvmfPkg/AmdSev/AmdSevX64.dsc | 1 + OvmfPkg/AmdSev/AmdSevX64.fdf | 1 + .../ConfidentialMigrationDxe.inf | 34 .../ConfidentialMigrationDxe.c| 53 +++ 5 files changed, 94 insertions(+) create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 3978852557..cfc645619d 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -370,6 +370,11 @@ # instance in PiSmmCpuDxeSmm, and CpuHotplugSmm. gUefiOvmfPkgTokenSpaceGuid.PcdCpuHotEjectDataAddress|0|UINT64|0x46 + ## Set via FW_CFG to enable confidential migration as source or target. + # + gUefiOvmfPkgTokenSpaceGuid.PcdIsConfidentialMigrationTarget|FALSE|BOOLEAN|0x49 + gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler|FALSE|BOOLEAN|0x4a + [PcdsFeatureFlag] gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0x1c gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN|0x1d diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc index e6cd10b759..982ecaf70e 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.dsc +++ b/OvmfPkg/AmdSev/AmdSevX64.dsc @@ -790,6 +790,7 @@ !endif OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf OvmfPkg/AmdSev/Grub/Grub.inf + OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf !if $(BUILD_SHELL) == TRUE ShellPkg/Application/Shell/Shell.inf { diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf index 0a89749700..9bf17b8d51 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.fdf +++ b/OvmfPkg/AmdSev/AmdSevX64.fdf @@ -274,6 +274,7 @@ INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf !endif INF OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf INF OvmfPkg/AmdSev/Grub/Grub.inf +INF OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf !if $(BUILD_SHELL) == TRUE INF ShellPkg/Application/Shell/Shell.inf !endif diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf new file mode 100644 index 00..6e3fa7e51c --- /dev/null +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf @@ -0,0 +1,34 @@ +## @file +# +# Copyright (C) 2021 IBM Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION= 0x00010005 + BASE_NAME = ConfidentialMigration + FILE_GUID = 5c2978f4-f175-434b-9e6c-9b03bd7e346f + MODULE_TYPE= DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT= SetupMigrationHandler + +[Sources] + ConfidentialMigrationDxe.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + DebugLib + MemoryAllocationLib + UefiDriverEntryPoint + UefiLib + +[Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdIsConfidentialMigrationTarget + gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler + +[Depex] + TRUE diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c new file mode 100644 index 00..f0dfbd279e --- /dev/null +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c @@ -0,0 +1,53 @@ +/** @file + In-guest support for confidential migration + + Copyright (C) 2021 IBM Coporation. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include + +VOID +EFIAPI +MigrationHandlerMain () +{ + DebugPrint (DEBUG_INFO,"Migration Handler Started\n"); + +} + +/** +SetupMigrationHandler runs in the firmware of the main VM to setup +regions of memory that the Migration Handler can use when executing +in the mirror VM. + +**/ +EFI_STATUS +EFIAPI +SetupMigrationHandler ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + if (!PcdGetBool(PcdStartConfidentialMigrationHandler)) { +return 0; + } + + // + // If VM is migration target, wait until hypervisor modifies CPU state + // and restarts execution. + // + if (PcdGetBool(PcdIsConfidentialMigrationTarget)) { +DebugPrint (DEBUG_INFO,"Waiting for incoming confidential migration.\n"); + +while (1) { + CpuPause (); +} + } + + // + // If VM is migration source, continue with boot. + // + return 0; +} -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#79518): https://edk2.groups.io/g/devel/message/79518 Mute This Topic: https://groups.io/mt/84982979/21656 Group Owner: devel+
[edk2-devel] [RFC PATCH 0/9] Firmware Support for Fast Live Migration for AMD SEV
With AMD SEV the hypervisor cannot decrypt or move guest memory pages. This makes migration tricky. While the AMD Secure Processor can export/import pages wrapped with a transport key, the bandwidth is limited. We look to provide similar support via firmware. In particular, we implement a Migration Handler (MH) in OVMF. The MH runs in a separate mirror VM that shares the memory of the guest. To migrate a guest, the HV asks the MH on the source to export wrapped pages, which the MH on the target will import. To start the MH on the source or the target the HV boots the mirror VM to a custom entry vector implemented in these patches. This RFC does not include encryption support. The pages are passed to/from the HV in plaintext. This RFC depends on mirror VM support already upstreamed in KVM, AMD page encryption status tracking (Ashish Kalra's v6 OVMF live migration patches), mirror VM support in QEMU (Ashish's v1 QEMU RFC), page encryption status tracking support in QEMU (Ashish QEMU guest live migration support v4), and MH support in QEMU (coming soon). This RFC is aimed at SEV only. The general design carries over to SEV-ES and SEV-SNP, but extra support is required. Dov Murik (1): OvmfPkg/AmdSev: Build page table for migration handler Tobin Feldman-Fitzthum (8): OvmfPkg/AmdSev: Base for Confidential Migration Handler OvmfPkg/PlatfomPei: Set Confidential Migration PCD OvmfPkg/AmdSev: Setup Migration Handler Mailbox OvmfPkg/AmdSev: MH support for mailbox protocol OvmfPkg/AmdSev: Don't overwrite mailbox or pagetables OvmfPkg/AmdSev: Don't overwrite MH stack OvmfPkg/AmdSev: Add Migration Handler entry point OvmfPkg/ResetVector: Expose Migration Handler Entry Addresses OvmfPkg/OvmfPkg.dec | 13 + OvmfPkg/AmdSev/AmdSevX64.dsc | 2 + OvmfPkg/AmdSev/AmdSevX64.fdf | 16 +- .../ConfidentialMigrationDxe.inf | 38 +++ .../ConfidentialMigrationPei.inf | 37 +++ OvmfPkg/PlatformPei/PlatformPei.inf | 2 + OvmfPkg/ResetVector/ResetVector.inf | 1 + .../ConfidentialMigration/VirtualMemory.h | 177 .../ConfidentialMigrationDxe.c| 272 ++ .../ConfidentialMigrationPei.c| 31 ++ OvmfPkg/PlatformPei/Platform.c| 10 + .../MigrationEntryPoint.nasm | 51 OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 13 + OvmfPkg/ResetVector/ResetVector.nasmb | 1 + 14 files changed, 660 insertions(+), 4 deletions(-) create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.c create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/MigrationEntryPoint.nasm -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#79517): https://edk2.groups.io/g/devel/message/79517 Mute This Topic: https://groups.io/mt/84982978/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [RFC PATCH 00/14] Firmware Support for Fast Live Migration for AMD SEV
On 3/12/21 9:32 PM, Yao, Jiewen wrote: Hi We discuss the patch internally. We do see PROs and CONs with this approach. The advantage is that it is very simple. In-VM migration can save lots of effort on security context restore. On the other hand, we feel not so comfortable to reserve a dedicate CPU to achieve that. Similar to the feedback in the community. Using Hot-Plug is not a solution for Intel TDX as well. It is unsupported now. I like the idea to diverge the migration boot mode v.s. normal boot mode in SEC phase. We must be very carefully handle this migration boot mode, to avoid any touching on system memory. Intel TDX Virtual Firmware skips the PEI phase directly. If we choose this approach, SEC-based migration is our preference. Besides this patch, we would like to understand a full picture. 1) How the key is passed from source VM to destination? I saw you mentions: "Key sharing is out of scope for this part of the RFC." "This will probably be implemented via inject-launch-secret in the future" Does that mean two PSP will sync with each other and negotiate the key, after the Migration Agent (MA) checks the policy? The source and destination migration handlers will need to share a key. If we only relied on the PSP for migration, we could use the existing secure channel between the PSP and the guest owner to transfer the pages. Unfortunately the throughput of this approach is far too low. Thus, we have some migration handler running on a guest vCPU with a transport key shared between the source and the target. The main mechanism for getting a key to the migration handler is inject-launch-secret. Here the guest owner can provide a secret to the PSP via a secure channel and the PSP will inject it at some guest physical address. You use inject-launch-secret after the launch measurement of the guest has been generated to inject the secret conditionally. One approach would be to inject the transport key directly in the source and the target. This is pretty simple, but might have a few drawbacks. The injection has to happen at boot, meaning that the source machine would have to be provisioned with a transport key before a migration happens and that all migrations from that machine would have to use the same transport key. One way around this would be to inject asymmetric keys and use them to derive the transport key. Another approach entirely is to use the PSP to migrate just a few pages, which might include a secret set by the source MH that the target MH could use to decrypt incoming pages. Using the PSP to migrate pages requires some extra kernel support. For the RFC, we just assume that there is some shared key. We have talked some about the various options internally. 2) How the attestation is supported? I read the whitepaper https://www.amd.com/system/files/TechDocs/SEV-SNP-strengthening-vm-isolation-with-integrity-protection-and-more.pdf. It seems SEV and SEV-ES only support attestation during launch, I don't believe this migration feature will impact the attestation report. Am I right? SEV-SNP supports more flexible attestation, does it include any information about the new migrated content? Brijesh already addressed most of this. In our approach the MH is baked into the firmware, which can be attested prior to injecting the key. In other words there aren't any additional steps to attest the MH and it does not change the functionality of any existing attestation mechanisms. -Tobin -Original Message- From: devel@edk2.groups.io On Behalf Of Yao, Jiewen Sent: Thursday, March 4, 2021 9:49 AM To: devel@edk2.groups.io; to...@linux.ibm.com Cc: Dov Murik ; Tobin Feldman-Fitzthum ; James Bottomley ; Hubertus Franke ; Brijesh Singh ; Ashish Kalra ; Jon Grimm ; Tom Lendacky ; Yao, Jiewen Subject: Re: [edk2-devel] [RFC PATCH 00/14] Firmware Support for Fast Live Migration for AMD SEV Hi Tobin Thanks for your patch. You may that Intel is working on TDX for the same live migration feature. Please give me some time (about 1 work week) to digest and evaluate the patch and impact. Then I will provide feedback. Thank you Yao Jiewen -Original Message- From: devel@edk2.groups.io On Behalf Of Tobin Feldman-Fitzthum Sent: Wednesday, March 3, 2021 4:48 AM To: devel@edk2.groups.io Cc: Dov Murik ; Tobin Feldman-Fitzthum ; Tobin Feldman-Fitzthum ; James Bottomley ; Hubertus Franke ; Brijesh Singh ; Ashish Kalra ; Jon Grimm ; Tom Lendacky Subject: [edk2-devel] [RFC PATCH 00/14] Firmware Support for Fast Live Migration for AMD SEV This is a demonstration of fast migration for encrypted virtual machines using a Migration Handler that lives in OVMF. This demo uses AMD SEV, but the ideas may generalize to other confidential computing platforms. With AMD SEV, guest memory is encrypted and the hypervisor cannot access or move it. This makes migration tricky. In this demo, we show how the HV can ask a Migration Handler
Re: [edk2-devel] [RFC PATCH 00/14] Firmware Support for Fast Live Migration for AMD SEV
On Fri, Mar 05, 2021 at 10:44:23AM +, Ashish Kalra wrote: On Wed, Mar 03, 2021 at 01:25:40PM -0500, Tobin Feldman-Fitzthum wrote: Hi Tobin, On 03/02/21 21:48, Tobin Feldman-Fitzthum wrote: This is a demonstration of fast migration for encrypted virtual machines using a Migration Handler that lives in OVMF. This demo uses AMD SEV, but the ideas may generalize to other confidential computing platforms. With AMD SEV, guest memory is encrypted and the hypervisor cannot access or move it. This makes migration tricky. In this demo, we show how the HV can ask a Migration Handler (MH) in the firmware for an encrypted page. The MH encrypts the page with a transport key prior to releasing it to the HV. The target machine also runs an MH that decrypts the page once it is passed in by the target HV. These patches are not ready for production, but the are a full end-to-end solution that facilitates a fast live migration between two SEV VMs. Corresponding patches for QEMU have been posted my colleague Dov Murik on qemu-devel. Our approach needs little kernel support, requiring only one hypercall that the guest can use to mark a page as encrypted or shared. This series includes updated patches from Ashish Kalra and Brijesh Singh that allow OVMF to use this hypercall. The MH runs continuously in the guest, waiting for communication from the HV. The HV starts an additional vCPU for the MH but does not expose it to the guest OS via ACPI. We use the MpService to start the MH. The MpService is only available at runtime and processes that are started by it are usually cleaned up on ExitBootServices. Since we need the MH to run continuously, we had to make some modifications. Ideally a feature could be added to the MpService to allow for the starting of long-running processes. Besides migration, this could support other background processes that need to operate within the encryption boundary. For now, we have included a handful of patches that modify the MpService to allow the MH to keep running after ExitBootServices. These are temporary. I plan to do a lightweight review for this series. (My understanding is that it's an RFC and not actually being proposed for merging.) Regarding the MH's availability at runtime -- does that necessarily require the isolation of an AP? Because in the current approach, allowing the MP Services to survive into OS runtime (in some form or another) seems critical, and I don't think it's going to fly. I agree that the UefiCpuPkg patches have been well separated from the rest of the series, but I'm somewhat doubtful the "firmware-initiated background process" idea will be accepted. Have you investigated exposing a new "runtime service" (a function pointer) via the UEFI Configuration table, and calling that (perhaps periodically?) from the guest kernel? It would be a form of polling I guess. Or maybe, poll the mailbox directly in the kernel, and call the new firmware runtime service when there's an actual command to process. Continuous runtime availability for the MH is almost certainly the most controversial part of this proposal, which is why I put it in the cover letter and why it's good to discuss. (You do spell out "little kernel support", and I'm not sure if that's a technical benefit, or a political / community benefit.) As you allude to, minimal kernel support is really one of the main things that shapes our approach. This is partly a political and practical benefit, but there are also technical benefits. Having the MH in firmware likely leads to higher availability. It can be accessed when the OS is unreachable, perhaps during boot or when the OS is hung. There are also potential portability advantages although we do currently require support for one hypercall. The cost of implementing this hypercall is low. Generally speaking, our task is to find a home for functionality that was traditionally provided by the hypervisor, but that needs to be inside the trust domain, but that isn't really part of a guest. A meta-goal of this project is to figure out the best way to do this. I'm quite uncomfortable with an attempt to hide a CPU from the OS via ACPI. The OS has other ways to learn (for example, a boot loader could use the MP services itself, stash the information, and hand it to the OS kernel -- this would minimally allow for detecting an inconsistency in the OS). What about "all-but-self" IPIs too -- the kernel might think all the processors it's poking like that were under its control. This might be the second most controversial piece. Here's a question: if we could successfully hide the MH vCPU from the OS, would it still make you uncomfortable? In other words, is the worry that there might be some inconsistency or more generally that there is something hidden from the OS? One thing to think about is that the guest owner should generally be aware that there is a migration handler running. The way I see it, a guest owner of an
Re: [edk2-devel] [RFC PATCH 00/14] Firmware Support for Fast Live Migration for AMD SEV
Hi Tobin, On 03/02/21 21:48, Tobin Feldman-Fitzthum wrote: This is a demonstration of fast migration for encrypted virtual machines using a Migration Handler that lives in OVMF. This demo uses AMD SEV, but the ideas may generalize to other confidential computing platforms. With AMD SEV, guest memory is encrypted and the hypervisor cannot access or move it. This makes migration tricky. In this demo, we show how the HV can ask a Migration Handler (MH) in the firmware for an encrypted page. The MH encrypts the page with a transport key prior to releasing it to the HV. The target machine also runs an MH that decrypts the page once it is passed in by the target HV. These patches are not ready for production, but the are a full end-to-end solution that facilitates a fast live migration between two SEV VMs. Corresponding patches for QEMU have been posted my colleague Dov Murik on qemu-devel. Our approach needs little kernel support, requiring only one hypercall that the guest can use to mark a page as encrypted or shared. This series includes updated patches from Ashish Kalra and Brijesh Singh that allow OVMF to use this hypercall. The MH runs continuously in the guest, waiting for communication from the HV. The HV starts an additional vCPU for the MH but does not expose it to the guest OS via ACPI. We use the MpService to start the MH. The MpService is only available at runtime and processes that are started by it are usually cleaned up on ExitBootServices. Since we need the MH to run continuously, we had to make some modifications. Ideally a feature could be added to the MpService to allow for the starting of long-running processes. Besides migration, this could support other background processes that need to operate within the encryption boundary. For now, we have included a handful of patches that modify the MpService to allow the MH to keep running after ExitBootServices. These are temporary. I plan to do a lightweight review for this series. (My understanding is that it's an RFC and not actually being proposed for merging.) Regarding the MH's availability at runtime -- does that necessarily require the isolation of an AP? Because in the current approach, allowing the MP Services to survive into OS runtime (in some form or another) seems critical, and I don't think it's going to fly. I agree that the UefiCpuPkg patches have been well separated from the rest of the series, but I'm somewhat doubtful the "firmware-initiated background process" idea will be accepted. Have you investigated exposing a new "runtime service" (a function pointer) via the UEFI Configuration table, and calling that (perhaps periodically?) from the guest kernel? It would be a form of polling I guess. Or maybe, poll the mailbox directly in the kernel, and call the new firmware runtime service when there's an actual command to process. Continuous runtime availability for the MH is almost certainly the most controversial part of this proposal, which is why I put it in the cover letter and why it's good to discuss. (You do spell out "little kernel support", and I'm not sure if that's a technical benefit, or a political / community benefit.) As you allude to, minimal kernel support is really one of the main things that shapes our approach. This is partly a political and practical benefit, but there are also technical benefits. Having the MH in firmware likely leads to higher availability. It can be accessed when the OS is unreachable, perhaps during boot or when the OS is hung. There are also potential portability advantages although we do currently require support for one hypercall. The cost of implementing this hypercall is low. Generally speaking, our task is to find a home for functionality that was traditionally provided by the hypervisor, but that needs to be inside the trust domain, but that isn't really part of a guest. A meta-goal of this project is to figure out the best way to do this. I'm quite uncomfortable with an attempt to hide a CPU from the OS via ACPI. The OS has other ways to learn (for example, a boot loader could use the MP services itself, stash the information, and hand it to the OS kernel -- this would minimally allow for detecting an inconsistency in the OS). What about "all-but-self" IPIs too -- the kernel might think all the processors it's poking like that were under its control. This might be the second most controversial piece. Here's a question: if we could successfully hide the MH vCPU from the OS, would it still make you uncomfortable? In other words, is the worry that there might be some inconsistency or more generally that there is something hidden from the OS? One thing to think about is that the guest owner should generally be aware that there is a migration handler running. The way I see it, a guest owner of an SEV VM would need to opt-in to migration and should then expect that there is an MH running even if they a
Re: [edk2-devel] [RFC PATCH 03/14] OvmfPkg/PlatformDxe: Add support for SEV live migration.
On 3/3/21 11:41 AM, Ashish Kalra wrote: Hello Tobin, You don't need this patch for MH support, this patch is only required for (SEV) slow migration support. If the SevLiveMigrationEnabled variable is not set, the bitmap sync does not work correctly (bitmap all zeros), at least for the version of the kernel we have been using. Since the bitmap will be replaced, this might not be necessary in the future but it is for our setup at the moment. -Tobin Thanks, Ashish On Tue, Mar 02, 2021 at 03:48:28PM -0500, Tobin Feldman-Fitzthum wrote: From: Ashish Kalra Detect for KVM hypervisor and check for SEV live migration feature support via KVM_FEATURE_CPUID, if detected setup a new UEFI enviroment variable to indicate OVMF support for SEV live migration. Signed-off-by: Ashish Kalra --- OvmfPkg/OvmfPkg.dec | 1 + OvmfPkg/PlatformDxe/Platform.inf | 2 + OvmfPkg/Include/Guid/MemEncryptLib.h | 16 + OvmfPkg/PlatformDxe/PlatformConfig.h | 5 ++ OvmfPkg/PlatformDxe/AmdSev.c | 99 OvmfPkg/PlatformDxe/Platform.c | 6 ++ 6 files changed, 129 insertions(+) create mode 100644 OvmfPkg/Include/Guid/MemEncryptLib.h create mode 100644 OvmfPkg/PlatformDxe/AmdSev.c diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 4348bb45c6..4450d78b91 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -122,6 +122,7 @@ gQemuKernelLoaderFsMediaGuid = {0x1428f772, 0xb64a, 0x441e, {0xb8, 0xc3, 0x9e, 0xbd, 0xd7, 0xf8, 0x93, 0xc7}} gGrubFileGuid = {0xb5ae312c, 0xbc8a, 0x43b1, {0x9c, 0x62, 0xeb, 0xb8, 0x26, 0xdd, 0x5d, 0x07}} gConfidentialComputingSecretGuid = {0xadf956ad, 0xe98c, 0x484c, {0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}} + gMemEncryptGuid = {0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}} [Ppis] # PPI whose presence in the PPI database signals that the TPM base address diff --git a/OvmfPkg/PlatformDxe/Platform.inf b/OvmfPkg/PlatformDxe/Platform.inf index 14727c1220..2896f0a1d1 100644 --- a/OvmfPkg/PlatformDxe/Platform.inf +++ b/OvmfPkg/PlatformDxe/Platform.inf @@ -24,6 +24,7 @@ PlatformConfig.c PlatformConfig.h PlatformForms.vfr + AmdSev.c [Packages] MdePkg/MdePkg.dec @@ -56,6 +57,7 @@ [Guids] gEfiIfrTianoGuid gOvmfPlatformConfigGuid + gMemEncryptGuid [Depex] gEfiHiiConfigRoutingProtocolGuid AND diff --git a/OvmfPkg/Include/Guid/MemEncryptLib.h b/OvmfPkg/Include/Guid/MemEncryptLib.h new file mode 100644 index 00..8264a647af --- /dev/null +++ b/OvmfPkg/Include/Guid/MemEncryptLib.h @@ -0,0 +1,16 @@ +/** @file + AMD Memory Encryption GUID, define a new GUID for defining + new UEFI enviroment variables assocaiated with SEV Memory Encryption. + Copyright (c) 2020, AMD Inc. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __MEMENCRYPT_LIB_H__ +#define __MEMENCRYPT_LIB_H__ + +#define MEMENCRYPT_GUID \ +{0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}} + +extern EFI_GUID gMemEncryptGuid; + +#endif diff --git a/OvmfPkg/PlatformDxe/PlatformConfig.h b/OvmfPkg/PlatformDxe/PlatformConfig.h index 716514da21..4f662aafa4 100644 --- a/OvmfPkg/PlatformDxe/PlatformConfig.h +++ b/OvmfPkg/PlatformDxe/PlatformConfig.h @@ -44,6 +44,11 @@ PlatformConfigLoad ( OUT UINT64 *OptionalElements ); +VOID +AmdSevSetConfig( + VOID + ); + // // Feature flags for OptionalElements. // diff --git a/OvmfPkg/PlatformDxe/AmdSev.c b/OvmfPkg/PlatformDxe/AmdSev.c new file mode 100644 index 00..1f804984b7 --- /dev/null +++ b/OvmfPkg/PlatformDxe/AmdSev.c @@ -0,0 +1,99 @@ +/**@file + Detect KVM hypervisor support for SEV live migration and if + detected, setup a new UEFI enviroment variable indicating + OVMF support for SEV live migration. + Copyright (c) 2020, Advanced Micro Devices. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +// +// The package level header files this module uses +// + +#include +#include +#include +#include +#include +#include + +/** + Figures out if we are running inside KVM HVM and + KVM HVM supports SEV Live Migration feature. + @retval TRUE KVM was detected and Live Migration supported + @retval FALSE KVM was not detected or Live Migration not supported +**/ +BOOLEAN +KvmDetectSevLiveMigrationFeature( + VOID + ) +{ + UINT8 Signature[13]; + UINT32 mKvmLeaf = 0; + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + + Signature[12] = '\0'; + for (mKvmLeaf = 0x4000; mKvmLeaf < 0x4001; mKvmLeaf += 0x100) { +AsmCpuid (mKvmLeaf, + NULL, + (UINT32 *) [0], + (UINT32 *) [4], + (UINT32 *) [8]); + +if (!AsciiStrCmp ((CHAR8 *) Signature, "KVMKVMKVM\0\0\0")) { + DEBUG (( +DEBUG_ERROR, +"%a: KVM Detected, signature = %s\n", +__FUN
Re: [edk2-devel] [RFC PATCH 02/14] OvmfPkg/PlatformPei: Mark SEC GHCB page in the page encrpytion bitmap.
Hello Tobin, Just a high level question, why is this patch included in this patch series, i don't think you are supporting SEV-ES platform migration in this patch-set ? You are correct that we don't support migration for SEV-ES machines, although our approach can potentially be adapted for SEV-ES. I was on the fence about including this patch, because we don't strictly need it for migration. I'm not sure if the SEC GHCB would be significant even if we did support SEV-ES migration. Ultimately it seemed like a good idea because the SEV firmware build does otherwise support SEV-ES. Since I was introducing the hypercall in an environment where SEV-ES can be enabled, it seemed reasonable to include. Syncing page encryption status hypothetically has uses beyond migration. Note that I am not adding full support for the hypercall in OVMF, which might be a good idea at some point. -Tobin Thanks, Ashish On Tue, Mar 02, 2021 at 03:48:27PM -0500, Tobin Feldman-Fitzthum wrote: From: Ashish Kalra Mark the SEC GHCB page that is mapped as unencrypted in ResetVector code in the hypervisor page encryption bitmap. Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Ashish Kalra --- OvmfPkg/PlatformPei/AmdSev.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c index dddffdebda..c72eeb37c5 100644 --- a/OvmfPkg/PlatformPei/AmdSev.c +++ b/OvmfPkg/PlatformPei/AmdSev.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,15 @@ AmdSevEsInitialize ( PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE); ASSERT_RETURN_ERROR (PcdStatus); + // + // GHCB_BASE setup during reset-vector needs to be marked as + // decrypted in the hypervisor page encryption bitmap. + // + SetMemoryEncDecHypercall3 (FixedPcdGet32 (PcdOvmfSecGhcbBase), +EFI_SIZE_TO_PAGES(FixedPcdGet32 (PcdOvmfSecGhcbSize)), +FALSE +); + // // Allocate GHCB and per-CPU variable pages. // Since the pages must survive across the UEFI to OS transition -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#72388): https://edk2.groups.io/g/devel/message/72388 Mute This Topic: https://groups.io/mt/81036364/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 07/14] OvmfPkg/AmdSev: MH support for mailbox protocol
The migration handler communicates with the hypervisor via a shared mailbox page. The MH can perform four functions at the behest of the HV: init, save page, restore page, and reset. Signed-off-by: Tobin Feldman-Fitzthum --- .../ConfidentialMigrationDxe.inf | 1 + .../ConfidentialMigrationDxe.c| 78 +++ 2 files changed, 79 insertions(+) diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf index a4906a2451..49457d5d17 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf @@ -34,6 +34,7 @@ [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdIsConfidentialMigrationTarget gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase [Depex] gEfiMpServiceProtocolGuid diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c index 6d9fe7043b..8402fcc4fa 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c @@ -9,16 +9,94 @@ #include #include #include +#include +// +// Functions implemented by the migration handler +// +#define MH_FUNC_INIT 0 +#define MH_FUNC_SAVE_PAGE 1 +#define MH_FUNC_RESTORE_PAGE 2 +#define MH_FUNC_RESET 3 + +// +// Return codes for MH functions +// +#define MH_SUCCESS0 +#define MH_INVALID_FUNC (-1) +#define MH_AUTH_ERR (-2) + +// +// Index of CPU that MH runs on. +// UINTN MigrationHandlerCpuIndex; +// +// Mailbox for communication with hypervisor +// +typedef volatile struct { + UINT64 nr; + UINT64 gpa; + UINT32 do_prefetch; + UINT32 ret; + UINT32 go; + UINT32 done; +} MH_COMMAND_PARAMETERS; + + VOID EFIAPI MigrationHandlerMain ( IN OUT VOID *Buffer ) { + UINT64 params_base; + MH_COMMAND_PARAMETERS*params; + VOID *page_va; + DebugPrint (DEBUG_INFO,"MIGRATION Handler Started\n"); + + params_base = PcdGet32 (PcdConfidentialMigrationMailboxBase); + params = (VOID *)params_base; + page_va = (VOID *)params_base + 0x1000; + + DisableInterrupts(); + params->go = 0; + + while (1) { +while (!params->go) { + CpuPause(); +} +params->done = 0; + +switch (params->nr) { +case MH_FUNC_INIT: + params->ret = MH_SUCCESS; + break; + +case MH_FUNC_SAVE_PAGE: + CopyMem(page_va, (VOID *)params->gpa, 4096); + params->ret = MH_SUCCESS; + break; + +case MH_FUNC_RESTORE_PAGE: + CopyMem((VOID *)params->gpa, page_va, 4096); + params->ret = MH_SUCCESS; + break; + +case MH_FUNC_RESET: + params->ret = MH_SUCCESS; + break; + +default: + params->ret = MH_INVALID_FUNC; + break; +} + +params->go = 0; +params->done = 1; + + } } EFI_STATUS -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#72365): https://edk2.groups.io/g/devel/message/72365 Mute This Topic: https://groups.io/mt/81036401/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 14/14] OvmfPkg/AmdSev: MH page encryption POC
This code is for demonstration purposes only. It is not secure or robust. The purpose is to show where encryption will be incorporated and to get a sense of the performance impact of adding encryption. We plan to use AES-GCM to encrypt the pages as a stream. This will also allow us to verify the GPA as part of the AAD, ensuring that a malicious hypervisor hasn't exchanged pages in-flight. Currently the CryptoPkg and the BaseCryptLib do not expose AES-GCM, despite it being included in OpensslLib. Thus, we use CBC here. Key sharing is out of scope for this part of the RFC. We assume that the source and destination MH share a key. This will probably be implemented via inject-launch-secret in the future. For now, we hardcode a key, but this is strictly temporary. We have had trouble using RandomBytes() in the MH when SEV is enabled. Thus the IV is hardcoded. Again, this is temporary. The HV and the MH will exchange information pertaining to encryption, like the IV, via an additional header on the shared mailbox page. This patch does not do any safety checks or handle encrypt/decrypt failures. Again, this is only here to show where encryption will go and generally how the MH on the source and target can share pages without exposing guest memory to the HV. Signed-off-by: Tobin Feldman-Fitzthum --- .../ConfidentialMigrationDxe.inf | 2 ++ .../ConfidentialMigrationDxe.c| 36 +-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf index 2816952863..ae074a8b07 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf @@ -22,6 +22,7 @@ MdePkg/MdePkg.dec OvmfPkg/OvmfPkg.dec UefiCpuPkg/UefiCpuPkg.dec + CryptoPkg/CryptoPkg.dec [LibraryClasses] MemoryAllocationLib @@ -29,6 +30,7 @@ UefiBootServicesTableLib MpInitLib UefiDriverEntryPoint + BaseCryptLib [Protocols] gEfiMpServiceProtocolGuid diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c index 42b99be552..a9cb490561 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "VirtualMemory.h" #include "MpLib.h" @@ -46,6 +47,14 @@ typedef volatile struct { UINT32 done; } MH_COMMAND_PARAMETERS; +// +// Additional header for encryption support. +// +struct page_hdr { + UINT8IV[16]; + UINT8tag[16]; +}; + // // Addresses for MH page table. // @@ -57,6 +66,20 @@ STATIC PHYSICAL_ADDRESS mMigrationHelperPageTables = 0; // #define UNENC_VIRT_ADDR_BASE0xff80ULL +// +// Key shared between source and target MH (temporary) +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 cipher_key[] = { + 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0, 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a + }; + +// +// IV for CBC cipher (temporary). We are having trouble with +// calling RandomBytes from inside the Migration Handler +// +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 Ivec[] = { + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 +}; /** Allocates and fills in custom page tables for Migration Handler. @@ -159,6 +182,8 @@ MigrationHandlerMain ( UINT64 params_base; MH_COMMAND_PARAMETERS*params; VOID *page_va; + VOID *cipher_ctx; + INTN ctx_size; DebugPrint (DEBUG_INFO,"MIGRATION Handler Started\n"); @@ -171,6 +196,7 @@ MigrationHandlerMain ( params_base = mailbox_start + UNENC_VIRT_ADDR_BASE; params = (VOID *)params_base; page_va = (VOID *)params_base + 0x1000; + //struct page_hdr *hdr_va = (void *) params_base + 0x800; mailbox_end = mailbox_start + 2 * EFI_PAGE_SIZE; @@ -180,6 +206,9 @@ MigrationHandlerMain ( stack_end = GetMHTopOfStack(); stack_start = stack_end - PcdGet32(PcdCpuApStackSize); + ctx_size = AesGetContextSize (); + cipher_ctx = AllocateRuntimePool (ctx_size); + DisableInterrupts(); params->go = 0; @@ -195,7 +224,9 @@ MigrationHandlerMain ( break; case MH_FUNC_SAVE_PAGE: - CopyMem(page_va, (VOID *)params->gpa, 4096); + AesInit (cipher_ctx, cipher_key, 128); + AesCbcEncrypt(cipher_ctx, (VOID *)params->gpa, 4096, Ivec, page_va); + params->ret = MH_SUCCESS; break; @@ -208,7 +239,8 @@ MigrationHandlerMain ( (params->gpa >= stack_start && params->gpa < stack_end)) { } else { -CopyMem((VOID *)params->gpa, page_va, 4096); +AesInit (cipher_ctx, cipher_key, 128
[edk2-devel] [RFC PATCH 13/14] OvmfPkg/AmdSev: Don't overwrite MH stack
When restoring pages, the Migration Handler shoudl avoid overwriting its own stack. Signed-off-by: Tobin Feldman-Fitzthum --- .../ConfidentialMigrationDxe.inf | 2 + OvmfPkg/AmdSev/ConfidentialMigration/MpLib.h | 235 ++ .../ConfidentialMigrationDxe.c| 30 ++- 3 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/MpLib.h diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf index 8dadfd1d13..2816952863 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf @@ -16,6 +16,7 @@ [Sources] ConfidentialMigrationDxe.c VirtualMemory.h + MpLib.h [Packages] MdePkg/MdePkg.dec @@ -36,6 +37,7 @@ gUefiOvmfPkgTokenSpaceGuid.PcdIsConfidentialMigrationTarget gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase + gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize [Depex] gEfiMpServiceProtocolGuid diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/MpLib.h b/OvmfPkg/AmdSev/ConfidentialMigration/MpLib.h new file mode 100644 index 00..5007e25243 --- /dev/null +++ b/OvmfPkg/AmdSev/ConfidentialMigration/MpLib.h @@ -0,0 +1,235 @@ +/** @file + Common header file for MP Initialize Library. + -- adapted from UefiCpuPkg/Library/MpInitLib/MpLib.h + Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved. + Copyright (c) 2020, AMD Inc. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _MP_LIB_H_ +#define _MP_LIB_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#define CPU_INIT_MP_LIB_HOB_GUID \ + { \ +0x58eb6a19, 0x3699, 0x4c68, { 0xa8, 0x36, 0xda, 0xcd, 0x8e, 0xdc, 0xad, 0x4a } \ + } + + +// +// CPU exchange information for switch BSP +// +typedef struct { + UINT8 State;// offset 0 + UINTN StackPointer; // offset 4 / 8 + IA32_DESCRIPTOR Gdtr; // offset 8 / 16 + IA32_DESCRIPTOR Idtr; // offset 14 / 26 +} CPU_EXCHANGE_ROLE_INFO; + +// +// AP initialization state during APs wakeup +// +typedef enum { + ApInitConfig = 1, + ApInitReconfig = 2, + ApInitDone = 3 +} AP_INIT_STATE; + +// +// AP state +// +// The state transitions for an AP when it process a procedure are: +// Idle > Ready > Busy > Idle +// [BSP] [AP] [AP] +// +typedef enum { + CpuStateIdle, + CpuStateReady, + CpuStateBusy, + CpuStateFinished, + CpuStateDisabled +} CPU_STATE; + +// +// CPU volatile registers around INIT-SIPI-SIPI +// +typedef struct { + UINTN Cr0; + UINTN Cr3; + UINTN Cr4; + UINTN Dr0; + UINTN Dr1; + UINTN Dr2; + UINTN Dr3; + UINTN Dr6; + UINTN Dr7; + IA32_DESCRIPTORGdtr; + IA32_DESCRIPTORIdtr; + UINT16 Tr; +} CPU_VOLATILE_REGISTERS; + +// +// AP related data +// +typedef struct { + SPIN_LOCK ApLock; + volatile UINT32*StartupApSignal; + volatile UINTN ApFunction; + volatile UINTN ApFunctionArgument; + BOOLEANCpuHealthy; + volatile CPU_STATE State; + CPU_VOLATILE_REGISTERS VolatileRegisters; + BOOLEANWaiting; + BOOLEAN*Finished; + UINT64 ExpectedTime; + UINT64 CurrentTime; + UINT64 TotalTime; + EFI_EVENT WaitEvent; + UINT32 ProcessorSignature; + UINT8 PlatformId; + UINT64 MicrocodeEntryAddr; +} CPU_AP_DATA; + +// +// Basic CPU information saved in Guided HOB. +// Because the contents will be shard between PEI and DXE, +// we need to make sure the each fields offset same in different +// architecture. +// +#pragma pack (1) +typedef struct { + UINT32 InitialApicId; + UINT32 ApicId; + UINT32 Health; + UINT64 ApTopOfStack; +} CPU_INFO_IN_HOB; +#pragma pack () + +// +// AP reset code information including code address and size, +// this structure will be shared be C code and assembly code. +// It is natural aligned by design. +// +typedef struct { + UINT8 *RendezvousFunnelAddress; + UINTN ModeEntryOffset; + UINTN RendezvousFunnelSize; + UINT8 *RelocateApLoopFuncAddress;
[edk2-devel] [RFC PATCH 11/14] OvmfPkg/AmdSev: Build page table for migration handler
From: Dov Murik 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 Signed-off-by: Dov Murik --- .../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 00..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. + Copyright (c) 2017, AMD Incorporated. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + Code is derived from OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h + +**/ + +#ifndef __VIRTUAL_MEMORY__ +#define __VIRTUAL_MEMORY__ + +#include +#include +#include +#include +#include +#include + +#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; + UINT64Uint64; +} 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; + UINT64Uint64; +} PAGE_TABLE_4K_ENTRY; + +// +// Page Table Entry 2MB +// +typedef union { + struct { +UINT64 Prese
[edk2-devel] [RFC PATCH 10/14] UefiCpuPkg/CpuExceptionHandlerLib: Exception handling as runtime memory
Reserve IDT and other exception-related memory as runtime so it won't be overwritten by the OS while the MH is running. Signed-off-by: Tobin Feldman-Fitzthum --- UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c index fd59f09ecd..35610f8cf5 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c @@ -102,7 +102,7 @@ InitializeCpuInterruptHandlers ( EFI_CPU_INTERRUPT_HANDLER *ExternalInterruptHandler; Status = gBS->AllocatePool ( - EfiBootServicesCode, + EfiRuntimeServicesCode, sizeof (RESERVED_VECTORS_DATA) * CPU_INTERRUPT_NUM, (VOID **) ); @@ -116,7 +116,7 @@ InitializeCpuInterruptHandlers ( } } - ExternalInterruptHandler = AllocateZeroPool (sizeof (EFI_CPU_INTERRUPT_HANDLER) * CPU_INTERRUPT_NUM); + ExternalInterruptHandler = AllocateRuntimeZeroPool (sizeof (EFI_CPU_INTERRUPT_HANDLER) * CPU_INTERRUPT_NUM); ASSERT (ExternalInterruptHandler != NULL); // @@ -130,7 +130,7 @@ InitializeCpuInterruptHandlers ( // // Create Interrupt Descriptor Table and Copy the old IDT table in // - IdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM); + IdtTable = AllocateRuntimeZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM); ASSERT (IdtTable != NULL); CopyMem (IdtTable, (VOID *)IdtDescriptor.Base, sizeof (IA32_IDT_GATE_DESCRIPTOR) * IdtEntryCount); @@ -138,7 +138,7 @@ InitializeCpuInterruptHandlers ( ASSERT (TemplateMap.ExceptionStubHeaderSize <= HOOKAFTER_STUB_SIZE); Status = gBS->AllocatePool ( - EfiBootServicesCode, + EfiRuntimeServicesCode, TemplateMap.ExceptionStubHeaderSize * CPU_INTERRUPT_NUM, (VOID **) ); -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#72360): https://edk2.groups.io/g/devel/message/72360 Mute This Topic: https://groups.io/mt/81036375/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 03/14] OvmfPkg/PlatformDxe: Add support for SEV live migration.
From: Ashish Kalra Detect for KVM hypervisor and check for SEV live migration feature support via KVM_FEATURE_CPUID, if detected setup a new UEFI enviroment variable to indicate OVMF support for SEV live migration. Signed-off-by: Ashish Kalra --- OvmfPkg/OvmfPkg.dec | 1 + OvmfPkg/PlatformDxe/Platform.inf | 2 + OvmfPkg/Include/Guid/MemEncryptLib.h | 16 + OvmfPkg/PlatformDxe/PlatformConfig.h | 5 ++ OvmfPkg/PlatformDxe/AmdSev.c | 99 OvmfPkg/PlatformDxe/Platform.c | 6 ++ 6 files changed, 129 insertions(+) create mode 100644 OvmfPkg/Include/Guid/MemEncryptLib.h create mode 100644 OvmfPkg/PlatformDxe/AmdSev.c diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 4348bb45c6..4450d78b91 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -122,6 +122,7 @@ gQemuKernelLoaderFsMediaGuid = {0x1428f772, 0xb64a, 0x441e, {0xb8, 0xc3, 0x9e, 0xbd, 0xd7, 0xf8, 0x93, 0xc7}} gGrubFileGuid = {0xb5ae312c, 0xbc8a, 0x43b1, {0x9c, 0x62, 0xeb, 0xb8, 0x26, 0xdd, 0x5d, 0x07}} gConfidentialComputingSecretGuid = {0xadf956ad, 0xe98c, 0x484c, {0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}} + gMemEncryptGuid = {0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}} [Ppis] # PPI whose presence in the PPI database signals that the TPM base address diff --git a/OvmfPkg/PlatformDxe/Platform.inf b/OvmfPkg/PlatformDxe/Platform.inf index 14727c1220..2896f0a1d1 100644 --- a/OvmfPkg/PlatformDxe/Platform.inf +++ b/OvmfPkg/PlatformDxe/Platform.inf @@ -24,6 +24,7 @@ PlatformConfig.c PlatformConfig.h PlatformForms.vfr + AmdSev.c [Packages] MdePkg/MdePkg.dec @@ -56,6 +57,7 @@ [Guids] gEfiIfrTianoGuid gOvmfPlatformConfigGuid + gMemEncryptGuid [Depex] gEfiHiiConfigRoutingProtocolGuid AND diff --git a/OvmfPkg/Include/Guid/MemEncryptLib.h b/OvmfPkg/Include/Guid/MemEncryptLib.h new file mode 100644 index 00..8264a647af --- /dev/null +++ b/OvmfPkg/Include/Guid/MemEncryptLib.h @@ -0,0 +1,16 @@ +/** @file + AMD Memory Encryption GUID, define a new GUID for defining + new UEFI enviroment variables assocaiated with SEV Memory Encryption. + Copyright (c) 2020, AMD Inc. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __MEMENCRYPT_LIB_H__ +#define __MEMENCRYPT_LIB_H__ + +#define MEMENCRYPT_GUID \ +{0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}} + +extern EFI_GUID gMemEncryptGuid; + +#endif diff --git a/OvmfPkg/PlatformDxe/PlatformConfig.h b/OvmfPkg/PlatformDxe/PlatformConfig.h index 716514da21..4f662aafa4 100644 --- a/OvmfPkg/PlatformDxe/PlatformConfig.h +++ b/OvmfPkg/PlatformDxe/PlatformConfig.h @@ -44,6 +44,11 @@ PlatformConfigLoad ( OUT UINT64 *OptionalElements ); +VOID +AmdSevSetConfig( + VOID + ); + // // Feature flags for OptionalElements. // diff --git a/OvmfPkg/PlatformDxe/AmdSev.c b/OvmfPkg/PlatformDxe/AmdSev.c new file mode 100644 index 00..1f804984b7 --- /dev/null +++ b/OvmfPkg/PlatformDxe/AmdSev.c @@ -0,0 +1,99 @@ +/**@file + Detect KVM hypervisor support for SEV live migration and if + detected, setup a new UEFI enviroment variable indicating + OVMF support for SEV live migration. + Copyright (c) 2020, Advanced Micro Devices. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +// +// The package level header files this module uses +// + +#include +#include +#include +#include +#include +#include + +/** + Figures out if we are running inside KVM HVM and + KVM HVM supports SEV Live Migration feature. + @retval TRUE KVM was detected and Live Migration supported + @retval FALSE KVM was not detected or Live Migration not supported +**/ +BOOLEAN +KvmDetectSevLiveMigrationFeature( + VOID + ) +{ + UINT8 Signature[13]; + UINT32 mKvmLeaf = 0; + UINT32 RegEax, RegEbx, RegEcx, RegEdx; + + Signature[12] = '\0'; + for (mKvmLeaf = 0x4000; mKvmLeaf < 0x4001; mKvmLeaf += 0x100) { +AsmCpuid (mKvmLeaf, + NULL, + (UINT32 *) [0], + (UINT32 *) [4], + (UINT32 *) [8]); + +if (!AsciiStrCmp ((CHAR8 *) Signature, "KVMKVMKVM\0\0\0")) { + DEBUG (( +DEBUG_ERROR, +"%a: KVM Detected, signature = %s\n", +__FUNCTION__, +Signature +)); + +RegEax = 0x4001; +RegEcx = 0; + AsmCpuid (0x4001, , , , ); + if (RegEax & (1 << 14)) { + DEBUG (( +DEBUG_ERROR, +"%a: Live Migration feature supported\n", +__FUNCTION__ +)); +return TRUE; + } +} + } + + return FALSE; +} + +/** + Function checks if SEV Live Migration support is available, if present then it sets + a UEFI enviroment variable to be queried later using Runtime services. + **/ +VOID +AmdSevSetConfig( + VOID + ) +{ + EFI_STATUS Status; + BOOLEAN SevLiveMigrationEnabled; + +
[edk2-devel] [RFC PATCH 01/14] OvmfPkg/BaseMemEncryptLib: Support to issue unencrypted hypercall
From: Brijesh Singh By default all the SEV guest memory regions are considered encrypted, if a guest changes the encryption attribute of the page (e.g mark a page as decrypted) then notify hypervisor. Hypervisor will need to track the unencrypted pages. The information will be used during guest live migration, guest page migration and guest debugging. Invoke hypercall via the new hypercall library. This hypercall is used to notify hypervisor when a page is marked as 'decrypted' (i.e C-bit removed). Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Brijesh Singh Signed-off-by: Ashish Kalra --- .../DxeMemEncryptSevLib.inf| 1 + .../PeiMemEncryptSevLib.inf| 1 + .../X64/PeiDxeVirtualMemory.c | 18 ++ 3 files changed, 20 insertions(+) diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf index f2e162d680..aefcd7c0f7 100644 --- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf @@ -49,6 +49,7 @@ DebugLib MemoryAllocationLib PcdLib + MemEncryptHypercallLib [FeaturePcd] gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf index 03a78c32df..7503f56a0b 100644 --- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf @@ -49,6 +49,7 @@ DebugLib MemoryAllocationLib PcdLib + MemEncryptHypercallLib [FeaturePcd] gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c index d3455e812b..98a1d2e3a8 100644 --- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "VirtualMemory.h" @@ -585,6 +586,9 @@ SetMemoryEncDec ( UINT64 AddressEncMask; BOOLEANIsWpEnabled; RETURN_STATUS Status; + UINTN Size; + BOOLEANCBitChanged; + PHYSICAL_ADDRESS OrigPhysicalAddress; // // Set PageMapLevel4Entry to suppress incorrect compiler/analyzer warnings. @@ -636,6 +640,10 @@ SetMemoryEncDec ( Status = EFI_SUCCESS; + Size = Length; + CBitChanged = FALSE; + OrigPhysicalAddress = PhysicalAddress; + while (Length != 0) { // @@ -695,6 +703,7 @@ SetMemoryEncDec ( )); PhysicalAddress += BIT30; Length -= BIT30; +CBitChanged = TRUE; } else { // // We must split the page @@ -749,6 +758,7 @@ SetMemoryEncDec ( SetOrClearCBit (>Uint64, Mode); PhysicalAddress += BIT21; Length -= BIT21; + CBitChanged = TRUE; } else { // // We must split up this page into 4K pages @@ -791,6 +801,7 @@ SetMemoryEncDec ( SetOrClearCBit (>Uint64, Mode); PhysicalAddress += EFI_PAGE_SIZE; Length -= EFI_PAGE_SIZE; +CBitChanged = TRUE; } } } @@ -808,6 +819,13 @@ SetMemoryEncDec ( // CpuFlushTlb(); + // + // Notify Hypervisor on C-bit status + // + if (CBitChanged) { +SetMemoryEncDecHypercall3 (OrigPhysicalAddress, EFI_SIZE_TO_PAGES(Size), !Mode); + } + Done: // // Restore page table write protection, if any. -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#72351): https://edk2.groups.io/g/devel/message/72351 Mute This Topic: https://groups.io/mt/81036363/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 08/14] UefiCpuPkg/MpInitLib: temp removal of MpLib cleanup
The Migration Handdler is started using the Mp Service, which is only designed to function during boot time. The MH needs to run continuously. In the abscence of a generalized persitent Mp Service, temporary alterations were made to keep the MH running. Here, we skip registering the ExitBootServices callback that would normally clean up the APs. Obviously this is not suitable for production, as it does not generalize for multiple APs (it leaves all APs untouched rather than just the MH) and it introduces a weird dependency where the MpLib needs an OVMF PCD. Signed-off-by: Tobin Feldman-Fitzthum --- UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 2 ++ UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 21 --- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf index 1771575c69..71cc968de8 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf @@ -39,6 +39,7 @@ MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec UefiCpuPkg/UefiCpuPkg.dec + OvmfPkg/OvmfPkg.dec [LibraryClasses] BaseLib @@ -76,3 +77,4 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index 7839c24976..7d59ec4a92 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -569,14 +569,19 @@ InitMpGlobalData ( ); ASSERT_EFI_ERROR (Status); - Status = gBS->CreateEvent ( - EVT_SIGNAL_EXIT_BOOT_SERVICES, - TPL_CALLBACK, - MpInitChangeApLoopCallback, - NULL, - - ); - ASSERT_EFI_ERROR (Status); + // + // Workaround for persistent processes . + // + if (!PcdGetBool (PcdStartConfidentialMigrationHandler)) { +Status = gBS->CreateEvent ( +EVT_SIGNAL_EXIT_BOOT_SERVICES, +TPL_CALLBACK, +MpInitChangeApLoopCallback, +NULL, + +); +ASSERT_EFI_ERROR (Status); + } Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#72358): https://edk2.groups.io/g/devel/message/72358 Mute This Topic: https://groups.io/mt/81036373/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 05/14] OvmfPkg/PlatfomPei: Set Confidential Migration PCD
Confidential Migration relies on two boolean PCDs set from FW_CFG Signed-off-by: Tobin Feldman-Fitzthum --- OvmfPkg/PlatformPei/PlatformPei.inf | 2 ++ OvmfPkg/PlatformPei/Platform.c | 10 ++ 2 files changed, 12 insertions(+) diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf index 6ef77ba7bb..66e6fcfa4f 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -92,6 +92,8 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase + gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler + gUefiOvmfPkgTokenSpaceGuid.PcdIsConfidentialMigrationTarget gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c index 96468701e3..5926c8d414 100644 --- a/OvmfPkg/PlatformPei/Platform.c +++ b/OvmfPkg/PlatformPei/Platform.c @@ -275,6 +275,15 @@ NoexecDxeInitialization ( UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdSetNxForStack); } +VOID +ConfidentialMigrationInitialization ( + VOID + ) +{ + UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdStartConfidentialMigrationHandler); + UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdIsConfidentialMigrationTarget); +} + VOID PciExBarInitialization ( VOID @@ -752,6 +761,7 @@ InitializePlatform ( InstallClearCacheCallback (); AmdSevInitialize (); + ConfidentialMigrationInitialization (); MiscInitialization (); InstallFeatureControlCallback (); -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#72357): https://edk2.groups.io/g/devel/message/72357 Mute This Topic: https://groups.io/mt/81036371/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 02/14] OvmfPkg/PlatformPei: Mark SEC GHCB page in the page encrpytion bitmap.
From: Ashish Kalra Mark the SEC GHCB page that is mapped as unencrypted in ResetVector code in the hypervisor page encryption bitmap. Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Ashish Kalra --- OvmfPkg/PlatformPei/AmdSev.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c index dddffdebda..c72eeb37c5 100644 --- a/OvmfPkg/PlatformPei/AmdSev.c +++ b/OvmfPkg/PlatformPei/AmdSev.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,15 @@ AmdSevEsInitialize ( PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE); ASSERT_RETURN_ERROR (PcdStatus); + // + // GHCB_BASE setup during reset-vector needs to be marked as + // decrypted in the hypervisor page encryption bitmap. + // + SetMemoryEncDecHypercall3 (FixedPcdGet32 (PcdOvmfSecGhcbBase), +EFI_SIZE_TO_PAGES(FixedPcdGet32 (PcdOvmfSecGhcbSize)), +FALSE +); + // // Allocate GHCB and per-CPU variable pages. // Since the pages must survive across the UEFI to OS transition -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#72352): https://edk2.groups.io/g/devel/message/72352 Mute This Topic: https://groups.io/mt/81036364/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 04/14] OvmfPkg/AmdSev: Base for Confidential Migration Handler
Base enablement of DXE driver that supports confidential migration. Signed-off-by: Tobin Feldman-Fitzthum --- OvmfPkg/OvmfPkg.dec | 5 ++ OvmfPkg/AmdSev/AmdSevX64.dsc | 1 + OvmfPkg/AmdSev/AmdSevX64.fdf | 1 + .../ConfidentialMigrationDxe.inf | 39 + .../ConfidentialMigrationDxe.c| 83 +++ 5 files changed, 129 insertions(+) create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 4450d78b91..402c3b61fa 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -324,6 +324,11 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId|0|UINT16|0x1b gUefiOvmfPkgTokenSpaceGuid.PcdQemuSmbiosValidated|FALSE|BOOLEAN|0x21 + ## Set via FW_CFG to enable confidentialmigration as source or target. + # + gUefiOvmfPkgTokenSpaceGuid.PcdIsConfidentialMigrationTarget|FALSE|BOOLEAN|0x46 + gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler|FALSE|BOOLEAN|0x47 + ## The IO port aperture shared by all PCI root bridges. # gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase|0x0|UINT64|0x22 diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc index ca21fd6e5f..fa68143663 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.dsc +++ b/OvmfPkg/AmdSev/AmdSevX64.dsc @@ -787,6 +787,7 @@ !endif OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf OvmfPkg/AmdSev/Grub/Grub.inf + OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf !if $(BUILD_SHELL) == TRUE ShellPkg/Application/Shell/Shell.inf { diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf index c0098502aa..6ef6dc89f2 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.fdf +++ b/OvmfPkg/AmdSev/AmdSevX64.fdf @@ -273,6 +273,7 @@ INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf !endif INF OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf +INF OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf INF OvmfPkg/AmdSev/Grub/Grub.inf !if $(BUILD_SHELL) == TRUE INF ShellPkg/Application/Shell/Shell.inf diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf new file mode 100644 index 00..a4906a2451 --- /dev/null +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf @@ -0,0 +1,39 @@ +## @file +# +# Copyright (C) 2021 IBM Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION= 0x00010005 + BASE_NAME = ConfidentialMigration + FILE_GUID = 5c2978f4-f175-434b-9e6c-9b03bd7e346f + MODULE_TYPE= DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT= LaunchMigrationHandler + +[Sources] + ConfidentialMigrationDxe.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + MemoryAllocationLib + DebugLib + UefiBootServicesTableLib + MpInitLib + UefiDriverEntryPoint + +[Protocols] + gEfiMpServiceProtocolGuid + +[Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdIsConfidentialMigrationTarget + gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler + +[Depex] + gEfiMpServiceProtocolGuid diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c new file mode 100644 index 00..6d9fe7043b --- /dev/null +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c @@ -0,0 +1,83 @@ +/** @file + In-guest support for confidential migration + + Copyright (C) 2021 IBM Coporation. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include +#include +#include +#include +#include + +UINTN MigrationHandlerCpuIndex; + +VOID +EFIAPI +MigrationHandlerMain ( + IN OUT VOID *Buffer + ) +{ + DebugPrint (DEBUG_INFO,"MIGRATION Handler Started\n"); +} + +EFI_STATUS +EFIAPI +LaunchMigrationHandler ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_MP_SERVICES_PROTOCOL *MpProto; + EFI_PROCESSOR_INFORMATION Tcb; + EFI_STATUSStatus; + UINTN NumProc; + UINTN NumEnabled; + + gST = SystemTable; + gBS = gST->BootServices; + gRT = gST->RuntimeServices; + + Status = EFI_NOT_STARTED; + + if (!PcdGetBool(PcdStartConfidentialMigrationHandler)) { +return 0; + } + + // + // Use the MP Service protocol to start Migration Handler on AP + // + gBS->LocateProtocol (, NULL, (void**)); + MpProto->GetNumberOfProcessors (MpProto, , ); + if (NumProc < 2) { +DebugPrint (DEBUG_ERROR,"Only one vCPU enabled. Please
[edk2-devel] [RFC PATCH 00/14] Firmware Support for Fast Live Migration for AMD SEV
This is a demonstration of fast migration for encrypted virtual machines using a Migration Handler that lives in OVMF. This demo uses AMD SEV, but the ideas may generalize to other confidential computing platforms. With AMD SEV, guest memory is encrypted and the hypervisor cannot access or move it. This makes migration tricky. In this demo, we show how the HV can ask a Migration Handler (MH) in the firmware for an encrypted page. The MH encrypts the page with a transport key prior to releasing it to the HV. The target machine also runs an MH that decrypts the page once it is passed in by the target HV. These patches are not ready for production, but the are a full end-to-end solution that facilitates a fast live migration between two SEV VMs. Corresponding patches for QEMU have been posted my colleague Dov Murik on qemu-devel. Our approach needs little kernel support, requiring only one hypercall that the guest can use to mark a page as encrypted or shared. This series includes updated patches from Ashish Kalra and Brijesh Singh that allow OVMF to use this hypercall. The MH runs continuously in the guest, waiting for communication from the HV. The HV starts an additional vCPU for the MH but does not expose it to the guest OS via ACPI. We use the MpService to start the MH. The MpService is only available at runtime and processes that are started by it are usually cleaned up on ExitBootServices. Since we need the MH to run continuously, we had to make some modifications. Ideally a feature could be added to the MpService to allow for the starting of long-running processes. Besides migration, this could support other background processes that need to operate within the encryption boundary. For now, we have included a handful of patches that modify the MpService to allow the MH to keep running after ExitBootServices. These are temporary. Ashish Kalra (2): OvmfPkg/PlatformPei: Mark SEC GHCB page in the page encrpytion bitmap. OvmfPkg/PlatformDxe: Add support for SEV live migration. Brijesh Singh (1): OvmfPkg/BaseMemEncryptLib: Support to issue unencrypted hypercall Dov Murik (1): OvmfPkg/AmdSev: Build page table for migration handler Tobin Feldman-Fitzthum (10): OvmfPkg/AmdSev: Base for Confidential Migration Handler OvmfPkg/PlatfomPei: Set Confidential Migration PCD OvmfPkg/AmdSev: Setup Migration Handler Mailbox OvmfPkg/AmdSev: MH support for mailbox protocol UefiCpuPkg/MpInitLib: temp removal of MpLib cleanup UefiCpuPkg/MpInitLib: Allocate MP buffer as runtime memory UefiCpuPkg/CpuExceptionHandlerLib: Exception handling as runtime memory OvmfPkg/AmdSev: Don't overwrite mailbox or pagetables OvmfPkg/AmdSev: Don't overwrite MH stack OvmfPkg/AmdSev: MH page encryption POC OvmfPkg/OvmfPkg.dec | 11 + OvmfPkg/AmdSev/AmdSevX64.dsc | 2 + OvmfPkg/AmdSev/AmdSevX64.fdf | 13 +- .../ConfidentialMigrationDxe.inf | 45 +++ .../ConfidentialMigrationPei.inf | 35 ++ .../DxeMemEncryptSevLib.inf | 1 + .../PeiMemEncryptSevLib.inf | 1 + OvmfPkg/PlatformDxe/Platform.inf | 2 + OvmfPkg/PlatformPei/PlatformPei.inf | 2 + UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 2 + UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 2 + OvmfPkg/AmdSev/ConfidentialMigration/MpLib.h | 235 + .../ConfidentialMigration/VirtualMemory.h | 177 ++ OvmfPkg/Include/Guid/MemEncryptLib.h | 16 + OvmfPkg/PlatformDxe/PlatformConfig.h | 5 + .../ConfidentialMigrationDxe.c| 325 ++ .../ConfidentialMigrationPei.c| 25 ++ .../X64/PeiDxeVirtualMemory.c | 18 + OvmfPkg/PlatformDxe/AmdSev.c | 99 ++ OvmfPkg/PlatformDxe/Platform.c| 6 + OvmfPkg/PlatformPei/AmdSev.c | 10 + OvmfPkg/PlatformPei/Platform.c| 10 + .../CpuExceptionHandlerLib/DxeException.c | 8 +- UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 21 +- UefiCpuPkg/Library/MpInitLib/MpLib.c | 7 +- 25 files changed, 1061 insertions(+), 17 deletions(-) create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/MpLib.h create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/VirtualMemory.h create mode 100644 OvmfPkg/Include/Guid/MemEncryptLib.h create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.c create mode 100644 OvmfPkg/PlatformDxe/AmdSev.c -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#72353): https://edk2.groups.io/g/devel/message/72353
[edk2-devel] [RFC PATCH 06/14] OvmfPkg/AmdSev: Setup Migration Handler Mailbox
The migration handler communicates with the hypervisor using a special mailbox, a page of shared memory where pending commands can be written. Another shared page is used to pass the incoming or outgoing guest memory pages. These pages are set aside in MEMFD, which this patch expands, and reserved as runtime memory in ConfidentialMigrationPei, which this patch introduces. Signed-off-by: Tobin Feldman-Fitzthum --- OvmfPkg/OvmfPkg.dec | 5 +++ OvmfPkg/AmdSev/AmdSevX64.dsc | 1 + OvmfPkg/AmdSev/AmdSevX64.fdf | 12 --- .../ConfidentialMigrationPei.inf | 35 +++ .../ConfidentialMigrationPei.c| 25 + 5 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.c diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 402c3b61fa..5c55e3c7c9 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -318,6 +318,11 @@ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|0x0|UINT32|0x42 gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize|0x0|UINT32|0x43 + ## Area used by the confidential migration handler to communicate with + # the hypervisor. + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase|0x0|UINT32|0x48 + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxSize|0x0|UINT32|0x49 + [PcdsDynamic, PcdsDynamicEx] gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc index fa68143663..4f748a0015 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.dsc +++ b/OvmfPkg/AmdSev/AmdSevX64.dsc @@ -620,6 +620,7 @@ UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf UefiCpuPkg/CpuMpPei/CpuMpPei.inf OvmfPkg/AmdSev/SecretPei/SecretPei.inf + OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf !if $(TPM_ENABLE) == TRUE OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf index 6ef6dc89f2..94468f2ca0 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.fdf +++ b/OvmfPkg/AmdSev/AmdSevX64.fdf @@ -36,10 +36,10 @@ FV = SECFV [FD.MEMFD] BaseAddress = $(MEMFD_BASE_ADDRESS) -Size = 0xD0 +Size = 0xE0 ErasePolarity = 1 BlockSize = 0x1 -NumBlocks = 0xD0 +NumBlocks = 0xE0 0x00|0x006000 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize @@ -68,11 +68,14 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.P 0x01|0x01 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize -0x02|0x0E +0x02|0x003000 +gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase|gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxSize + +0x12|0x0E gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize FV = PEIFV -0x10|0xC0 +0x20|0xC0 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize FV = DXEFV @@ -145,6 +148,7 @@ INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf INF UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf INF UefiCpuPkg/CpuMpPei/CpuMpPei.inf INF OvmfPkg/AmdSev/SecretPei/SecretPei.inf +INF OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf !if $(TPM_ENABLE) == TRUE INF OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf new file mode 100644 index 00..918cf22abd --- /dev/null +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.inf @@ -0,0 +1,35 @@ +## @file +# PEI support for confidential migration. +# +# Copyright (C) 2021 IBM Corporation. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION= 0x00010005 + BASE_NAME = ConfidentialMigration + FILE_GUID = a747792e-71a1-4c24-84a9-a76a0a279878 + MODULE_TYPE= PEIM + VERSION_STRING = 1.0 + ENTRY_POINT= InitializeConfidentialMigrationPei + +[Sources] + ConfidentialMigrationPei.c + +[Packages] + OvmfPkg/OvmfPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + HobLib + PeimEntryPoint + PcdLib + +[FixedPcd] + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase + gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxSize + +[Depex] + TRUE diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationPei.c new
[edk2-devel] [RFC PATCH 09/14] UefiCpuPkg/MpInitLib: Allocate MP buffer as runtime memory
Another temporary change to support the persistence of the MH. The Mp buffer needs to be allocated as runtime memory or it may be overwritten by the OS. Signed-off-by: Tobin Feldman-Fitzthum --- UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 2 ++ UefiCpuPkg/Library/MpInitLib/MpLib.c | 7 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf index 34abf25d43..0b26cf6aaf 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf @@ -39,6 +39,7 @@ MdePkg/MdePkg.dec UefiCpuPkg/UefiCpuPkg.dec MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec [LibraryClasses] BaseLib @@ -65,6 +66,7 @@ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled ## CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler [Ppis] gEdkiiPeiShadowMicrocodePpiGuid## SOMETIMES_CONSUMES diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index 2568986d8c..0ca2858ca3 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -1974,7 +1974,12 @@ MpInitLibInitialize ( BufferSize += VolatileRegisters.Idtr.Limit + 1; BufferSize += sizeof (CPU_MP_DATA); BufferSize += (sizeof (CPU_AP_DATA) + sizeof (CPU_INFO_IN_HOB))* MaxLogicalProcessorNumber; - MpBuffer= AllocatePages (EFI_SIZE_TO_PAGES (BufferSize)); + if (PcdGetBool (PcdStartConfidentialMigrationHandler)) { +MpBuffer= AllocateRuntimePages (EFI_SIZE_TO_PAGES (BufferSize)); + } + else { +MpBuffer= AllocatePages (EFI_SIZE_TO_PAGES (BufferSize)); + } ASSERT (MpBuffer != NULL); ZeroMem (MpBuffer, BufferSize); Buffer = (UINTN) MpBuffer; -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#72359): https://edk2.groups.io/g/devel/message/72359 Mute This Topic: https://groups.io/mt/81036374/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-
[edk2-devel] [RFC PATCH 12/14] OvmfPkg/AmdSev: Don't overwrite mailbox or pagetables
While restoring pages, the MH should avoid overwriting its pagetables or the mailbox it uses to communicate with the HV. Signed-off-by: Tobin Feldman-Fitzthum --- .../ConfidentialMigrationDxe.c| 22 +-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c index 3df3b09732..f609e16f8d 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c @@ -128,6 +128,10 @@ MigrationHandlerMain ( IN OUT VOID *Buffer ) { + UINT64 mailbox_start; + UINT64 mailbox_end; + UINT64 pagetable_start; + UINT64 pagetable_end; UINT64 params_base; MH_COMMAND_PARAMETERS*params; VOID *page_va; @@ -139,10 +143,16 @@ MigrationHandlerMain ( // // Shared pages must be offset by UNENC_VIRT_ADDR_BASE. // - params_base = PcdGet32 (PcdConfidentialMigrationMailboxBase) + UNENC_VIRT_ADDR_BASE; + mailbox_start = PcdGet32 (PcdConfidentialMigrationMailboxBase); + params_base = mailbox_start + UNENC_VIRT_ADDR_BASE; params = (VOID *)params_base; page_va = (VOID *)params_base + 0x1000; + mailbox_end = mailbox_start + 2 * EFI_PAGE_SIZE; + + pagetable_start = mMigrationHelperPageTables; + pagetable_end = pagetable_start + 11 * EFI_PAGE_SIZE; + DisableInterrupts(); params->go = 0; @@ -163,7 +173,15 @@ MigrationHandlerMain ( break; case MH_FUNC_RESTORE_PAGE: - CopyMem((VOID *)params->gpa, page_va, 4096); + // + // Don't import a page that covers the mailbox or pagetables. + // + if ((params->gpa >= mailbox_start && params->gpa < mailbox_end) || + (params->gpa >= pagetable_start && params->gpa < pagetable_end)) { + } + else { +CopyMem((VOID *)params->gpa, page_va, 4096); + } params->ret = MH_SUCCESS; break; -- 2.20.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#72361): https://edk2.groups.io/g/devel/message/72361 Mute This Topic: https://groups.io/mt/81036378/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-