!296 sync 24.03 LTS patch list

From: @JiaboFeng 
Reviewed-by: @imxcc 
Signed-off-by: @imxcc
This commit is contained in:
openeuler-ci-bot 2024-12-12 08:45:31 +00:00 committed by Gitee
commit 19e2f998a8
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
13 changed files with 1847 additions and 1 deletions

View File

@ -0,0 +1,330 @@
From ae4bf41d9c71137a21e7b8fc4aceca7212145b40 Mon Sep 17 00:00:00 2001
From: Ashish Kalra <ashish.kalra@amd.com>
Date: Tue, 5 Apr 2022 16:09:28 +0000
Subject: [PATCH 1/9] OvmfPkg/BaseMemEncryptLib: Detect SEV live migration
feature.
cherry-picked from https://patchew.org/EDK2/cover.1629380011.git.ashish.kalra@amd.com .
Add support to check if we are running inside KVM HVM and
KVM HVM supports SEV Live Migration feature.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
OvmfPkg/Include/Library/MemEncryptSevLib.h | 12 ++++
.../DxeMemEncryptSevLibInternal.c | 49 ++++++++++++++--
.../PeiDxeMemEncryptSevLibInternal.c | 58 +++++++++++++++++++
.../PeiDxeMemEncryptSevLibInternal.h | 31 ++++++++++
.../PeiMemEncryptSevLibInternal.c | 42 ++++++++++++++
.../SecMemEncryptSevLibInternal.c | 18 ++++++
6 files changed, 206 insertions(+), 4 deletions(-)
create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h
diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index 4fa9c0d7..babec60d 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -83,6 +83,18 @@ MemEncryptSevIsEnabled (
VOID
);
+/**
+ Returns a boolean to indicate whether SEV live migration is enabled.
+
+ @retval TRUE SEV live migration is enabled
+ @retval FALSE SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+ VOID
+ );
+
/**
This function clears memory encryption bit for the memory region specified by
BaseAddress and NumPages from the current page table context.
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
index 4aba0075..d80ebe2f 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
@@ -18,10 +18,14 @@
#include <Uefi/UefiBaseType.h>
#include <ConfidentialComputingGuestAttr.h>
-STATIC UINT64 mCurrentAttr = 0;
-STATIC BOOLEAN mCurrentAttrRead = FALSE;
-STATIC UINT64 mSevEncryptionMask = 0;
-STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE;
+#include "PeiDxeMemEncryptSevLibInternal.h"
+
+STATIC UINT64 mCurrentAttr = 0;
+STATIC BOOLEAN mCurrentAttrRead = FALSE;
+STATIC UINT64 mSevEncryptionMask = 0;
+STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE;
+STATIC BOOLEAN mSevLiveMigrationStatus = FALSE;
+STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE;
/**
The function check if the specified Attr is set.
@@ -111,6 +115,24 @@ MemEncryptSevSnpIsEnabled (
return ConfidentialComputingGuestHas (CCAttrAmdSevSnp);
}
+/**
+ Figures out if we are running inside KVM HVM and
+ KVM HVM supports SEV Live Migration feature.
+**/
+STATIC
+VOID
+EFIAPI
+InternalDetectSevLiveMigrationFeature (
+ VOID
+ )
+{
+ if (KvmDetectSevLiveMigrationFeature ()) {
+ mSevLiveMigrationStatus = TRUE;
+ }
+
+ mSevLiveMigrationStatusChecked = TRUE;
+}
+
/**
Returns a boolean to indicate whether SEV-ES is enabled.
@@ -141,6 +163,25 @@ MemEncryptSevIsEnabled (
return ConfidentialComputingGuestHas (CCAttrAmdSev);
}
+/**
+ Returns a boolean to indicate whether SEV live migration is enabled.
+
+ @retval TRUE SEV live migration is enabled
+ @retval FALSE SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+ VOID
+ )
+{
+ if (!mSevLiveMigrationStatusChecked) {
+ InternalDetectSevLiveMigrationFeature ();
+ }
+
+ return mSevLiveMigrationStatus;
+}
+
/**
Returns the SEV encryption mask.
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
index 78ea16ae..868392f7 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
@@ -16,6 +16,8 @@
#include <Register/SmramSaveStateMap.h>
#include <Uefi/UefiBaseType.h>
+#include "PeiDxeMemEncryptSevLibInternal.h"
+
/**
Locate the page range that covers the initial (pre-SMBASE-relocation) SMRAM
Save State Map.
@@ -61,3 +63,59 @@ MemEncryptSevLocateInitialSmramSaveStateMapPages (
return RETURN_SUCCESS;
}
+
+/**
+ Figures out if we are running inside KVM HVM and
+ KVM HVM supports SEV Live Migration feature.
+
+ @retval TRUE SEV live migration is supported.
+ @retval FALSE SEV live migration is not supported.
+**/
+BOOLEAN
+EFIAPI
+KvmDetectSevLiveMigrationFeature (
+ VOID
+ )
+{
+ CHAR8 Signature[13];
+ UINT32 mKvmLeaf;
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+
+ Signature[12] = '\0';
+ for (mKvmLeaf = 0x40000000; mKvmLeaf < 0x40010000; mKvmLeaf += 0x100) {
+ AsmCpuid (
+ mKvmLeaf,
+ NULL,
+ (UINT32 *)&Signature[0],
+ (UINT32 *)&Signature[4],
+ (UINT32 *)&Signature[8]
+ );
+
+ if (AsciiStrCmp (Signature, "KVMKVMKVM") == 0) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: KVM Detected, signature = %a\n",
+ __FUNCTION__,
+ Signature
+ ));
+
+ RegEax = mKvmLeaf + 1;
+ RegEcx = 0;
+ AsmCpuid (mKvmLeaf + 1, &RegEax, &RegEbx, &RegEcx, &RegEdx);
+ if ((RegEax & KVM_FEATURE_MIGRATION_CONTROL) != 0) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: SEV Live Migration feature supported\n",
+ __FUNCTION__
+ ));
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h
new file mode 100644
index 00000000..b0ef053c
--- /dev/null
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h
@@ -0,0 +1,31 @@
+/** @file
+
+ Secure Encrypted Virtualization (SEV) library helper function
+
+ Copyright (c) 2021, AMD Incorporated. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_
+#define PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_
+
+#include <Library/BaseLib.h>
+
+#define KVM_FEATURE_MIGRATION_CONTROL BIT17
+
+/**
+ Figures out if we are running inside KVM HVM and
+ KVM HVM supports SEV Live Migration feature.
+
+ @retval TRUE SEV live migration is supported.
+ @retval FALSE SEV live migration is not supported.
+**/
+BOOLEAN
+EFIAPI
+KvmDetectSevLiveMigrationFeature (
+ VOID
+ );
+
+#endif // PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
index 41d1246a..307087a1 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
@@ -17,6 +17,11 @@
#include <Register/Cpuid.h>
#include <Uefi/UefiBaseType.h>
+#include "PeiDxeMemEncryptSevLibInternal.h"
+
+STATIC BOOLEAN mSevLiveMigrationStatus = FALSE;
+STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE;
+
/**
Read the workarea to determine whether SEV is enabled. If enabled,
then return the SevEsWorkArea pointer.
@@ -83,6 +88,24 @@ MemEncryptSevSnpIsEnabled (
return Msr.Bits.SevSnpBit ? TRUE : FALSE;
}
+/**
+ Figures out if we are running inside KVM HVM and
+ KVM HVM supports SEV Live Migration feature.
+**/
+STATIC
+VOID
+EFIAPI
+InternalDetectSevLiveMigrationFeature (
+ VOID
+ )
+{
+ if (KvmDetectSevLiveMigrationFeature ()) {
+ mSevLiveMigrationStatus = TRUE;
+ }
+
+ mSevLiveMigrationStatusChecked = TRUE;
+}
+
/**
Returns a boolean to indicate whether SEV-ES is enabled.
@@ -121,6 +144,25 @@ MemEncryptSevIsEnabled (
return Msr.Bits.SevBit ? TRUE : FALSE;
}
+/**
+ Returns a boolean to indicate whether SEV live migration is enabled.
+
+ @retval TRUE SEV live migration is enabled
+ @retval FALSE SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+ VOID
+ )
+{
+ if (!mSevLiveMigrationStatusChecked) {
+ InternalDetectSevLiveMigrationFeature ();
+ }
+
+ return mSevLiveMigrationStatus;
+}
+
/**
Returns the SEV encryption mask.
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
index 27148c7e..9142ac40 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
@@ -121,6 +121,24 @@ MemEncryptSevIsEnabled (
return Msr.Bits.SevBit ? TRUE : FALSE;
}
+/**
+ Returns a boolean to indicate whether SEV live migration is enabled.
+
+ @retval TRUE SEV live migration is enabled
+ @retval FALSE SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+ VOID
+ )
+{
+ //
+ // Not used in SEC phase.
+ //
+ return FALSE;
+}
+
/**
Returns the SEV encryption mask.
--
2.25.1

View File

@ -0,0 +1,301 @@
From 2c000372cab80ab68a8672138c8d0f5cb1ae43d9 Mon Sep 17 00:00:00 2001
From: Ashish Kalra <ashish.kalra@amd.com>
Date: Tue, 5 Apr 2022 16:23:53 +0000
Subject: [PATCH 2/9] OvmfPkg/BaseMemEncryptLib: Hypercall API for page
encryption state change
cherry-picked from https://patchew.org/EDK2/cover.1629380011.git.ashish.kalra@amd.com .
Add API to issue hypercall on page encryption state change.
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.
This hypercall is used to notify hypervisor when the page's
encryption state changes.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
OvmfPkg/Include/Library/MemEncryptSevLib.h | 52 +++++++++++++++
.../DxeMemEncryptSevLib.inf | 1 +
.../Ia32/MemEncryptSevLib.c | 27 ++++++++
.../PeiMemEncryptSevLib.inf | 1 +
.../SecMemEncryptSevLibInternal.c | 20 ++++++
.../X64/AsmHelperStub.nasm | 33 ++++++++++
.../X64/MemEncryptSevLib.c | 66 +++++++++++++++++++
7 files changed, 200 insertions(+)
create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm
diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index babec60d..b60496c2 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -240,4 +240,56 @@ MemEncryptSevSnpPreValidateSystemRam (
IN UINTN NumPages
);
+/**
+ This hypercall is used to notify hypervisor when the page's encryption
+ state changes.
+
+ @param[in] PhysicalAddress The physical address that is the start address
+ of a memory region.
+ @param[in] Pages Number of pages in memory region.
+ @param[in] IsEncrypted Encrypted or Decrypted.
+
+ @retval RETURN_SUCCESS Hypercall returned success.
+ @retval RETURN_UNSUPPORTED Hypercall not supported.
+ @retval RETURN_NO_MAPPING Hypercall returned error.
+**/
+RETURN_STATUS
+EFIAPI
+SetMemoryEncDecHypercall3 (
+ IN UINTN PhysicalAddress,
+ IN UINTN Pages,
+ IN BOOLEAN IsEncrypted
+ );
+
+#define KVM_HC_MAP_GPA_RANGE 12
+#define KVM_MAP_GPA_RANGE_PAGE_SZ_4K 0
+#define KVM_MAP_GPA_RANGE_PAGE_SZ_2M BIT0
+#define KVM_MAP_GPA_RANGE_PAGE_SZ_1G BIT1
+#define KVM_MAP_GPA_RANGE_ENC_STATE(n) ((n) << 4)
+#define KVM_MAP_GPA_RANGE_ENCRYPTED KVM_MAP_GPA_RANGE_ENC_STATE(1)
+#define KVM_MAP_GPA_RANGE_DECRYPTED KVM_MAP_GPA_RANGE_ENC_STATE(0)
+
+/**
+ Interface exposed by the ASM implementation of the core hypercall
+
+ @param[in] HypercallNum KVM_HC_MAP_GPA_RANGE hypercall.
+ @param[in] PhysicalAddress The physical address that is the start address
+ of a memory region.
+ @param[in] Pages Number of pages in memory region.
+ @param[in] Attributes Bits 3:0 - preferred page size encoding,
+ 0 = 4kb, 1 = 2mb, 2 = 1gb, etc...
+ Bit 4 - plaintext = 0, encrypted = 1
+ Bits 63:5 - reserved (must be zero)
+
+ @retval Hypercall returned status.
+**/
+UINTN
+EFIAPI
+SetMemoryEncDecHypercall3AsmStub (
+ IN UINTN HypercallNum,
+ IN UINTN PhysicalAddress,
+ IN UINTN Pages,
+ IN UINTN Attributes
+ );
+
#endif // _MEM_ENCRYPT_SEV_LIB_H_
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
index 3a1d3089..4d32fae6 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
@@ -40,6 +40,7 @@
X64/SnpPageStateChangeInternal.c
X64/VirtualMemory.c
X64/VirtualMemory.h
+ X64/AsmHelperStub.nasm
[Sources.IA32]
Ia32/MemEncryptSevLib.c
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
index f92299fc..c1c10a61 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
@@ -153,3 +153,30 @@ MemEncryptSevSnpPreValidateSystemRam (
{
ASSERT (FALSE);
}
+
+/**
+ This hyercall is used to notify hypervisor when the page's encryption
+ state changes.
+
+ @param[in] PhysicalAddress The physical address that is the start address
+ of a memory region.
+ @param[in] Pages Number of Pages in the memory region.
+ @param[in] IsEncrypted Encrypted or Decrypted.
+
+ @retval RETURN_SUCCESS Hypercall returned success.
+ @retval RETURN_UNSUPPORTED Hypercall not supported.
+ @retval RETURN_NO_MAPPING Hypercall returned error.
+**/
+RETURN_STATUS
+EFIAPI
+SetMemoryEncDecHypercall3 (
+ IN UINTN PhysicalAddress,
+ IN UINTN Pages,
+ IN BOOLEAN IsEncrypted
+ )
+{
+ //
+ // Memory encryption bit is not accessible in 32-bit mode
+ //
+ return RETURN_UNSUPPORTED;
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
index 8f56783d..3f11f06a 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
@@ -40,6 +40,7 @@
X64/SnpPageStateChangeInternal.c
X64/VirtualMemory.c
X64/VirtualMemory.h
+ X64/AsmHelperStub.nasm
[Sources.IA32]
Ia32/MemEncryptSevLib.c
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
index 9142ac40..ffb22a08 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
@@ -139,6 +139,26 @@ MemEncryptSevLiveMigrationIsEnabled (
return FALSE;
}
+/**
+ Interface exposed by the ASM implementation of the core hypercall
+
+ @retval Hypercall returned status.
+**/
+UINTN
+EFIAPI
+SetMemoryEncDecHypercall3AsmStub (
+ IN UINTN HypercallNum,
+ IN UINTN PhysicalAddress,
+ IN UINTN Pages,
+ IN UINTN Attributes
+ )
+{
+ //
+ // Not used in SEC phase.
+ //
+ return RETURN_UNSUPPORTED;
+}
+
/**
Returns the SEV encryption mask.
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm
new file mode 100644
index 00000000..0ec35dd9
--- /dev/null
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm
@@ -0,0 +1,33 @@
+/** @file
+
+ ASM helper stub to invoke hypercall
+
+ Copyright (c) 2021, AMD Incorporated. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+DEFAULT REL
+SECTION .text
+
+; UINTN
+; EFIAPI
+; SetMemoryEncDecHypercall3AsmStub (
+; IN UINTN HypercallNum,
+; IN UINTN Arg1,
+; IN UINTN Arg2,
+; IN UINTN Arg3
+; );
+global ASM_PFX(SetMemoryEncDecHypercall3AsmStub)
+ASM_PFX(SetMemoryEncDecHypercall3AsmStub):
+ ; UEFI calling conventions require RBX to
+ ; be nonvolatile/callee-saved.
+ push rbx
+ mov rax, rcx ; Copy HypercallNumber to rax
+ mov rbx, rdx ; Copy Arg1 to the register expected by KVM
+ mov rcx, r8 ; Copy Arg2 to register expected by KVM
+ mov rdx, r9 ; Copy Arg3 to register expected by KVM
+ vmmcall ; Call VMMCALL
+ pop rbx
+ ret
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
index e7c703bb..a64ff2a5 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
@@ -142,3 +142,69 @@ MemEncryptSevClearMmioPageEncMask (
EFI_PAGES_TO_SIZE (NumPages)
);
}
+
+/**
+ This hyercall is used to notify hypervisor when the page's encryption
+ state changes.
+
+ @param[in] PhysicalAddress The physical address that is the start address
+ of a memory region.
+ @param[in] Pages Number of Pages in the memory region.
+ @param[in] IsEncrypted Encrypted or Decrypted.
+
+ @retval RETURN_SUCCESS Hypercall returned success.
+ @retval RETURN_UNSUPPORTED Hypercall not supported.
+ @retval RETURN_NO_MAPPING Hypercall returned error.
+**/
+RETURN_STATUS
+EFIAPI
+SetMemoryEncDecHypercall3 (
+ IN UINTN PhysicalAddress,
+ IN UINTN Pages,
+ IN BOOLEAN IsEncrypted
+ )
+{
+ RETURN_STATUS Ret;
+ UINTN Error;
+ UINTN EncryptState;
+
+ Ret = RETURN_UNSUPPORTED;
+
+ if (MemEncryptSevLiveMigrationIsEnabled ()) {
+ Ret = RETURN_SUCCESS;
+ //
+ // The encryption bit is set/clear on the smallest page size, hence
+ // use the 4k page size in MAP_GPA_RANGE hypercall below.
+ //
+ // Also, when the GCD map is being walked and the c-bit being cleared
+ // from MMIO and NonExistent memory spaces, the physical address
+ // range being passed may not be page-aligned and adding an assert
+ // here prevents booting. Hence, rounding it down when calling
+ // SetMemoryEncDecHypercall3AsmStub below.
+ //
+
+ EncryptState = IsEncrypted ? KVM_MAP_GPA_RANGE_ENCRYPTED :
+ KVM_MAP_GPA_RANGE_DECRYPTED;
+
+ Error = SetMemoryEncDecHypercall3AsmStub (
+ KVM_HC_MAP_GPA_RANGE,
+ PhysicalAddress & ~EFI_PAGE_MASK,
+ Pages,
+ KVM_MAP_GPA_RANGE_PAGE_SZ_4K | EncryptState
+ );
+
+ if (Error != 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "SetMemoryEncDecHypercall3 failed, Phys = %x, Pages = %d, Err = %Ld\n",
+ PhysicalAddress,
+ Pages,
+ (INT64)Error
+ ));
+
+ Ret = RETURN_NO_MAPPING;
+ }
+ }
+
+ return Ret;
+}
--
2.25.1

View File

@ -0,0 +1,84 @@
From 481f0a191fc03e79bbb52b08c1d4890b6331e68d Mon Sep 17 00:00:00 2001
From: Ashish Kalra <ashish.kalra@amd.com>
Date: Tue, 5 Apr 2022 16:26:02 +0000
Subject: [PATCH 3/9] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state
change hypercall
cherry-picked from https://patchew.org/EDK2/cover.1629380011.git.ashish.kalra@amd.com .
Invoke the hypercall API to notify hypervisor when the page's
encryption state changes.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
.../X64/PeiDxeVirtualMemory.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
index a49cf125..42e3b03f 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
@@ -727,6 +727,7 @@ SetMemoryEncDec (
UINT64 PgTableMask;
UINT64 AddressEncMask;
BOOLEAN IsWpEnabled;
+ BOOLEAN CBitChanged;
UINTN OrigLength;
RETURN_STATUS Status;
PHYSICAL_ADDRESS PageAddress;
@@ -800,6 +801,7 @@ SetMemoryEncDec (
// Save the specified length and physical address (we need it later).
//
OrigLength = Length;
+ CBitChanged = FALSE;
OrigPhysicalAddress = PhysicalAddress;
while (Length != 0) {
@@ -860,6 +862,7 @@ SetMemoryEncDec (
));
PhysicalAddress += BIT30;
Length -= BIT30;
+ CBitChanged = TRUE;
} else {
//
// We must split the page
@@ -915,6 +918,7 @@ SetMemoryEncDec (
SetOrClearCBit (&PageDirectory2MEntry->Uint64, Mode);
PhysicalAddress += BIT21;
Length -= BIT21;
+ CBitChanged = TRUE;
} else {
//
// We must split up this page into 4K pages
@@ -958,6 +962,7 @@ SetMemoryEncDec (
SetOrClearCBit (&PageTableEntry->Uint64, Mode);
PhysicalAddress += EFI_PAGE_SIZE;
Length -= EFI_PAGE_SIZE;
+ CBitChanged = TRUE;
}
}
}
@@ -990,6 +995,17 @@ SetMemoryEncDec (
);
}
+ //
+ // Notify Hypervisor on C-bit status
+ //
+ if (CBitChanged) {
+ Status = SetMemoryEncDecHypercall3 (
+ OrigPhysicalAddress,
+ EFI_SIZE_TO_PAGES (OrigLength),
+ (Mode == SetCBit) ? TRUE : FALSE
+ );
+ }
+
Done:
//
// Restore page table write protection, if any.
--
2.25.1

View File

@ -0,0 +1,47 @@
From 1058be0934a043804f2ae0b8ea1aa42454dc0eb8 Mon Sep 17 00:00:00 2001
From: Ashish Kalra <ashish.kalra@amd.com>
Date: Tue, 5 Apr 2022 16:27:26 +0000
Subject: [PATCH 4/9] OvmfPkg/VmgExitLib: Encryption state change hypercall
support in VC handler
cherry-picked from https://patchew.org/EDK2/cover.1629380011.git.ashish.kalra@amd.com .
Make the #VC handler aware of the page encryption state
change hypercall by adding support to check KVM_HC_MAP_GPA_RANGE
hypercall and add the additional register values used by
hypercall in the GHCB.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
OvmfPkg/Library/CcExitLib/CcExitVcHandler.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
index 0fc30f7b..5c9a9085 100644
--- a/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
+++ b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
@@ -677,6 +677,19 @@ VmmCallExit (
Ghcb->SaveArea.Cpl = (UINT8)(Regs->Cs & 0x3);
CcExitVmgSetOffsetValid (Ghcb, GhcbCpl);
+ if (Regs->Rax == KVM_HC_MAP_GPA_RANGE) {
+ //
+ // KVM_HC_MAP_GPA_RANGE hypercall requires these
+ // extra registers.
+ //
+ Ghcb->SaveArea.Rbx = Regs->Rbx;
+ CcExitVmgSetOffsetValid (Ghcb, GhcbRbx);
+ Ghcb->SaveArea.Rcx = Regs->Rcx;
+ CcExitVmgSetOffsetValid (Ghcb, GhcbRcx);
+ Ghcb->SaveArea.Rdx = Regs->Rdx;
+ CcExitVmgSetOffsetValid (Ghcb, GhcbRdx);
+ }
+
Status = CcExitVmgExit (Ghcb, SVM_EXIT_VMMCALL, 0, 0);
if (Status != 0) {
return Status;
--
2.25.1

View File

@ -0,0 +1,44 @@
From 16e7adce62f7c28cc1823229b40a27493737cae6 Mon Sep 17 00:00:00 2001
From: Ashish Kalra <ashish.kalra@amd.com>
Date: Tue, 5 Apr 2022 16:30:54 +0000
Subject: [PATCH 5/9] OvmfPkg/PlatformPei: Mark SEC GHCB page as unencrypted
via hypercall
cherry-picked from https://patchew.org/EDK2/cover.1629380011.git.ashish.kalra@amd.com .
Mark the SEC GHCB page (that is mapped as unencrypted in
ResetVector code) in the hypervisor's guest page encryption
state tracking.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
OvmfPkg/PlatformPei/AmdSev.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index e6b602d7..553e841e 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -229,6 +229,17 @@ AmdSevEsInitialize (
Status = PcdSetBoolS (PcdSevEsIsEnabled, TRUE);
ASSERT_RETURN_ERROR (Status);
+ //
+ // The SEC Ghcb setup during reset-vector needs to be marked as
+ // decrypted in the hypervisor's guest page encryption state
+ // tracking.
+ //
+ 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.25.1

View File

@ -0,0 +1,196 @@
From 8d82fca148d9564b666b5f4185a0e78e1f77e230 Mon Sep 17 00:00:00 2001
From: Ashish Kalra <ashish.kalra@amd.com>
Date: Tue, 5 Apr 2022 16:40:03 +0000
Subject: [PATCH 6/9] OvmfPkg/AmdSevDxe: Add support for SEV live migration.
cherry-picked from https://patchew.org/EDK2/cover.1629380011.git.ashish.kalra@amd.com .
Check for SEV live migration feature support, if detected
setup a new UEFI enviroment variable to indicate OVMF
support for SEV live migration.
This environment variable is created by UEFI but consumed
by the (guest) linux kernel. This is actually part of a
3-way negotiation of the live migration feature between
hypervisor, guest OVMF and guest kernel. Host indicates
support for live migration, which is detected by OVMF
and correspondingly OVMF sets this SetLiveMigrationEnabled
UEFI variable, which is read by the guest kernel and it
indicates to the guest kernel that both host and OVMF
support and have enabled the live migration feature.
The new runtime UEFI environment variable is set via the
notification function registered for the
EFI_END_OF_DXE_EVENT_GROUP_GUID event in AmdSevDxe driver.
AmdSevDxe module is an apriori driver so it gets loaded between PEI
and DXE phases and the SetVariable call will fail at the driver's
entry point as the Variable DXE module is still not loaded yet.
So we need to wait for an event notification which is signaled
after the Variable DXE module is loaded, hence, using the
EndOfDxe event notification to make this call.
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
OvmfPkg/AmdSevDxe/AmdSevDxe.c | 67 ++++++++++++++++++++++
OvmfPkg/AmdSevDxe/AmdSevDxe.inf | 4 ++
OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h | 20 +++++++
OvmfPkg/OvmfPkg.dec | 1 +
4 files changed, 92 insertions(+)
create mode 100644 OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h
diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
index db3675ae..e3a8049d 100644
--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c
+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
@@ -15,10 +15,13 @@
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/MemEncryptSevLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Guid/ConfidentialComputingSevSnpBlob.h>
+#include <Guid/AmdSevMemEncryptLib.h>
+#include <Guid/EventGroup.h>
#include <Library/PcdLib.h>
#include <Pi/PrePiDxeCis.h>
#include <Protocol/SevMemoryAcceptance.h>
@@ -191,6 +194,39 @@ STATIC EDKII_MEMORY_ACCEPT_PROTOCOL mMemoryAcceptProtocol = {
AmdSevMemoryAccept
};
+STATIC
+VOID
+EFIAPI
+AmdSevDxeOnEndOfDxe (
+ IN EFI_EVENT Event,
+ IN VOID *EventToSignal
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN SevLiveMigrationEnabled;
+
+ SevLiveMigrationEnabled = MemEncryptSevLiveMigrationIsEnabled ();
+
+ if (SevLiveMigrationEnabled) {
+ Status = gRT->SetVariable (
+ L"SevLiveMigrationEnabled",
+ &gAmdSevMemEncryptGuid,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof SevLiveMigrationEnabled,
+ &SevLiveMigrationEnabled
+ );
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Setting SevLiveMigrationEnabled variable, status = %lx\n",
+ __FUNCTION__,
+ Status
+ ));
+ }
+}
+
EFI_STATUS
EFIAPI
AmdSevDxeEntryPoint (
@@ -203,6 +239,7 @@ AmdSevDxeEntryPoint (
UINTN NumEntries;
UINTN Index;
CONFIDENTIAL_COMPUTING_SNP_BLOB_LOCATION *SnpBootDxeTable;
+ EFI_EVENT Event;
//
// Do nothing when SEV is not enabled
@@ -361,5 +398,35 @@ AmdSevDxeEntryPoint (
);
}
+ //
+ // AmdSevDxe module is an apriori driver so it gets loaded between PEI
+ // and DXE phases and the SetVariable call will fail at the driver's
+ // entry point as the Variable DXE module is still not loaded yet.
+ // So we need to wait for an event notification which is signaled
+ // after the Variable DXE module is loaded, hence, using the
+ // EndOfDxe event notification to make this call.
+ //
+ // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.
+ // The notification function sets the runtime variable indicating OVMF
+ // support for SEV live migration.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ AmdSevDxeOnEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &Event
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: CreateEventEx(): %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ }
+
return EFI_SUCCESS;
}
diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.inf b/OvmfPkg/AmdSevDxe/AmdSevDxe.inf
index e7c7d526..dd1da527 100644
--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.inf
@@ -57,3 +57,7 @@
[Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
+
+[Guids]
+ gAmdSevMemEncryptGuid
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
diff --git a/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h b/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h
new file mode 100644
index 00000000..62d22e79
--- /dev/null
+++ b/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h
@@ -0,0 +1,20 @@
+/** @file
+
+ AMD Memory Encryption GUID, define a new GUID for defining
+ new UEFI environment variables assocaiated with SEV Memory Encryption.
+
+ Copyright (c) 2021, AMD Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __AMD_SEV_MEMENCRYPT_LIB_H__
+#define __AMD_SEV_MEMENCRYPT_LIB_H__
+
+#define AMD_SEV_MEMENCRYPT_GUID \
+{0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}}
+
+extern EFI_GUID gAmdSevMemEncryptGuid;
+
+#endif
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 34bca309..d50b1ae3 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -170,6 +170,7 @@
gUefiOvmfPkgTdxAcpiHobGuid = {0x6a0c5870, 0xd4ed, 0x44f4, {0xa1, 0x35, 0xdd, 0x23, 0x8b, 0x6f, 0x0c, 0x8d}}
gEfiNonCcFvGuid = {0xae047c6d, 0xbce9, 0x426c, {0xae, 0x03, 0xa6, 0x8e, 0x3b, 0x8a, 0x04, 0x88}}
gOvmfVariableGuid = {0x50bea1e5, 0xa2c5, 0x46e9, {0x9b, 0x3a, 0x59, 0x59, 0x65, 0x16, 0xb0, 0x0a}}
+ gAmdSevMemEncryptGuid = {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
--
2.25.1

View File

@ -0,0 +1,35 @@
From fbdd6e4664e41eb299a797f1ab615d81b1bd958b Mon Sep 17 00:00:00 2001
From: hanliyang <hanliyang@hygon.cn>
Date: Mon, 17 Jan 2022 01:19:21 -0500
Subject: [PATCH 7/9] OvmfPkg/BaseMemcryptSevLib: Correct the calculation of
page range that notified to hypervisor
Correct the calculation of page range that notified to hypervisor.
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
.../Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
index 42e3b03f..69ada871 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
@@ -999,9 +999,13 @@ SetMemoryEncDec (
// Notify Hypervisor on C-bit status
//
if (CBitChanged) {
+ UINTN StartPfn = OrigPhysicalAddress >> EFI_PAGE_SHIFT;
+ UINTN EndPfn = (OrigPhysicalAddress + OrigLength +
+ ((1 << EFI_PAGE_SHIFT) - 1)) >> EFI_PAGE_SHIFT;
+
Status = SetMemoryEncDecHypercall3 (
OrigPhysicalAddress,
- EFI_SIZE_TO_PAGES (OrigLength),
+ (EndPfn - StartPfn),
(Mode == SetCBit) ? TRUE : FALSE
);
}
--
2.25.1

View File

@ -0,0 +1,36 @@
From 6b7bb04614be39e9903c602dd65ba18426f6a6f2 Mon Sep 17 00:00:00 2001
From: hanliyang <hanliyang@hygon.cn>
Date: Sun, 19 Jun 2022 18:12:35 +0800
Subject: [PATCH 8/9] OvmfPkg/BaseMemEncryptLib: Return SUCCESS if not support
SEV live migration
Add this change to avoid trigger 'ASSERT_EFI_ERROR (Status = Unsupported)'
when QEMU doesn't support SEV live migration.
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
index a64ff2a5..7b29582d 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
@@ -168,10 +168,12 @@ SetMemoryEncDecHypercall3 (
UINTN Error;
UINTN EncryptState;
- Ret = RETURN_UNSUPPORTED;
+ //
+ // Return success if not support migration.
+ //
+ Ret = RETURN_SUCCESS;
if (MemEncryptSevLiveMigrationIsEnabled ()) {
- Ret = RETURN_SUCCESS;
//
// The encryption bit is set/clear on the smallest page size, hence
// use the 4k page size in MAP_GPA_RANGE hypercall below.
--
2.25.1

View File

@ -0,0 +1,159 @@
From d9edefe3936aecbb9640a390cd990f1771e0dac2 Mon Sep 17 00:00:00 2001
From: Xin Jiang <jiangxin@hygon.cn>
Date: Wed, 10 Jan 2024 17:34:57 +0800
Subject: [PATCH 9/9] OvmfPkg/BaseMemEncryptLib: Save memory encrypt status in
reserved memory
The MMIO routine of VC handler will get memory encrypt status to
validate MMIO address. MemEncryptSevGetEncryptionMask() will enable
interrupt while interrupt must be disabled during VC.
During DXE stage, VC routine as below:
CcExitHandleVc->MemEncryptSevGetAddressRangeState->
MemEncryptSevGetEncryptionMask->PcdGet64(PcdPteMemoryEncryptionAddressOrMask)
Unfortunately, PcdGet64() will enable interrupt in VC context.
Signed-off-by: Xin Jiang <jiangxin@hygon.cn>
---
OvmfPkg/AmdSev/AmdSevX64.fdf | 5 ++++-
.../Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf | 4 ++++
.../BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c | 9 ++-------
OvmfPkg/OvmfPkg.dec | 4 ++++
OvmfPkg/OvmfPkgX64.fdf | 5 ++++-
OvmfPkg/PlatformPei/AmdSev.c | 2 ++
OvmfPkg/PlatformPei/Csv.c | 6 ++++++
OvmfPkg/PlatformPei/PlatformPei.inf | 2 ++
8 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf
index 714ab004..b0d9033f 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.fdf
+++ b/OvmfPkg/AmdSev/AmdSevX64.fdf
@@ -80,7 +80,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGui
0x012000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize
-0x013000|0x00D000
+0x013000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase|gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize
+
+0x014000|0x00C000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
index 4d32fae6..6f2f69d0 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
@@ -61,3 +61,7 @@
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr
+
+[FixedPcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
index d80ebe2f..a9d43237 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
@@ -22,8 +22,6 @@
STATIC UINT64 mCurrentAttr = 0;
STATIC BOOLEAN mCurrentAttrRead = FALSE;
-STATIC UINT64 mSevEncryptionMask = 0;
-STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE;
STATIC BOOLEAN mSevLiveMigrationStatus = FALSE;
STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE;
@@ -193,10 +191,7 @@ MemEncryptSevGetEncryptionMask (
VOID
)
{
- if (!mSevEncryptionMaskSaved) {
- mSevEncryptionMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask);
- mSevEncryptionMaskSaved = TRUE;
- }
+ UINT64 *MemEncryptStatus = (UINT64 *)(UINT64)FixedPcdGet32 (PcdMemEncrpytStatusBase);
- return mSevEncryptionMask;
+ return *MemEncryptStatus;
}
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index d50b1ae3..a6016d58 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -443,6 +443,10 @@
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|0|UINT32|0x72
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize|0|UINT32|0x73
+ ## the base address of memory encryption status.
+ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase|0|UINT32|0x74
+ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize|0|UINT32|0x75
+
[PcdsDynamic, PcdsDynamicEx]
gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index b1cf0d99..a34b9f57 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -100,7 +100,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGui
0x011000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize
-0x012000|0x00E000
+0x012000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase|gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize
+
+0x013000|0x00D000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index 553e841e..7c4ef899 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -379,6 +379,8 @@ AmdSevInitialize (
PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask);
ASSERT_RETURN_ERROR (PcdStatus);
+ *(UINT64 *)(UINT64)FixedPcdGet32 (PcdMemEncrpytStatusBase) = EncryptionMask;
+
DEBUG ((DEBUG_INFO, "SEV is enabled (mask 0x%lx)\n", EncryptionMask));
//
diff --git a/OvmfPkg/PlatformPei/Csv.c b/OvmfPkg/PlatformPei/Csv.c
index a52112d5..fe8c059b 100644
--- a/OvmfPkg/PlatformPei/Csv.c
+++ b/OvmfPkg/PlatformPei/Csv.c
@@ -33,6 +33,12 @@ CsvInitializeMemInfo (
UINT64 LowerMemorySize;
UINT64 UpperMemorySize;
+ BuildMemoryAllocationHob (
+ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdMemEncrpytStatusBase),
+ (UINT64)(UINTN) FixedPcdGet32 (PcdMemEncrpytStatusSize),
+ EfiReservedMemoryType
+ );
+
if (!CsvIsEnabled ()) {
return ;
}
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index 07de179f..c2d503fa 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -137,6 +137,8 @@
gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable
--
2.25.1

View File

@ -0,0 +1,218 @@
From ceb82e7d081399dd91cc6e0e8eabd5b7260afac0 Mon Sep 17 00:00:00 2001
From: Adttil <2429917001@qq.com>
Date: Fri, 29 Nov 2024 08:35:27 +0800
Subject: [PATCH 1/3] VirtioDxe: add support of MMIO Bar for virtio devices
As some virtio devices support MMIO BAR, add support for
it in Virtio10Dxe and VirtioPciDeviceDXE.
Signed-off-by: jiangdongxu <jiangdongxu1@huawei.com>
---
OvmfPkg/Include/Protocol/VirtioDevice.h | 12 +++
.../VirtioMmioDeviceLib/VirtioMmioDevice.c | 1 +
OvmfPkg/Virtio10Dxe/Virtio10.c | 1 +
OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c | 89 +++++++++++++++----
4 files changed, 85 insertions(+), 18 deletions(-)
diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h
index ad37f4e3..802b8970 100644
--- a/OvmfPkg/Include/Protocol/VirtioDevice.h
+++ b/OvmfPkg/Include/Protocol/VirtioDevice.h
@@ -466,6 +466,16 @@ EFI_STATUS
IN VOID *Mapping
);
+/**
+ * Note: Zero virtio devices has BAR0 of type MMIO but not PIO which do not
+ * flow the virtio 0.95 spec due to hw limiation. We extend edk2 to support
+ * such variant.
+ */
+typedef enum {
+ VirtioCfgSpaceAcessIo = 0,
+ VirtioCfgSpaceAcessMem
+} VIRTIO_CFG_SPACE_ACCESS_MODE;
+
///
/// This protocol provides an abstraction over the VirtIo transport layer
///
@@ -482,6 +492,8 @@ struct _VIRTIO_DEVICE_PROTOCOL {
//
INT32 SubSystemDeviceId;
+ VIRTIO_CFG_SPACE_ACCESS_MODE CfgAccessMode;
+
VIRTIO_GET_DEVICE_FEATURES GetDeviceFeatures;
VIRTIO_SET_GUEST_FEATURES SetGuestFeatures;
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
index fac32422..a340711d 100644
--- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
@@ -17,6 +17,7 @@
STATIC CONST VIRTIO_DEVICE_PROTOCOL mMmioDeviceProtocolTemplate = {
0, // Revision
0, // SubSystemDeviceId
+ 0, // CfgAccessMode
VirtioMmioGetDeviceFeatures, // GetDeviceFeatures
VirtioMmioSetGuestFeatures, // SetGuestFeatures
VirtioMmioSetQueueAddress, // SetQueueAddress
diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
index 970524f6..b968b016 100644
--- a/OvmfPkg/Virtio10Dxe/Virtio10.c
+++ b/OvmfPkg/Virtio10Dxe/Virtio10.c
@@ -954,6 +954,7 @@ Virtio10UnmapSharedBuffer (
STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = {
VIRTIO_SPEC_REVISION (1, 0, 0),
0, // SubSystemDeviceId, filled in dynamically
+ 0, // CfgAccessMode
Virtio10GetDeviceFeatures,
Virtio10SetGuestFeatures,
Virtio10SetQueueAddress,
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
index b4ac195b..61ff376d 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
@@ -23,6 +23,7 @@
STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate = {
0, // Revision
0, // SubSystemDeviceId
+ 0, // CfgAccessMode
VirtioPciGetDeviceFeatures, // GetDeviceFeatures
VirtioPciSetGuestFeatures, // SetGuestFeatures
VirtioPciSetQueueAddress, // SetQueueAddress
@@ -117,14 +118,25 @@ VirtioPciIoRead (
return EFI_INVALID_PARAMETER;
}
- return PciIo->Io.Read (
- PciIo,
- Width,
- PCI_BAR_IDX0,
- FieldOffset,
- Count,
- Buffer
- );
+ if (Dev->VirtioDevice.CfgAccessMode == VirtioCfgSpaceAcessIo) {
+ return PciIo->Io.Read (
+ PciIo,
+ Width,
+ PCI_BAR_IDX0,
+ FieldOffset,
+ Count,
+ Buffer
+ );
+ } else {
+ return PciIo->Mem.Read (
+ PciIo,
+ Width,
+ PCI_BAR_IDX0,
+ FieldOffset,
+ Count,
+ Buffer
+ );
+ }
}
/**
@@ -197,14 +209,25 @@ VirtioPciIoWrite (
return EFI_INVALID_PARAMETER;
}
- return PciIo->Io.Write (
- PciIo,
- Width,
- PCI_BAR_IDX0,
- FieldOffset,
- Count,
- &Value
- );
+ if (Dev->VirtioDevice.CfgAccessMode == VirtioCfgSpaceAcessIo) {
+ return PciIo->Io.Write (
+ PciIo,
+ Width,
+ PCI_BAR_IDX0,
+ FieldOffset,
+ Count,
+ &Value
+ );
+ } else {
+ return PciIo->Mem.Write (
+ PciIo,
+ Width,
+ PCI_BAR_IDX0,
+ FieldOffset,
+ Count,
+ &Value
+ );
+ }
}
/**
@@ -332,6 +355,7 @@ VirtioPciInit (
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
PCI_TYPE00 Pci;
+ VOID *Resources;
ASSERT (Device != NULL);
PciIo = Device->PciIo;
@@ -373,6 +397,27 @@ VirtioPciInit (
Device->DeviceSpecificConfigurationOffset =
VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI;
+ Status = PciIo->GetBarAttributes(PciIo, PCI_BAR_IDX0, NULL, &Resources);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (*(UINT8 *)Resources == ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR) {
+ EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
+
+ Descriptor = Resources;
+ if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+ Device->VirtioDevice.CfgAccessMode = VirtioCfgSpaceAcessMem;
+ DEBUG ((DEBUG_INFO, "%a: Legacy Virtio MMIO BAR used.\n", __FUNCTION__));
+ } else {
+ Device->VirtioDevice.CfgAccessMode = VirtioCfgSpaceAcessIo;
+ DEBUG ((DEBUG_INFO, "%a: Legacy Virtio IO BAR used.\n", __FUNCTION__));
+ }
+ } else {
+ DEBUG ((DEBUG_WARN, "%a: Cannot determine BAR0 type, assume IO.\n", __FUNCTION__));
+ Device->VirtioDevice.CfgAccessMode = VirtioCfgSpaceAcessIo;
+ }
+
return EFI_SUCCESS;
}
@@ -434,6 +479,7 @@ VirtioPciDeviceBindingStart (
{
VIRTIO_PCI_DEVICE *Device;
EFI_STATUS Status;
+ UINT64 Attributes;
Device = (VIRTIO_PCI_DEVICE *)AllocateZeroPool (sizeof *Device);
if (Device == NULL) {
@@ -473,11 +519,18 @@ VirtioPciDeviceBindingStart (
goto ClosePciIo;
}
+ Status = Device->PciIo->Attributes (Device->PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0, &Attributes);
+ if (EFI_ERROR (Status)) {
+ goto ClosePciIo;
+ }
+
+ Attributes &= (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_IO);
Status = Device->PciIo->Attributes (
Device->PciIo,
EfiPciIoAttributeOperationEnable,
- (EFI_PCI_IO_ATTRIBUTE_IO |
- EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
+ Attributes | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER,
NULL
);
if (EFI_ERROR (Status)) {
--
2.43.0

View File

@ -0,0 +1,123 @@
From 05de598734e741c596394bfbe42b1ab7af8316e1 Mon Sep 17 00:00:00 2001
From: Adttil <2429917001@qq.com>
Date: Fri, 29 Nov 2024 08:46:00 +0800
Subject: [PATCH 2/3] Virtio: wait virtio device reset done.
The Virtio 1.0 driver performs subsequent negotiation operations
only after the device reset operation is complete.
Implement this in the VirtioScsiDxe and VirtioBlkDxe.
Signed-off-by: jiangdongxu <jiangdongxu1@huawei.com>
---
OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 21 +++++++++++++++++++++
OvmfPkg/VirtioScsiDxe/VirtioScsi.c | 21 +++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index 74ed52f9..eed56994 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -28,6 +28,9 @@
#include "VirtioBlk.h"
+#define MAX_RETRY_TIMES 1000
+#define DEVICE_WAIT_INTVL 1000
+
/**
Convenience macros to read and write region 0 IO space elements of the
@@ -721,6 +724,10 @@ VirtioBlkInit (
UINT32 OptIoSize;
UINT16 QueueSize;
UINT64 RingBaseShift;
+ UINT8 DevStat;
+ UINT16 RetryTimes;
+
+ RetryTimes = MAX_RETRY_TIMES;
PhysicalBlockExp = 0;
AlignmentOffset = 0;
@@ -735,12 +742,26 @@ VirtioBlkInit (
goto Failed;
}
+ Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat);
+ while (DevStat != NextDevStat && RetryTimes) {
+ gBS->Stall(DEVICE_WAIT_INTVL);
+ Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat);
+ RetryTimes--;
+ }
+
NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence
Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto Failed;
}
+ Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat);
+ while (DevStat != NextDevStat && RetryTimes) {
+ gBS->Stall(DEVICE_WAIT_INTVL);
+ Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat);
+ RetryTimes--;
+ }
+
NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
index 3705f5fc..580fe731 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
@@ -43,6 +43,9 @@
#include "VirtioScsi.h"
+#define MAX_RETRY_TIMES 1000
+#define DEVICE_WAIT_INTVL 1000
+
/**
Convenience macros to read and write configuration elements of the
@@ -932,6 +935,10 @@ VirtioScsiInit (
UINT16 MaxChannel; // for validation only
UINT32 NumQueues; // for validation only
UINT16 QueueSize;
+ UINT8 DevStat;
+ UINT16 RetryTimes;
+
+ RetryTimes = MAX_RETRY_TIMES;
//
// Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
@@ -942,12 +949,26 @@ VirtioScsiInit (
goto Failed;
}
+ Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat);
+ while (DevStat != NextDevStat && RetryTimes) {
+ gBS->Stall(DEVICE_WAIT_INTVL);
+ Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat);
+ RetryTimes--;
+ }
+
NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence
Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto Failed;
}
+ Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat);
+ while (DevStat != NextDevStat && RetryTimes) {
+ gBS->Stall(DEVICE_WAIT_INTVL);
+ Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat);
+ RetryTimes--;
+ }
+
NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
--
2.43.0

View File

@ -0,0 +1,250 @@
From 734457162d02f6b4d66b8eb82da0717765fceebe Mon Sep 17 00:00:00 2001
From: Adttil <2429917001@qq.com>
Date: Fri, 29 Nov 2024 09:04:13 +0800
Subject: [PATCH 3/3] VirtioBlk: split large IO according to segment_size_max
When the VirtioBlk device is initialized, the value of SegmentSizeMax
is obtained based on the feature capability. Then delivere the requests
based on the value of SegmentSizeMax.
Signed-off-by: jiangdongxu <jiangdongxu1@huawei.com>
---
MdePkg/Include/Protocol/BlockIo.h | 10 ++
OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 148 +++++++++++++++++++++---------
2 files changed, 117 insertions(+), 41 deletions(-)
diff --git a/MdePkg/Include/Protocol/BlockIo.h b/MdePkg/Include/Protocol/BlockIo.h
index ac9adf7a..ac5e1c2a 100644
--- a/MdePkg/Include/Protocol/BlockIo.h
+++ b/MdePkg/Include/Protocol/BlockIo.h
@@ -197,6 +197,16 @@ typedef struct {
/// granularity as a number of logical blocks.
///
UINT32 OptimalTransferLengthGranularity;
+
+ ///
+ /// Maximum size of any single segment
+ ///
+ UINT32 MaxSegmentSize;
+
+ ///
+ /// Maximum number of segments in a request
+ ///
+ UINT32 MaxSegments;
} EFI_BLOCK_IO_MEDIA;
#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index eed56994..6d7c7aef 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -31,6 +31,8 @@
#define MAX_RETRY_TIMES 1000
#define DEVICE_WAIT_INTVL 1000
+#define DEFAULT_MAX_SEGMENTS 32
+
/**
Convenience macros to read and write region 0 IO space elements of the
@@ -460,6 +462,68 @@ FreeHostStatusBuffer:
return Status;
}
+STATIC
+EFI_STATUS
+EFIAPI
+VirtioBlkReadWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN BOOLEAN RequestIsWrite
+ )
+{
+ VBLK_DEV *Dev;
+ EFI_STATUS Status;
+ UINT32 SizeMax;
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);
+ Status = VerifyReadWriteRequest (
+ &Dev->BlockIoMedia,
+ Lba,
+ BufferSize,
+ RequestIsWrite
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SizeMax = Dev->BlockIoMedia.MaxSegmentSize;
+ while (BufferSize >= SizeMax) {
+ Status = SynchronousRequest (
+ Dev,
+ Lba,
+ SizeMax,
+ Buffer,
+ RequestIsWrite
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba += SizeMax / Dev->BlockIoMedia.BlockSize;
+ BufferSize -= SizeMax;
+ Buffer = (CHAR8 *)Buffer + SizeMax;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ return SynchronousRequest (
+ Dev,
+ Lba,
+ BufferSize,
+ Buffer,
+ RequestIsWrite
+ );
+}
+
/**
ReadBlocks() operation for virtio-blk.
@@ -487,30 +551,13 @@ VirtioBlkReadBlocks (
OUT VOID *Buffer
)
{
- VBLK_DEV *Dev;
- EFI_STATUS Status;
-
- if (BufferSize == 0) {
- return EFI_SUCCESS;
- }
-
- Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);
- Status = VerifyReadWriteRequest (
- &Dev->BlockIoMedia,
- Lba,
- BufferSize,
- FALSE // RequestIsWrite
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- return SynchronousRequest (
- Dev,
+ return VirtioBlkReadWriteBlocks(
+ This,
+ MediaId,
Lba,
BufferSize,
Buffer,
- FALSE // RequestIsWrite
+ FALSE // RequestIsRead
);
}
@@ -541,26 +588,9 @@ VirtioBlkWriteBlocks (
IN VOID *Buffer
)
{
- VBLK_DEV *Dev;
- EFI_STATUS Status;
-
- if (BufferSize == 0) {
- return EFI_SUCCESS;
- }
-
- Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);
- Status = VerifyReadWriteRequest (
- &Dev->BlockIoMedia,
- Lba,
- BufferSize,
- TRUE // RequestIsWrite
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- return SynchronousRequest (
- Dev,
+ return VirtioBlkReadWriteBlocks(
+ This,
+ MediaId,
Lba,
BufferSize,
Buffer,
@@ -716,6 +746,8 @@ VirtioBlkInit (
UINT8 NextDevStat;
EFI_STATUS Status;
+ UINT32 MaxSegmentSize;
+ UINT32 MaxSegments;
UINT64 Features;
UINT64 NumSectors;
UINT32 BlockSize;
@@ -814,6 +846,36 @@ VirtioBlkInit (
BlockSize = 512;
}
+ if (Features & VIRTIO_BLK_F_SIZE_MAX) {
+ Status = VIRTIO_CFG_READ (Dev, SizeMax, &MaxSegmentSize);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ if (MaxSegmentSize == 0) {
+ //
+ // We need at least one 4KB page.
+ //
+ MaxSegmentSize = SIZE_4KB;
+ }
+ } else {
+ MaxSegmentSize = SIZE_512KB;
+ }
+
+ if (Features & VIRTIO_BLK_F_SEG_MAX) {
+ Status = VIRTIO_CFG_READ (Dev, SegMax, &MaxSegments);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ if (MaxSegments == 0) {
+ //
+ // We need at least one SG element, whatever they say.
+ //
+ MaxSegments = 1;
+ }
+ } else {
+ MaxSegments = DEFAULT_MAX_SEGMENTS;
+ }
+
if (Features & VIRTIO_BLK_F_TOPOLOGY) {
Status = VIRTIO_CFG_READ (
Dev,
@@ -955,6 +1017,8 @@ VirtioBlkInit (
Dev->BlockIoMedia.ReadOnly = (BOOLEAN)((Features & VIRTIO_BLK_F_RO) != 0);
Dev->BlockIoMedia.WriteCaching = (BOOLEAN)((Features & VIRTIO_BLK_F_FLUSH) != 0);
Dev->BlockIoMedia.BlockSize = BlockSize;
+ Dev->BlockIoMedia.MaxSegments = MaxSegments;
+ Dev->BlockIoMedia.MaxSegmentSize = MaxSegmentSize;
Dev->BlockIoMedia.IoAlign = 0;
Dev->BlockIoMedia.LastBlock = DivU64x32 (
NumSectors,
@@ -968,6 +1032,8 @@ VirtioBlkInit (
Dev->BlockIoMedia.BlockSize,
Dev->BlockIoMedia.LastBlock + 1
));
+ DEBUG ((DEBUG_INFO, "%a: MaxSegments=0x%x[B] MaxSegmentSize=0x%x[B]\n",
+ __FUNCTION__, Dev->BlockIoMedia.MaxSegments, Dev->BlockIoMedia.MaxSegmentSize));
if (Features & VIRTIO_BLK_F_TOPOLOGY) {
Dev->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
--
2.43.0

View File

@ -7,7 +7,7 @@
Name: edk2
Version: %{stable_date}
Release: 14
Release: 16
Summary: EFI Development Kit II
License: BSD-2-Clause-Patent and OpenSSL and MIT
URL: https://github.com/tianocore/edk2
@ -110,6 +110,23 @@ patch65: 0065-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch
patch66: 0066-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-guest.patch
patch67: 0067-OvmfPkg-Use-classic-mmio-window-for-CSV-guest.patch
# Support live migrate Hygon CSV/CSV2/CSV3 guest
patch68: 0068-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch
patch69: 0069-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch
patch70: 0070-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch
patch71: 0071-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch
patch72: 0072-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch
patch73: 0073-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch
patch74: 0074-OvmfPkg-BaseMemcryptSevLib-Correct-the-calculation-o.patch
patch75: 0075-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-not-supp.patch
# Fix nesting #VC in mmio check
patch76: 0076-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt-status.patch
# Support vdpa blk/scsi device boot
patch77: 0077-VirtioDxe-add-support-of-MMIO-Bar-for-virtio-devices.patch
patch78: 0078-Virtio-wait-virtio-device-reset-done.patch
patch79: 0079-VirtioBlk-split-large-IO-according-to-segment_size_m.patch
BuildRequires: acpica-tools gcc gcc-c++ libuuid-devel python3 bc nasm python3-unversioned-command isl
%description
@ -379,6 +396,12 @@ chmod +x %{buildroot}%{_bindir}/Rsa2048Sha256GenerateKeys
%endif
%changelog
* Fri Nov 29 2024 adttil<2429917001@qq.com> - 202308-16
- vdpa: support vdpa blk/scsi device boot
* Wed Oct 23 2024 hanliyang<hanliyang@hygon.cn> - 202308-15
- Add support for live migration of Hygon CSV1/2/3 guests, fix nesting #VC
* Tue Nov 12 2024 hanliyang<hanliyang@hygon.cn> - 202308-14
- Add support for running in Hygon CSV3 guest