Compare commits

...

11 Commits

Author SHA1 Message Date
openeuler-ci-bot
db413a8c0c
!292 Update LoongArch virtual machine
From: @yetist 
Reviewed-by: @lixianglai, @caojinhuahw 
Signed-off-by: @caojinhuahw
2024-12-17 06:51:05 +00:00
Xiaotian Wu
5273094c17 Update LoongArch virtual machine 2024-12-17 09:22:07 +08:00
openeuler-ci-bot
19e2f998a8
!296 sync 24.03 LTS patch list
From: @JiaboFeng 
Reviewed-by: @imxcc 
Signed-off-by: @imxcc
2024-12-12 08:45:31 +00:00
Adttil
da93b0b1f2 vdpa: support vdpa blk/scsi device boot 2024-12-12 16:25:48 +08:00
hanliyang
dbb569a545 Support live migration for Hygon CSV1/2/3 guests, fix nesting #VC
The live migration of Hygon CSV1/2/3 guest depends on the KVM
hypercall KVM_HC_MAP_GPA_RANGE, add code to sync page enc/dec
status to KVM.

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)

Signed-off-by: hanliyang <hanliyang@hygon.cn>
2024-12-12 16:25:36 +08:00
openeuler-ci-bot
ef32b54b56
!291 [openEuler-24.03-LTS-SP1]Hygon: Add support to run in the Hygon CSV3 guest
From: @hanliyang 
Reviewed-by: @caojinhuahw 
Signed-off-by: @caojinhuahw
2024-11-26 07:19:54 +00:00
hanliyang
3ab396d92e Add support for Hygon CSV3 guest
Cherry-picked from https://gitee.com/src-openeuler/edk2/tree/openEuler-24.03-LTS

Reference the commit 42da937f6ebc ("Add support for Hygon CSV3 guest")
in https://gitee.com/src-openeuler/edk2/tree/openEuler-24.03-LTS.

Signed-off-by: hanliyang <hanliyang@hygon.cn>
2024-11-12 14:59:56 +08:00
openeuler-ci-bot
9d8e1bd5d8
!285 Fix CVE-2023-45236、CVE-2023-45237
From: @jacob1996 
Reviewed-by: @caojinhuahw 
Signed-off-by: @caojinhuahw
2024-10-23 01:25:23 +00:00
ShenYage
c74770f08b Fix CVE-2023-45236、CVE-2023-45237
Signed-off-by: ShenYage <shenyage1@huawei.com>
2024-10-15 23:08:29 +08:00
openeuler-ci-bot
defff199a5
!276 [sync] PR-271: fix CVE-2024-38796
From: @openeuler-sync-bot 
Reviewed-by: @caojinhuahw 
Signed-off-by: @caojinhuahw
2024-10-14 03:50:09 +00:00
zhangxianting
c19c4c36f9 fix CVE-2024-38796
(cherry picked from commit e90700e1bbee8afb2e66b8b19bfce953a9146841)
2024-10-14 09:17:12 +08:00
30 changed files with 7330 additions and 1 deletions

View File

@ -0,0 +1,32 @@
From c95233b8525ca6828921affd1496146cff262e65 Mon Sep 17 00:00:00 2001
From: Doug Flick <dougflick@microsoft.com>
Date: Fri, 27 Sep 2024 12:08:55 -0700
Subject: [PATCH] MdePkg: Fix overflow issue in BasePeCoffLib
The RelocDir->Size is a UINT32 value, and RelocDir->VirtualAddress is
also a UINT32 value. The current code does not check for overflow when
adding RelocDir->Size to RelocDir->VirtualAddress. This patch adds a
check to ensure that the addition does not overflow.
Signed-off-by: Doug Flick <dougflick@microsoft.com>
Authored-by: sriraamx gobichettipalayam <sri..@intel.com>
---
MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
index 86ff2e769b..128090d98e 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
@@ -1054,7 +1054,7 @@ PeCoffLoaderRelocateImage (
RelocDir = &Hdr.Te->DataDirectory[0];
}
- if ((RelocDir != NULL) && (RelocDir->Size > 0)) {
+ if ((RelocDir != NULL) && (RelocDir->Size > 0) && (RelocDir->Size - 1 < MAX_UINT32 - RelocDir->VirtualAddress)) {
RelocBase = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress, TeStrippedOffset);
RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (
ImageContext,
--
2.20.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,823 @@
From bb6d7763998a29ac05144d382966fe9fd5b7ef78 Mon Sep 17 00:00:00 2001
From: Doug Flick <dougflick@microsoft.com>
Date: Wed, 8 May 2024 22:56:29 -0700
Subject: [PATCH 2/2] NetworkPkg TcpDxe: SECURITY PATCH CVE-2023-45236
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4541
REF: https://www.rfc-editor.org/rfc/rfc1948.txt
REF: https://www.rfc-editor.org/rfc/rfc6528.txt
REF: https://www.rfc-editor.org/rfc/rfc9293.txt
Bug Overview:
PixieFail Bug #8
CVE-2023-45236
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N
CWE-200 Exposure of Sensitive Information to an Unauthorized Actor
Updates TCP ISN generation to use a cryptographic hash of the
connection's identifying parameters and a secret key.
This prevents an attacker from guessing the ISN used for some other
connection.
This is follows the guidance in RFC 1948, RFC 6528, and RFC 9293.
RFC: 9293 Section 3.4.1. Initial Sequence Number Selection
A TCP implementation MUST use the above type of "clock" for clock-
driven selection of initial sequence numbers (MUST-8), and SHOULD
generate its initial sequence numbers with the expression:
ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
where M is the 4 microsecond timer, and F() is a pseudorandom
function (PRF) of the connection's identifying parameters ("localip,
localport, remoteip, remoteport") and a secret key ("secretkey")
(SHLD-1). F() MUST NOT be computable from the outside (MUST-9), or
an attacker could still guess at sequence numbers from the ISN used
for some other connection. The PRF could be implemented as a
cryptographic hash of the concatenation of the TCP connection
parameters and some secret data. For discussion of the selection of
a specific hash algorithm and management of the secret key data,
please see Section 3 of [42].
For each connection there is a send sequence number and a receive
sequence number. The initial send sequence number (ISS) is chosen by
the data sending TCP peer, and the initial receive sequence number
(IRS) is learned during the connection-establishing procedure.
For a connection to be established or initialized, the two TCP peers
must synchronize on each other's initial sequence numbers. This is
done in an exchange of connection-establishing segments carrying a
control bit called "SYN" (for synchronize) and the initial sequence
numbers. As a shorthand, segments carrying the SYN bit are also
called "SYNs". Hence, the solution requires a suitable mechanism for
picking an initial sequence number and a slightly involved handshake
to exchange the ISNs.
Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>
Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
NetworkPkg/SecurityFixes.yaml | 22 +++
NetworkPkg/TcpDxe/TcpDriver.c | 92 ++++++++++++-
NetworkPkg/TcpDxe/TcpDxe.inf | 8 +-
NetworkPkg/TcpDxe/TcpFunc.h | 23 ++--
NetworkPkg/TcpDxe/TcpInput.c | 13 +-
NetworkPkg/TcpDxe/TcpMain.h | 59 ++++++--
NetworkPkg/TcpDxe/TcpMisc.c | 244 ++++++++++++++++++++++++++++++++--
NetworkPkg/TcpDxe/TcpTimer.c | 3 +-
8 files changed, 415 insertions(+), 49 deletions(-)
diff --git a/NetworkPkg/SecurityFixes.yaml b/NetworkPkg/SecurityFixes.yaml
index a44cfc4..00ebacb 100644
--- a/NetworkPkg/SecurityFixes.yaml
+++ b/NetworkPkg/SecurityFixes.yaml
@@ -122,6 +122,28 @@ CVE_2023_45235:
- http://www.openwall.com/lists/oss-security/2024/01/16/2
- http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
- https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
+CVE_2023_45236:
+ commit_titles:
+ - "NetworkPkg: TcpDxe: SECURITY PATCH CVE-2023-45236 Patch"
+ cve: CVE-2023-45236
+ date_reported: 2023-08-28 13:56 UTC
+ description: "Bug 08 - edk2/NetworkPkg: Predictable TCP Initial Sequence Numbers"
+ note:
+ files_impacted:
+ - NetworkPkg/Include/Library/NetLib.h
+ - NetworkPkg/TcpDxe/TcpDriver.c
+ - NetworkPkg/TcpDxe/TcpDxe.inf
+ - NetworkPkg/TcpDxe/TcpFunc.h
+ - NetworkPkg/TcpDxe/TcpInput.c
+ - NetworkPkg/TcpDxe/TcpMain.h
+ - NetworkPkg/TcpDxe/TcpMisc.c
+ - NetworkPkg/TcpDxe/TcpTimer.c
+ links:
+ - https://bugzilla.tianocore.org/show_bug.cgi?id=4541
+ - https://nvd.nist.gov/vuln/detail/CVE-2023-45236
+ - http://www.openwall.com/lists/oss-security/2024/01/16/2
+ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
+ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
CVE_2023_45237:
commit_titles:
- "NetworkPkg:: SECURITY PATCH CVE 2023-45237"
diff --git a/NetworkPkg/TcpDxe/TcpDriver.c b/NetworkPkg/TcpDxe/TcpDriver.c
index f5d10c6..32cff88 100644
--- a/NetworkPkg/TcpDxe/TcpDriver.c
+++ b/NetworkPkg/TcpDxe/TcpDriver.c
@@ -83,6 +83,12 @@ EFI_SERVICE_BINDING_PROTOCOL gTcpServiceBinding = {
TcpServiceBindingDestroyChild
};
+//
+// This is the handle for the Hash2ServiceBinding Protocol instance this driver produces
+// if the platform does not provide one.
+//
+EFI_HANDLE mHash2ServiceHandle = NULL;
+
/**
Create and start the heartbeat timer for the TCP driver.
@@ -165,6 +171,23 @@ TcpDriverEntryPoint (
EFI_STATUS Status;
UINT32 Random;
+ //
+ // Initialize the Secret used for hashing TCP sequence numbers
+ //
+ // Normally this should be regenerated periodically, but since
+ // this is only used for UEFI networking and not a general purpose
+ // operating system, it is not necessary to regenerate it.
+ //
+ Status = PseudoRandomU32 (&mTcpGlobalSecret);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
+
+ //
+ // Get a random number used to generate a random port number
+ // Intentionally not linking this to mTcpGlobalSecret to avoid leaking information about the secret
+ //
Status = PseudoRandomU32 (&Random);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a Failed to generate random number: %r\n", __func__, Status));
@@ -207,9 +230,8 @@ TcpDriverEntryPoint (
}
//
- // Initialize ISS and random port.
+ // Initialize the random port.
//
- mTcpGlobalIss = Random % mTcpGlobalIss;
mTcp4RandomPort = (UINT16)(TCP_PORT_KNOWN + (Random % TCP_PORT_KNOWN));
mTcp6RandomPort = mTcp4RandomPort;
@@ -224,6 +246,8 @@ TcpDriverEntryPoint (
@param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
@retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
+ @retval EFI_UNSUPPORTED Service Binding Protocols are unavailable.
+ @retval EFI_ALREADY_STARTED The TCP driver is already started on the controller.
@retval EFI_SUCCESS A new IP6 service binding private was created.
**/
@@ -234,11 +258,13 @@ TcpCreateService (
IN UINT8 IpVersion
)
{
- EFI_STATUS Status;
- EFI_GUID *IpServiceBindingGuid;
- EFI_GUID *TcpServiceBindingGuid;
- TCP_SERVICE_DATA *TcpServiceData;
- IP_IO_OPEN_DATA OpenData;
+ EFI_STATUS Status;
+ EFI_GUID *IpServiceBindingGuid;
+ EFI_GUID *TcpServiceBindingGuid;
+ TCP_SERVICE_DATA *TcpServiceData;
+ IP_IO_OPEN_DATA OpenData;
+ EFI_SERVICE_BINDING_PROTOCOL *Hash2ServiceBinding;
+ EFI_HASH2_PROTOCOL *Hash2Protocol;
if (IpVersion == IP_VERSION_4) {
IpServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;
@@ -272,6 +298,33 @@ TcpCreateService (
return EFI_UNSUPPORTED;
}
+ Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2Protocol);
+ if (EFI_ERROR (Status)) {
+ //
+ // If we can't find the Hashing protocol, then we need to create one.
+ //
+
+ //
+ // Platform is expected to publish the hash service binding protocol to support TCP.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHash2ServiceBindingProtocolGuid,
+ NULL,
+ (VOID **)&Hash2ServiceBinding
+ );
+ if (EFI_ERROR (Status) || (Hash2ServiceBinding == NULL) || (Hash2ServiceBinding->CreateChild == NULL)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Create an instance of the hash protocol for this controller.
+ //
+ Status = Hash2ServiceBinding->CreateChild (Hash2ServiceBinding, &mHash2ServiceHandle);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
//
// Create the TCP service data.
//
@@ -423,6 +476,7 @@ TcpDestroyService (
EFI_STATUS Status;
LIST_ENTRY *List;
TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
+ EFI_SERVICE_BINDING_PROTOCOL *Hash2ServiceBinding;
ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
@@ -439,6 +493,30 @@ TcpDestroyService (
return EFI_SUCCESS;
}
+ //
+ // Destroy the Hash2ServiceBinding instance if it is created by Tcp driver.
+ //
+ if (mHash2ServiceHandle != NULL) {
+ Status = gBS->LocateProtocol (
+ &gEfiHash2ServiceBindingProtocolGuid,
+ NULL,
+ (VOID **)&Hash2ServiceBinding
+ );
+ if (EFI_ERROR (Status) || (Hash2ServiceBinding == NULL) || (Hash2ServiceBinding->DestroyChild == NULL)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Destroy the instance of the hashing protocol for this controller.
+ //
+ Status = Hash2ServiceBinding->DestroyChild (Hash2ServiceBinding, &mHash2ServiceHandle);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ mHash2ServiceHandle = NULL;
+ }
+
Status = gBS->OpenProtocol (
NicHandle,
ServiceBindingGuid,
diff --git a/NetworkPkg/TcpDxe/TcpDxe.inf b/NetworkPkg/TcpDxe/TcpDxe.inf
index 1b30980..dc08f76 100644
--- a/NetworkPkg/TcpDxe/TcpDxe.inf
+++ b/NetworkPkg/TcpDxe/TcpDxe.inf
@@ -6,6 +6,7 @@
# stack has been loaded in system. This driver supports both IPv4 and IPv6 network stack.
#
# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -68,7 +69,6 @@
NetLib
IpIoLib
-
[Protocols]
## SOMETIMES_CONSUMES
## SOMETIMES_PRODUCES
@@ -81,6 +81,12 @@
gEfiIp6ServiceBindingProtocolGuid ## TO_START
gEfiTcp6ProtocolGuid ## BY_START
gEfiTcp6ServiceBindingProtocolGuid ## BY_START
+ gEfiHash2ProtocolGuid ## BY_START
+ gEfiHash2ServiceBindingProtocolGuid ## BY_START
+
+[Guids]
+ gEfiHashAlgorithmMD5Guid ## CONSUMES
+ gEfiHashAlgorithmSha256Guid ## CONSUMES
[Depex]
gEfiHash2ServiceBindingProtocolGuid
diff --git a/NetworkPkg/TcpDxe/TcpFunc.h b/NetworkPkg/TcpDxe/TcpFunc.h
index a7af01f..35ea55d 100644
--- a/NetworkPkg/TcpDxe/TcpFunc.h
+++ b/NetworkPkg/TcpDxe/TcpFunc.h
@@ -2,7 +2,7 @@
Declaration of external functions shared in TCP driver.
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -36,8 +36,11 @@ VOID
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
+ @retval EFI_SUCCESS The operation completed successfully
+ @retval others The underlying functions failed and could not complete the operation
+
**/
-VOID
+EFI_STATUS
TcpInitTcbLocal (
IN OUT TCP_CB *Tcb
);
@@ -128,17 +131,6 @@ TcpCloneTcb (
IN TCP_CB *Tcb
);
-/**
- Compute an ISS to be used by a new connection.
-
- @return The result ISS.
-
-**/
-TCP_SEQNO
-TcpGetIss (
- VOID
- );
-
/**
Get the local mss.
@@ -202,8 +194,11 @@ TcpFormatNetbuf (
@param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
connection.
+ @retval EFI_SUCCESS The operation completed successfully
+ @retval others The underlying functions failed and could not complete the operation
+
**/
-VOID
+EFI_STATUS
TcpOnAppConnect (
IN OUT TCP_CB *Tcb
);
diff --git a/NetworkPkg/TcpDxe/TcpInput.c b/NetworkPkg/TcpDxe/TcpInput.c
index 7b329be..63fd03a 100644
--- a/NetworkPkg/TcpDxe/TcpInput.c
+++ b/NetworkPkg/TcpDxe/TcpInput.c
@@ -724,6 +724,7 @@ TcpInput (
TCP_SEQNO Urg;
UINT16 Checksum;
INT32 Usable;
+ EFI_STATUS Status;
ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
@@ -872,7 +873,17 @@ TcpInput (
Tcb->LocalEnd.Port = Head->DstPort;
Tcb->RemoteEnd.Port = Head->SrcPort;
- TcpInitTcbLocal (Tcb);
+ Status = TcpInitTcbLocal (Tcb);
+ if (EFI_ERROR (Status)) {
+ DEBUG (
+ (DEBUG_ERROR,
+ "TcpInput: discard a segment because failed to init local end for TCB %p\n",
+ Tcb)
+ );
+
+ goto DISCARD;
+ }
+
TcpInitTcbPeer (Tcb, Seg, &Option);
TcpSetState (Tcb, TCP_SYN_RCVD);
diff --git a/NetworkPkg/TcpDxe/TcpMain.h b/NetworkPkg/TcpDxe/TcpMain.h
index c0c9b7f..dbc1da2 100644
--- a/NetworkPkg/TcpDxe/TcpMain.h
+++ b/NetworkPkg/TcpDxe/TcpMain.h
@@ -3,7 +3,7 @@
It is the common head file for all Tcp*.c in TCP driver.
Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -13,6 +13,7 @@
#include <Protocol/ServiceBinding.h>
#include <Protocol/DriverBinding.h>
+#include <Protocol/Hash2.h>
#include <Library/IpIoLib.h>
#include <Library/DevicePathLib.h>
#include <Library/PrintLib.h>
@@ -31,7 +32,7 @@ extern EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable;
extern LIST_ENTRY mTcpRunQue;
extern LIST_ENTRY mTcpListenQue;
-extern TCP_SEQNO mTcpGlobalIss;
+extern TCP_SEQNO mTcpGlobalSecret;
extern UINT32 mTcpTick;
///
@@ -45,14 +46,6 @@ extern UINT32 mTcpTick;
#define TCP_EXPIRE_TIME 65535
-///
-/// The implementation selects the initial send sequence number and the unit to
-/// be added when it is increased.
-///
-#define TCP_BASE_ISS 0x4d7e980b
-#define TCP_ISS_INCREMENT_1 2048
-#define TCP_ISS_INCREMENT_2 100
-
typedef union {
EFI_TCP4_CONFIG_DATA Tcp4CfgData;
EFI_TCP6_CONFIG_DATA Tcp6CfgData;
@@ -774,4 +767,50 @@ Tcp6Poll (
IN EFI_TCP6_PROTOCOL *This
);
+/**
+ Retrieves the Initial Sequence Number (ISN) for a TCP connection identified by local
+ and remote IP addresses and ports.
+
+ This method is based on https://datatracker.ietf.org/doc/html/rfc9293#section-3.4.1
+ Where the ISN is computed as follows:
+ ISN = TimeStamp + MD5(LocalIP, LocalPort, RemoteIP, RemotePort, Secret)
+
+ Otherwise:
+ ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
+
+ "Here M is the 4 microsecond timer, and F() is a pseudorandom function (PRF) of the
+ connection's identifying parameters ("localip, localport, remoteip, remoteport")
+ and a secret key ("secretkey") (SHLD-1). F() MUST NOT be computable from the
+ outside (MUST-9), or an attacker could still guess at sequence numbers from the
+ ISN used for some other connection. The PRF could be implemented as a
+ cryptographic hash of the concatenation of the TCP connection parameters and some
+ secret data. For discussion of the selection of a specific hash algorithm and
+ management of the secret key data."
+
+ @param[in] LocalIp A pointer to the local IP address of the TCP connection.
+ @param[in] LocalIpSize The size, in bytes, of the LocalIp buffer.
+ @param[in] LocalPort The local port number of the TCP connection.
+ @param[in] RemoteIp A pointer to the remote IP address of the TCP connection.
+ @param[in] RemoteIpSize The size, in bytes, of the RemoteIp buffer.
+ @param[in] RemotePort The remote port number of the TCP connection.
+ @param[out] Isn A pointer to the variable that will receive the Initial
+ Sequence Number (ISN).
+
+ @retval EFI_SUCCESS The operation completed successfully, and the ISN was
+ retrieved.
+ @retval EFI_INVALID_PARAMETER One or more of the input parameters are invalid.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+
+**/
+EFI_STATUS
+TcpGetIsn (
+ IN UINT8 *LocalIp,
+ IN UINTN LocalIpSize,
+ IN UINT16 LocalPort,
+ IN UINT8 *RemoteIp,
+ IN UINTN RemoteIpSize,
+ IN UINT16 RemotePort,
+ OUT TCP_SEQNO *Isn
+ );
+
#endif
diff --git a/NetworkPkg/TcpDxe/TcpMisc.c b/NetworkPkg/TcpDxe/TcpMisc.c
index c93212d..753dec5 100644
--- a/NetworkPkg/TcpDxe/TcpMisc.c
+++ b/NetworkPkg/TcpDxe/TcpMisc.c
@@ -3,7 +3,7 @@
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -20,7 +20,34 @@ LIST_ENTRY mTcpListenQue = {
&mTcpListenQue
};
-TCP_SEQNO mTcpGlobalIss = TCP_BASE_ISS;
+//
+// The Session secret
+// This must be initialized to a random value at boot time
+//
+TCP_SEQNO mTcpGlobalSecret;
+
+//
+// Union to hold either an IPv4 or IPv6 address
+// This is used to simplify the ISN hash computation
+//
+typedef union {
+ UINT8 IPv4[4];
+ UINT8 IPv6[16];
+} NETWORK_ADDRESS;
+
+//
+// The ISN is computed by hashing this structure
+// It is initialized with the local and remote IP addresses and ports
+// and the secret
+//
+//
+typedef struct {
+ UINT16 LocalPort;
+ UINT16 RemotePort;
+ NETWORK_ADDRESS LocalAddress;
+ NETWORK_ADDRESS RemoteAddress;
+ TCP_SEQNO Secret;
+} ISN_HASH_CTX;
CHAR16 *mTcpStateName[] = {
L"TCP_CLOSED",
@@ -41,12 +68,18 @@ CHAR16 *mTcpStateName[] = {
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
+ @retval EFI_SUCCESS The operation completed successfully
+ @retval others The underlying functions failed and could not complete the operation
+
**/
-VOID
+EFI_STATUS
TcpInitTcbLocal (
IN OUT TCP_CB *Tcb
)
{
+ TCP_SEQNO Isn;
+ EFI_STATUS Status;
+
//
// Compute the checksum of the fixed parts of pseudo header
//
@@ -57,6 +90,16 @@ TcpInitTcbLocal (
0x06,
0
);
+
+ Status = TcpGetIsn (
+ Tcb->LocalEnd.Ip.v4.Addr,
+ sizeof (IPv4_ADDRESS),
+ Tcb->LocalEnd.Port,
+ Tcb->RemoteEnd.Ip.v4.Addr,
+ sizeof (IPv4_ADDRESS),
+ Tcb->RemoteEnd.Port,
+ &Isn
+ );
} else {
Tcb->HeadSum = NetIp6PseudoHeadChecksum (
&Tcb->LocalEnd.Ip.v6,
@@ -64,9 +107,25 @@ TcpInitTcbLocal (
0x06,
0
);
+
+ Status = TcpGetIsn (
+ Tcb->LocalEnd.Ip.v6.Addr,
+ sizeof (IPv6_ADDRESS),
+ Tcb->LocalEnd.Port,
+ Tcb->RemoteEnd.Ip.v6.Addr,
+ sizeof (IPv6_ADDRESS),
+ Tcb->RemoteEnd.Port,
+ &Isn
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "TcpInitTcbLocal: failed to get isn\n"));
+ ASSERT (FALSE);
+ return Status;
}
- Tcb->Iss = TcpGetIss ();
+ Tcb->Iss = Isn;
Tcb->SndUna = Tcb->Iss;
Tcb->SndNxt = Tcb->Iss;
@@ -82,6 +141,8 @@ TcpInitTcbLocal (
Tcb->RetxmitSeqMax = 0;
Tcb->ProbeTimerOn = FALSE;
+
+ return EFI_SUCCESS;
}
/**
@@ -506,18 +567,162 @@ TcpCloneTcb (
}
/**
- Compute an ISS to be used by a new connection.
-
- @return The resulting ISS.
+ Retrieves the Initial Sequence Number (ISN) for a TCP connection identified by local
+ and remote IP addresses and ports.
+
+ This method is based on https://datatracker.ietf.org/doc/html/rfc9293#section-3.4.1
+ Where the ISN is computed as follows:
+ ISN = TimeStamp + MD5(LocalIP, LocalPort, RemoteIP, RemotePort, Secret)
+
+ Otherwise:
+ ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
+
+ "Here M is the 4 microsecond timer, and F() is a pseudorandom function (PRF) of the
+ connection's identifying parameters ("localip, localport, remoteip, remoteport")
+ and a secret key ("secretkey") (SHLD-1). F() MUST NOT be computable from the
+ outside (MUST-9), or an attacker could still guess at sequence numbers from the
+ ISN used for some other connection. The PRF could be implemented as a
+ cryptographic hash of the concatenation of the TCP connection parameters and some
+ secret data. For discussion of the selection of a specific hash algorithm and
+ management of the secret key data."
+
+ @param[in] LocalIp A pointer to the local IP address of the TCP connection.
+ @param[in] LocalIpSize The size, in bytes, of the LocalIp buffer.
+ @param[in] LocalPort The local port number of the TCP connection.
+ @param[in] RemoteIp A pointer to the remote IP address of the TCP connection.
+ @param[in] RemoteIpSize The size, in bytes, of the RemoteIp buffer.
+ @param[in] RemotePort The remote port number of the TCP connection.
+ @param[out] Isn A pointer to the variable that will receive the Initial
+ Sequence Number (ISN).
+
+ @retval EFI_SUCCESS The operation completed successfully, and the ISN was
+ retrieved.
+ @retval EFI_INVALID_PARAMETER One or more of the input parameters are invalid.
+ @retval EFI_UNSUPPORTED The operation is not supported.
**/
-TCP_SEQNO
-TcpGetIss (
- VOID
+EFI_STATUS
+TcpGetIsn (
+ IN UINT8 *LocalIp,
+ IN UINTN LocalIpSize,
+ IN UINT16 LocalPort,
+ IN UINT8 *RemoteIp,
+ IN UINTN RemoteIpSize,
+ IN UINT16 RemotePort,
+ OUT TCP_SEQNO *Isn
)
{
- mTcpGlobalIss += TCP_ISS_INCREMENT_1;
- return mTcpGlobalIss;
+ EFI_STATUS Status;
+ EFI_HASH2_PROTOCOL *Hash2Protocol;
+ EFI_HASH2_OUTPUT HashResult;
+ ISN_HASH_CTX IsnHashCtx;
+ EFI_TIME TimeStamp;
+
+ //
+ // Check that the ISN pointer is valid
+ //
+ if (Isn == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The local ip may be a v4 or v6 address and may not be NULL
+ //
+ if ((LocalIp == NULL) || (LocalIpSize == 0) || (RemoteIp == NULL) || (RemoteIpSize == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // the local ip may be a v4 or v6 address
+ //
+ if ((LocalIpSize != sizeof (EFI_IPv4_ADDRESS)) && (LocalIpSize != sizeof (EFI_IPv6_ADDRESS))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Locate the Hash Protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2Protocol);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_NET, "Failed to locate Hash Protocol: %r\n", Status));
+
+ //
+ // TcpCreateService(..) is expected to be called prior to this function
+ //
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Initialize the hash algorithm
+ //
+ Status = Hash2Protocol->HashInit (Hash2Protocol, &gEfiHashAlgorithmSha256Guid);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_NET, "Failed to initialize sha256 hash algorithm: %r\n", Status));
+ return Status;
+ }
+
+ IsnHashCtx.LocalPort = LocalPort;
+ IsnHashCtx.RemotePort = RemotePort;
+ IsnHashCtx.Secret = mTcpGlobalSecret;
+
+ //
+ // Check the IP address family and copy accordingly
+ //
+ if (LocalIpSize == sizeof (EFI_IPv4_ADDRESS)) {
+ CopyMem (&IsnHashCtx.LocalAddress.IPv4, LocalIp, LocalIpSize);
+ } else if (LocalIpSize == sizeof (EFI_IPv6_ADDRESS)) {
+ CopyMem (&IsnHashCtx.LocalAddress.IPv6, LocalIp, LocalIpSize);
+ } else {
+ return EFI_INVALID_PARAMETER; // Unsupported address size
+ }
+
+ //
+ // Repeat the process for the remote IP address
+ //
+ if (RemoteIpSize == sizeof (EFI_IPv4_ADDRESS)) {
+ CopyMem (&IsnHashCtx.RemoteAddress.IPv4, RemoteIp, RemoteIpSize);
+ } else if (RemoteIpSize == sizeof (EFI_IPv6_ADDRESS)) {
+ CopyMem (&IsnHashCtx.RemoteAddress.IPv6, RemoteIp, RemoteIpSize);
+ } else {
+ return EFI_INVALID_PARAMETER; // Unsupported address size
+ }
+
+ //
+ // Compute the hash
+ // Update the hash with the data
+ //
+ Status = Hash2Protocol->HashUpdate (Hash2Protocol, (UINT8 *)&IsnHashCtx, sizeof (IsnHashCtx));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_NET, "Failed to update hash: %r\n", Status));
+ return Status;
+ }
+
+ //
+ // Finalize the hash and retrieve the result
+ //
+ Status = Hash2Protocol->HashFinal (Hash2Protocol, &HashResult);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_NET, "Failed to finalize hash: %r\n", Status));
+ return Status;
+ }
+
+ Status = gRT->GetTime (&TimeStamp, NULL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // copy the first 4 bytes of the hash result into the ISN
+ //
+ CopyMem (Isn, HashResult.Md5Hash, sizeof (*Isn));
+
+ //
+ // now add the timestamp to the ISN as 4 microseconds units (1000 / 4 = 250)
+ //
+ *Isn += (TCP_SEQNO)TimeStamp.Nanosecond * 250;
+
+ return Status;
}
/**
@@ -721,17 +926,28 @@ TcpFormatNetbuf (
@param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
connection.
+ @retval EFI_SUCCESS The operation completed successfully
+ @retval others The underlying functions failed and could not complete the operation
+
**/
-VOID
+EFI_STATUS
TcpOnAppConnect (
IN OUT TCP_CB *Tcb
)
{
- TcpInitTcbLocal (Tcb);
+ EFI_STATUS Status;
+
+ Status = TcpInitTcbLocal (Tcb);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
TcpSetState (Tcb, TCP_SYN_SENT);
TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);
TcpToSendData (Tcb, 1);
+
+ return EFI_SUCCESS;
}
/**
diff --git a/NetworkPkg/TcpDxe/TcpTimer.c b/NetworkPkg/TcpDxe/TcpTimer.c
index 5d2e124..f45d4fb 100644
--- a/NetworkPkg/TcpDxe/TcpTimer.c
+++ b/NetworkPkg/TcpDxe/TcpTimer.c
@@ -2,7 +2,7 @@
TCP timer related functions.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -483,7 +483,6 @@ TcpTickingDpc (
INT16 Index;
mTcpTick++;
- mTcpGlobalIss += TCP_ISS_INCREMENT_2;
//
// Don't use LIST_FOR_EACH, which isn't delete safe.
--
2.33.0

View File

@ -0,0 +1,137 @@
From 4fd49b9dd37821a12c480234cdef0217a31baae2 Mon Sep 17 00:00:00 2001
From: Xin Jiang <jiangxin@hygon.cn>
Date: Thu, 11 Apr 2024 12:02:21 +0800
Subject: [PATCH 01/11] MdePkg: Add StandardSignatureIsHygonGenuine() in
BaseCpuLib
This function allows IA32/X64 code to determine if it is running on an
Hygon brand processor.
Signed-off-by: Xin Jiang <jiangxin@hygon.cn>
---
MdePkg/Include/Library/CpuLib.h | 11 ++++++
MdePkg/Include/Register/Hygon/Cpuid.h | 47 +++++++++++++++++++++++
MdePkg/Library/BaseCpuLib/X86BaseCpuLib.c | 24 ++++++++++++
3 files changed, 82 insertions(+)
create mode 100644 MdePkg/Include/Register/Hygon/Cpuid.h
diff --git a/MdePkg/Include/Library/CpuLib.h b/MdePkg/Include/Library/CpuLib.h
index 3f29937d..220e4e8e 100644
--- a/MdePkg/Include/Library/CpuLib.h
+++ b/MdePkg/Include/Library/CpuLib.h
@@ -67,6 +67,17 @@ StandardSignatureIsAuthenticAMD (
VOID
);
+/**
+ Determine if the standard CPU signature is "HygonGenuine".
+ @retval TRUE The CPU signature matches.
+ @retval FALSE The CPU signature does not match.
+**/
+BOOLEAN
+EFIAPI
+StandardSignatureIsHygonGenuine (
+ VOID
+ );
+
/**
Return the 32bit CPU family and model value.
@return CPUID[01h].EAX with Processor Type and Stepping ID cleared.
diff --git a/MdePkg/Include/Register/Hygon/Cpuid.h b/MdePkg/Include/Register/Hygon/Cpuid.h
new file mode 100644
index 00000000..e8a2c76b
--- /dev/null
+++ b/MdePkg/Include/Register/Hygon/Cpuid.h
@@ -0,0 +1,47 @@
+/** @file
+ CPUID leaf definitions.
+
+ Provides defines for CPUID leaf indexes. Data structures are provided for
+ registers returned by a CPUID leaf that contain one or more bit fields.
+ If a register returned is a single 32-bit value, then a data structure is
+ not provided for that register.
+
+ Copyright (c) 2022, HYGON. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __HYGON_CPUID_H__
+#define __HYGON_CPUID_H__
+
+/**
+CPUID Signature Information
+
+@param EAX CPUID_SIGNATURE (0x00)
+
+@retval EAX Returns the highest value the CPUID instruction recognizes for
+ returning basic processor information. The value is returned is
+ processor specific.
+@retval EBX First 4 characters of a vendor identification string.
+@retval ECX Last 4 characters of a vendor identification string.
+@retval EDX Middle 4 characters of a vendor identification string.
+
+**/
+
+///
+/// @{ CPUID signature values returned by HYGON processors
+///
+#define CPUID_SIGNATURE_AUTHENTIC_HYGON_EBX SIGNATURE_32 ('H', 'y', 'g', 'o')
+#define CPUID_SIGNATURE_AUTHENTIC_HYGON_EDX SIGNATURE_32 ('n', 'G', 'e', 'n')
+#define CPUID_SIGNATURE_AUTHENTIC_HYGON_ECX SIGNATURE_32 ('u', 'i', 'n', 'e')
+///
+/// @}
+///
+
+#endif
diff --git a/MdePkg/Library/BaseCpuLib/X86BaseCpuLib.c b/MdePkg/Library/BaseCpuLib/X86BaseCpuLib.c
index 1cad32a4..6d7ceb11 100644
--- a/MdePkg/Library/BaseCpuLib/X86BaseCpuLib.c
+++ b/MdePkg/Library/BaseCpuLib/X86BaseCpuLib.c
@@ -11,6 +11,7 @@
#include <Register/Intel/Cpuid.h>
#include <Register/Amd/Cpuid.h>
+#include <Register/Hygon/Cpuid.h>
#include <Library/BaseLib.h>
#include <Library/CpuLib.h>
@@ -38,6 +39,29 @@ StandardSignatureIsAuthenticAMD (
RegEdx == CPUID_SIGNATURE_AUTHENTIC_AMD_EDX);
}
+/**
+ Determine if the standard CPU signature is "HygonGenuine".
+
+ @retval TRUE The CPU signature matches.
+ @retval FALSE The CPU signature does not match.
+
+**/
+BOOLEAN
+EFIAPI
+StandardSignatureIsHygonGenuine (
+ VOID
+ )
+{
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+
+ AsmCpuid (CPUID_SIGNATURE, NULL, &RegEbx, &RegEcx, &RegEdx);
+ return (RegEbx == CPUID_SIGNATURE_AUTHENTIC_HYGON_EBX &&
+ RegEcx == CPUID_SIGNATURE_AUTHENTIC_HYGON_ECX &&
+ RegEdx == CPUID_SIGNATURE_AUTHENTIC_HYGON_EDX);
+}
+
/**
Return the 32bit CPU family and model value.
--
2.43.0

View File

@ -0,0 +1,82 @@
From ee70f4f384975e7f0fa97aacbd72c8431f441eb9 Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
Date: Sun, 10 Apr 2022 21:50:15 -0400
Subject: [PATCH 02/11] UefiCpuPkg/LocalApicLib: Exclude second SendIpi
sequence on HYGON hardware
On HYGON processors the second SendIpi in the SendInitSipiSipi and
SendInitSipiSipiAllExcludingSelf routines is not required, and may cause
undesired side-effects during MP initialization.
This patch leverages the StandardSignatureIsHygonGenuine check to exclude
the second SendIpi and its associated MicroSecondDelay (200).
Signed-off-by: Xin Jiang <jiangxin@hygon.cn>
---
UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c | 5 +++--
UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c | 5 +++--
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
index d56c6275..6c035ee3 100644
--- a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
+++ b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
@@ -22,6 +22,7 @@
#include <Library/TimerLib.h>
#include <Library/PcdLib.h>
#include <Library/CpuLib.h>
+#include <Register/Hygon/Cpuid.h>
//
// Library internal functions
@@ -555,7 +556,7 @@ SendInitSipiSipi (
IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;
IcrLow.Bits.Level = 1;
SendIpi (IcrLow.Uint32, ApicId);
- if (!StandardSignatureIsAuthenticAMD ()) {
+ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) {
MicroSecondDelay (200);
SendIpi (IcrLow.Uint32, ApicId);
}
@@ -581,7 +582,7 @@ SendInitSipiSipiAllExcludingSelf (
SendInitIpiAllExcludingSelf ();
MicroSecondDelay (PcdGet32 (PcdCpuInitIpiDelayInMicroSeconds));
SendStartupIpiAllExcludingSelf (StartupRoutine);
- if (!StandardSignatureIsAuthenticAMD ()) {
+ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) {
MicroSecondDelay (200);
SendStartupIpiAllExcludingSelf (StartupRoutine);
}
diff --git a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
index aa4eb111..2fa614cd 100644
--- a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
+++ b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
@@ -24,6 +24,7 @@
#include <Library/PcdLib.h>
#include <Library/CpuLib.h>
#include <IndustryStandard/Tdx.h>
+#include <Register/Hygon/Cpuid.h>
//
// Library internal functions
@@ -794,7 +795,7 @@ SendInitSipiSipi (
IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;
IcrLow.Bits.Level = 1;
SendIpi (IcrLow.Uint32, ApicId);
- if (!StandardSignatureIsAuthenticAMD ()) {
+ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) {
MicroSecondDelay (200);
SendIpi (IcrLow.Uint32, ApicId);
}
@@ -820,7 +821,7 @@ SendInitSipiSipiAllExcludingSelf (
SendInitIpiAllExcludingSelf ();
MicroSecondDelay (PcdGet32 (PcdCpuInitIpiDelayInMicroSeconds));
SendStartupIpiAllExcludingSelf (StartupRoutine);
- if (!StandardSignatureIsAuthenticAMD ()) {
+ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) {
MicroSecondDelay (200);
SendStartupIpiAllExcludingSelf (StartupRoutine);
}
--
2.43.0

View File

@ -0,0 +1,706 @@
From 2b2a93b70ee396bb7932e78fa80f0f3697888cdb Mon Sep 17 00:00:00 2001
From: Liu Zixing <liuzixing@hygon.cn>
Date: Fri, 25 Feb 2022 14:25:11 +0800
Subject: [PATCH 03/11] OvmfPkg: Add CSV secure call library on Hygon CPU
CSV is the secure virtualization feature on Hygon CPU.
A CSV virtual machine is composed of private memory and shared memory.
The private memory or shared memory can be converted to the other by
the following steps:
- guest clear/set the c-bit in the guest page table
- guest send a update command to Hygon Secure Processor
While the update command has to be forwarded by the VMM to the Secure
Processor, to prevent the malicious VMM from attacking the update
command, a reliable command channel is required between the CSV VM
and the Hygon Secure Processor.
The secure call library is created to build a secure command channel
between the VM and the Secure Processor by #NPF on a special private
page which the VMM is not able to access.
This special page is called secure call page.
The VM puts command in the secure call page and triggers a #NPF
to reach the Secure Processor.
The Secure Processor then puts the response in the same page and
finishes the #NPF.
The information is protected in the secure call page all the way.
CsvLib is added to implement the functionality and new PCDs are added
accordingly.
Signed-off-by: Xin Jiang <jiangxin@hygon.cn>
---
OvmfPkg/AmdSev/AmdSevX64.dsc | 1 +
OvmfPkg/AmdSev/AmdSevX64.fdf | 5 +-
OvmfPkg/Include/Library/CsvLib.h | 84 +++++++
OvmfPkg/Library/CsvLib/CsvLib.c | 85 +++++++
OvmfPkg/Library/CsvLib/CsvLib.inf | 54 ++++
.../Library/CsvLib/Ia32/UpdateMemoryCsvLib.c | 53 ++++
.../Library/CsvLib/X64/UpdateMemoryCsvLib.c | 238 ++++++++++++++++++
OvmfPkg/OvmfPkg.dec | 8 +
OvmfPkg/OvmfPkgIa32.dsc | 2 +
OvmfPkg/OvmfPkgIa32X64.dsc | 2 +
OvmfPkg/OvmfPkgX64.dsc | 1 +
OvmfPkg/OvmfPkgX64.fdf | 5 +-
12 files changed, 536 insertions(+), 2 deletions(-)
create mode 100644 OvmfPkg/Include/Library/CsvLib.h
create mode 100644 OvmfPkg/Library/CsvLib/CsvLib.c
create mode 100644 OvmfPkg/Library/CsvLib/CsvLib.inf
create mode 100644 OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c
create mode 100644 OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c
diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc
index 2c6ed7c9..c70edd36 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.dsc
+++ b/OvmfPkg/AmdSev/AmdSevX64.dsc
@@ -171,6 +171,7 @@
MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf
!if $(SOURCE_DEBUG_ENABLE) == TRUE
PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf
index 463bd3e9..7afa73aa 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.fdf
+++ b/OvmfPkg/AmdSev/AmdSevX64.fdf
@@ -74,7 +74,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase|gUefiOvmfPkgTokenSpaceGuid.PcdO
0x00F000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize
-0x010000|0x010000
+0x010000|0x002000
+gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize
+
+0x012000|0x00E000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
diff --git a/OvmfPkg/Include/Library/CsvLib.h b/OvmfPkg/Include/Library/CsvLib.h
new file mode 100644
index 00000000..ceeab7dc
--- /dev/null
+++ b/OvmfPkg/Include/Library/CsvLib.h
@@ -0,0 +1,84 @@
+/** @file
+
+ CSV base library helper function
+
+ Copyright (c) 2022, HYGON. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CSV_LIB_H_
+#define _CSV_LIB_H_
+
+#include <Base.h>
+
+typedef struct {
+ IN UINT64 BaseAddress;
+ IN UINT64 Size;
+} CSV_SECURE_CMD_SHARED_REGION;
+
+typedef enum {
+ CsvSecureCmdEnc = 1,
+ CsvSecureCmdDec,
+ CsvSecureCmdReset,
+ CsvSecureCmdUpdateSecureCallTable,
+ CsvSecureCmdMapLowerMemory, //secure memory range below 4G
+ CsvSecureCmdMapUpperMemory //secure memory range above 4G
+} CSV_SECURE_COMMAND_TYPE;
+
+/**
+ Returns a boolean to indicate whether CSV is enabled
+
+ @retval TRUE CSV is enabled
+ @retval FALSE CSV is not enabled
+**/
+BOOLEAN
+EFIAPI
+CsvIsEnabled (
+ VOID
+ );
+
+#define CSV_SHARED_MEMORY_SIGNATURE SIGNATURE_32('C','S','V',' ')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ UINT64 Start;
+ UINT64 Length;
+} CsvSharedMemoryEntry;
+
+VOID
+EFIAPI
+CsvUpdateMemory (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages,
+ IN BOOLEAN Dec
+);
+
+VOID
+EFIAPI
+CsvResetMemory (
+ VOID
+);
+
+VOID
+EFIAPI
+CsvUpdateMapLowerMemory (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages
+);
+
+VOID
+EFIAPI
+CsvUpdateMapUpperMemory (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages
+);
+#endif // _CSV_LIB_H_
diff --git a/OvmfPkg/Library/CsvLib/CsvLib.c b/OvmfPkg/Library/CsvLib/CsvLib.c
new file mode 100644
index 00000000..332e8ee6
--- /dev/null
+++ b/OvmfPkg/Library/CsvLib/CsvLib.c
@@ -0,0 +1,85 @@
+/** @file
+
+ CSV library helper function
+
+ Copyright (c) 2022, HYGON. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/CsvLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Register/Cpuid.h>
+#include <Register/Amd/Cpuid.h>
+#include <Register/Hygon/Cpuid.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/CpuLib.h>
+#include <Register/Amd/Fam17Msr.h>
+
+STATIC BOOLEAN mCsvStatus = FALSE;
+STATIC BOOLEAN mCsvStatusChecked = FALSE;
+
+/**
+
+ Reads and sets the status of CSV features
+ **/
+STATIC
+VOID
+EFIAPI
+InternalCsvStatus (
+ VOID
+ )
+{
+ UINT32 RegEax;
+
+ //
+ // Check if memory encryption leaf exist
+ //
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= CPUID_MEMORY_ENCRYPTION_INFO) {
+ if(StandardSignatureIsHygonGenuine ()){
+ //
+ // Check MSR_0xC0010131 Bit 30 (Csv Enabled)
+ //
+ MSR_SEV_STATUS_REGISTER Msr;
+ Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);
+ if (Msr.Uint32 & (1 << 30)) {
+ mCsvStatus = TRUE;
+ DEBUG ((EFI_D_INFO, "CSV is enabled\n"));
+ }
+ }
+ }
+ mCsvStatusChecked = TRUE;
+}
+
+/**
+ Returns a boolean to indicate whether CSV is enabled
+
+ @retval TRUE CSV is enabled
+ @retval FALSE CSV is not enabled
+**/
+BOOLEAN
+EFIAPI
+CsvIsEnabled (
+ VOID
+ )
+{
+ if (!MemEncryptSevEsIsEnabled ())
+ return FALSE;
+
+ if (!mCsvStatusChecked) {
+ InternalCsvStatus ();
+ }
+
+ return mCsvStatus;
+}
diff --git a/OvmfPkg/Library/CsvLib/CsvLib.inf b/OvmfPkg/Library/CsvLib/CsvLib.inf
new file mode 100644
index 00000000..57efbe70
--- /dev/null
+++ b/OvmfPkg/Library/CsvLib/CsvLib.inf
@@ -0,0 +1,54 @@
+## @file
+# Library provides the helper functions for CSV guest
+#
+# Copyright (c) 2022 HYGON. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD
+# License which accompanies this distribution. The full text of the license
+# may be found at http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 1.25
+ BASE_NAME = CsvLib
+ FILE_GUID = 9460ef3a-b9c3-11e9-8324-7371ac35e1e3
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CsvLib|PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build
+# tools.
+#
+# VALID_ARCHITECTURES = Ia32 X64
+#
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[Sources]
+ CsvLib.c
+
+[Sources.X64]
+ X64/UpdateMemoryCsvLib.c
+[Sources.IA32]
+ Ia32/UpdateMemoryCsvLib.c
+
+[LibraryClasses]
+ BaseLib
+ CpuLib
+ DebugLib
+ MemEncryptSevLib
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize
diff --git a/OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c b/OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c
new file mode 100644
index 00000000..15d3aa89
--- /dev/null
+++ b/OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c
@@ -0,0 +1,53 @@
+/** @file
+
+ CSV library helper function
+
+ Copyright (c) 2022, HYGON. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/CsvLib.h>
+
+VOID
+EFIAPI
+CsvUpdateMemory (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages,
+ IN BOOLEAN Dec
+)
+{
+}
+
+VOID
+EFIAPI
+CsvResetMemory (
+ VOID
+)
+{
+}
+
+VOID
+EFIAPI
+CsvUpdateMapLowerMemory (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages
+)
+{
+}
+
+VOID
+EFIAPI
+CsvUpdateMapUpperMemory (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages
+)
+{
+}
diff --git a/OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c b/OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c
new file mode 100644
index 00000000..13d06d7c
--- /dev/null
+++ b/OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c
@@ -0,0 +1,238 @@
+/** @file
+
+ CSV library helper function
+
+ Copyright (c) 2022, HYGON. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/CsvLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+
+#define SECURE_CALL_ENTRY_MAX (254)
+
+
+typedef struct {
+ union {
+ UINT8 Guid[16];
+ UINT64 Guid64[2];
+ };
+ UINT32 CmdType;
+ UINT32 Nums;
+ UINT64 Unused;
+ struct {
+ UINT64 BaseAddress;
+ UINT64 Size;
+ } Entry[SECURE_CALL_ENTRY_MAX];
+} CSV_SECURE_CALL_CMD;
+
+STATIC UINT32 SecureCallPageIdx = 0;
+
+STATIC UINTN MemorySizeBelow4G = (UINTN)-1;
+STATIC UINTN MemorySizeAbove4G = (UINTN)-1;
+
+STATIC
+VOID
+EFIAPI
+CsvSecureCall(
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages,
+ IN CSV_SECURE_COMMAND_TYPE CmdType
+)
+{
+ volatile CSV_SECURE_COMMAND_TYPE CmdAck = 0;
+
+ CSV_SECURE_CALL_CMD *SecureCallPageRead;
+ CSV_SECURE_CALL_CMD *SecureCallPageWrite;
+ UINTN SecureCallBase = 0;
+
+ if (CsvIsEnabled () == FALSE) {
+ return ;
+ }
+
+ SecureCallBase = FixedPcdGet32 (PcdCsvDefaultSecureCallBase);
+
+ SecureCallPageRead =
+ (CSV_SECURE_CALL_CMD *)(UINT64)
+ (EFI_PAGE_SIZE * SecureCallPageIdx + SecureCallBase);
+
+ SecureCallPageWrite =
+ (CSV_SECURE_CALL_CMD *)
+ (UINT64)(EFI_PAGE_SIZE * (1 - SecureCallPageIdx) + SecureCallBase);
+
+ while(1) {
+ SecureCallPageWrite->CmdType = (UINT32)CmdType;
+ SecureCallPageWrite->Nums = 1;
+ SecureCallPageWrite->Entry[0].BaseAddress = (UINT64)BaseAddress;
+ SecureCallPageWrite->Entry[0].Size = (UINT64)NumPages << EFI_PAGE_SHIFT;
+
+ MemoryFence ();
+
+ CmdAck = SecureCallPageRead->CmdType;
+ if (CmdAck != CmdType)
+ break;
+ }
+ SecureCallPageIdx = 1 - SecureCallPageIdx;
+}
+
+STATIC
+UINT8
+CmosRead8 (
+ IN UINTN Index
+ )
+{
+ IoWrite8 (0x70, (UINT8) Index);
+ return IoRead8 (0x71);
+}
+
+
+STATIC
+VOID
+EFIAPI
+CsvGetSystemMemory(
+ VOID
+ )
+{
+ UINT8 Cmos0x34;
+ UINT8 Cmos0x35;
+ UINT32 Size;
+ UINTN CmosIndex;
+
+ //
+ // system memory below 4GB MB
+ //
+
+ Cmos0x34 = (UINT8) CmosRead8 (0x34);
+ Cmos0x35 = (UINT8) CmosRead8 (0x35);
+
+ MemorySizeBelow4G =
+ (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);
+
+ //
+ // system memory above 4GB MB
+ //
+
+ Size = 0;
+ for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {
+ Size = (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex);
+ }
+
+ MemorySizeAbove4G = LShiftU64 (Size, 16);
+}
+
+STATIC
+BOOLEAN
+EFIAPI
+CsvIsDRAM(
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages
+ )
+{
+ UINTN Size = EFI_PAGES_TO_SIZE (NumPages);
+ PHYSICAL_ADDRESS EndAddress;
+
+ Size = EFI_PAGES_TO_SIZE (NumPages);
+ EndAddress = BaseAddress + Size;
+
+ if (MemorySizeBelow4G == (UINTN)-1 ||
+ MemorySizeAbove4G == (UINTN)-1) {
+ CsvGetSystemMemory ();
+ }
+
+ if (BaseAddress < MemorySizeBelow4G) {
+ return TRUE;
+ } else if (BaseAddress >= BASE_4GB &&
+ BaseAddress < (BASE_4GB + MemorySizeAbove4G)) {
+ return TRUE;
+ } else if (EndAddress > BASE_4GB &&
+ EndAddress <= (BASE_4GB + MemorySizeAbove4G)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+STATIC
+VOID
+EFIAPI
+CsvUpdateEncryptMemory (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages
+)
+{
+ PHYSICAL_ADDRESS PageAddress = BaseAddress & ~EFI_PAGE_MASK;
+
+ if (CsvIsDRAM (PageAddress, NumPages)) {
+ CsvSecureCall (PageAddress, NumPages, CsvSecureCmdEnc);
+ }
+}
+
+STATIC
+VOID
+EFIAPI
+CsvUpdateDecryptMemory (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages
+)
+{
+ PHYSICAL_ADDRESS PageAddress = BaseAddress & ~EFI_PAGE_MASK;
+
+ if (CsvIsDRAM (PageAddress, NumPages)) {
+ CsvSecureCall (PageAddress, NumPages, CsvSecureCmdDec);
+ }
+}
+
+VOID
+EFIAPI
+CsvUpdateMemory (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages,
+ IN BOOLEAN Dec
+ )
+{
+ if (Dec)
+ CsvUpdateDecryptMemory (BaseAddress, NumPages);
+ else
+ CsvUpdateEncryptMemory (BaseAddress, NumPages);
+}
+
+VOID
+EFIAPI
+CsvResetMemory (
+ VOID
+)
+{
+ CsvSecureCall (0, 0, CsvSecureCmdReset);
+}
+
+VOID
+EFIAPI
+CsvUpdateMapLowerMemory (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages
+)
+{
+ CsvSecureCall (BaseAddress, NumPages, CsvSecureCmdMapLowerMemory);
+}
+
+VOID
+EFIAPI
+CsvUpdateMapUpperMemory (
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages
+)
+{
+ CsvSecureCall (BaseAddress, NumPages, CsvSecureCmdMapUpperMemory);
+}
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index e3861e5c..f19a356f 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -145,6 +145,10 @@
#
HardwareInfoLib|Include/Library/HardwareInfoLib.h
+ ## @libraryclass CSV Library
+ #
+ CsvLib|Include/Library/CsvLib.h
+
[Guids]
gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}
gEfiXenInfoGuid = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}}
@@ -429,6 +433,10 @@
## Restrict boot to EFI applications in firmware volumes.
gUefiOvmfPkgTokenSpaceGuid.PcdBootRestrictToFirmware|FALSE|BOOLEAN|0x6c
+ ## the base address of the secure call pages used by CSV.
+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|0|UINT32|0x70
+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize|0|UINT32|0x71
+
[PcdsDynamic, PcdsDynamicEx]
gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 80d8e370..6e561690 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -187,6 +187,8 @@
MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLibNull.inf
PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf
+
!if $(SMM_REQUIRE) == FALSE
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
!endif
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index d9757149..80849705 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -192,6 +192,8 @@
MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLibNull.inf
PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf
+
!if $(SMM_REQUIRE) == FALSE
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
!endif
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index b12d874d..7b276916 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -204,6 +204,7 @@
MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf
!if $(SMM_REQUIRE) == FALSE
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 41912fc1..41fdb8b8 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -94,7 +94,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase|gUefiOvmfPkgTokenSpaceGuid.PcdO
0x00E000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidSize
-0x010000|0x010000
+0x00F000|0x002000
+gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize
+
+0x011000|0x00F000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
--
2.43.0

View File

@ -0,0 +1,219 @@
From 1cfbda43138702311663a81e1cc5679d3df72ae3 Mon Sep 17 00:00:00 2001
From: Liu Zixing <liuzixing@hygon.cn>
Date: Fri, 25 Feb 2022 15:55:44 +0800
Subject: [PATCH 04/11] OvmfPkg/ResetVector: Support CSV in ResetVector phase
- A GUID is written along with the first secure call page address,
by which the Secure Processor can locate the first secure call page
address.
- Check whether the VM is a CSV VM when setting the first page table
- CSV VM will update first shared GHCB page address to Secure Processor
by secure call page
Signed-off-by: Xin Jiang <jiangxin@hygon.cn>
---
OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 15 +++
OvmfPkg/ResetVector/Ia32/AmdSev.asm | 9 ++
OvmfPkg/ResetVector/Ia32/CsvInit.asm | 107 +++++++++++++++++++
OvmfPkg/ResetVector/ResetVector.inf | 2 +
OvmfPkg/ResetVector/ResetVector.nasmb | 4 +
5 files changed, 137 insertions(+)
create mode 100644 OvmfPkg/ResetVector/Ia32/CsvInit.asm
diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
index 12f2cedd..c86b0499 100644
--- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
+++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
@@ -48,6 +48,21 @@ TIMES (15 - ((guidedStructureEnd - guidedStructureStart + 15) % 16)) DB 0
guidedStructureStart:
%ifdef ARCH_X64
+;
+; CSV secure call table
+;
+; Provide secure call pages when boot up for CSV guest.
+;
+; GUID : 9a5d926f-2fa5-ceba-ab21-6b275d5556a5
+;
+csvSecureCallBase:
+ DD CSV_DEFAULT_SECURE_CALL_SIZE
+ DD CSV_DEFAULT_SECURE_CALL_BASE
+ DW csvSecureCallEnd - csvSecureCallBase
+ DB 0x6F, 0x92, 0x5D, 0x9A, 0xA5, 0x2F, 0xBA, 0xCE
+ DB 0xAB, 0x21, 0x6B, 0x27, 0x5D, 0x55, 0x56, 0xA5
+csvSecureCallEnd:
+
;
; TDX Metadata offset block
;
diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
index 3abc8300..8f6de37c 100644
--- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm
+++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
@@ -192,6 +192,15 @@ pageTableEntries4kLoop:
mov ecx, (GHCB_BASE & 0x1F_FFFF) >> 12
mov [ecx * 8 + GHCB_PT_ADDR + 4], strict dword 0
+ OneTimeCall CheckCsvFeature
+ test eax, eax
+ jz SevClearPageEncMaskForGhcbPageExit
+
+ OneTimeCall CsvInit
+ mov eax, 1
+ test ecx, ecx
+ jz SevEsUnexpectedRespTerminate
+
SevClearPageEncMaskForGhcbPageExit:
OneTimeCallRet SevClearPageEncMaskForGhcbPage
diff --git a/OvmfPkg/ResetVector/Ia32/CsvInit.asm b/OvmfPkg/ResetVector/Ia32/CsvInit.asm
new file mode 100644
index 00000000..0744a35e
--- /dev/null
+++ b/OvmfPkg/ResetVector/Ia32/CsvInit.asm
@@ -0,0 +1,107 @@
+;------------------------------------------------------------------------------
+; @file
+; Provide the functions to check whether CSV is enabled.
+;
+; Copyright (c) 2022, HYGON. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS 32
+
+; If Secure Command returns ok then ECX will be non-zero.
+; If Secure Command returns error then ECX will be zero.
+CsvInit:
+ mov esp, SEV_ES_VC_TOP_OF_STACK
+ push esi
+ push edi
+
+ ; copy SECURE_CALL_GUID to CSV_DEFAULT_SECURE_CALL_BASE + 4096
+ cld
+ mov esi, ADDR_OF(SECURE_CALL_GUID)
+ mov edi, CSV_DEFAULT_SECURE_CALL_BASE
+ add edi, 4096
+ mov ecx, 4
+ rep movsd
+
+ ; secure call begin
+ mov esi, CSV_DEFAULT_SECURE_CALL_BASE
+ ; write secure cmd to page B
+ ; 16 bytes of page A/B is GUID, just ignore
+ mov [esi + 4096 + 16], DWORD 2 ; dec command
+ mov [esi + 4096 + 20], DWORD 1 ; 1 entry
+ ; 8 bytes is unused
+ mov [esi + 4096 + 32], DWORD GHCB_BASE; lower address
+ mov [esi + 4096 + 36], DWORD 0 ; upper address
+ mov [esi + 4096 + 40], DWORD 4096 ; lower 32 bit of page size
+ mov [esi + 4096 + 44], DWORD 0 ; upper 32 bit of page size
+ mfence
+ ; read from page A
+ mov ecx, [esi + 16]
+ ; check if the response comes
+ cmp ecx, 2
+ jne SecureCommandDone
+ ; no secure command response, clean ecx
+ xor ecx, ecx
+ ; secure call end
+
+SecureCommandDone:
+ pop edi
+ pop esi
+ mov esp, 0
+
+ OneTimeCallRet CsvInit
+
+; Check if CSV feature is enabled.
+;
+; Modified: EAX, EBX, ECX, EDX
+;
+; If CSV is enabled then EAX will be non-zero.
+; If CSV is disabled then EAX will be zero.
+;
+CheckCsvFeature:
+ mov esp, SEV_ES_VC_TOP_OF_STACK
+ mov eax, ADDR_OF(Idtr)
+ lidt [cs:eax]
+
+ ; Check if vendor Hygon CPUID_SIGNATURE(0x0)
+ ; CPUID raises a #VC exception if running as an SEV-ES guest
+ mov eax, 0
+ cpuid
+
+ cmp ebx, 0x6f677948
+ jne NoCsv
+ cmp ecx, 0x656e6975
+ jne NoCsv
+ cmp edx, 0x6e65476e
+ jne NoCsv
+
+ ; Check if CSV is enabled
+ ; MSR_0xC0010131 - Bit 30 (CSV enabled)
+ mov ecx, 0xc0010131
+ rdmsr
+ and eax, 0x40000000
+ jmp CsvExit
+
+NoCsv:
+ xor eax, eax
+
+CsvExit:
+ ;
+ ; Clear exception handlers and stack
+ ;
+ push eax
+ mov eax, ADDR_OF(IdtrClear)
+ lidt [cs:eax]
+ pop eax
+ mov esp, 0
+
+ OneTimeCallRet CheckCsvFeature
+
+SECURE_CALL_GUID:
+; low 0xceba2fa59a5d926f
+; high 0xa556555d276b21ab
+ dd 0x9a5d926f
+ dd 0xceba2fa5
+ dd 0x276b21ab
+ dd 0xa556555d
diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf
index a4154ca9..e4adedb8 100644
--- a/OvmfPkg/ResetVector/ResetVector.inf
+++ b/OvmfPkg/ResetVector/ResetVector.inf
@@ -35,6 +35,8 @@
[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
index 94fbb0a8..d156a511 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -123,11 +123,15 @@
%define TDX_WORK_AREA_PGTBL_READY (FixedPcdGet32 (PcdOvmfWorkAreaBase) + 4)
%define TDX_WORK_AREA_GPAW (FixedPcdGet32 (PcdOvmfWorkAreaBase) + 8)
+ %define CSV_DEFAULT_SECURE_CALL_BASE FixedPcdGet32 (PcdCsvDefaultSecureCallBase)
+ %define CSV_DEFAULT_SECURE_CALL_SIZE FixedPcdGet32 (PcdCsvDefaultSecureCallSize)
+
%include "X64/IntelTdxMetadata.asm"
%include "Ia32/Flat32ToFlat64.asm"
%include "Ia32/PageTables64.asm"
%include "Ia32/IntelTdx.asm"
%include "X64/OvmfSevMetadata.asm"
+ %include "Ia32/CsvInit.asm"
%endif
%include "Ia32/AmdSev.asm"
--
2.43.0

View File

@ -0,0 +1,214 @@
From d9a779013ce911160125d13e20a395495d30c723 Mon Sep 17 00:00:00 2001
From: Liu Zixing <liuzixing@hygon.cn>
Date: Fri, 25 Feb 2022 16:12:38 +0800
Subject: [PATCH 05/11] OvmfPkg/PlatformPei: Initialize CSV VM's memory
For CSV VM, the Secure Processor builds a temporary nested
page table to help the guest to run into the PEI phase.
In PEI phase, CSV VM detects the start address and size of the
guest physical memory.
The CSV VM sends the memory information to the Secure Processor
to build the permanent nested page table.
Signed-off-by: Xin Jiang <jiangxin@hygon.cn>
---
OvmfPkg/Include/Library/PlatformInitLib.h | 5 ++
OvmfPkg/Library/PlatformInitLib/MemDetect.c | 2 +-
OvmfPkg/PlatformPei/Csv.c | 82 +++++++++++++++++++++
OvmfPkg/PlatformPei/Platform.c | 2 +
OvmfPkg/PlatformPei/Platform.h | 10 +++
OvmfPkg/PlatformPei/PlatformPei.inf | 4 +
6 files changed, 104 insertions(+), 1 deletion(-)
create mode 100644 OvmfPkg/PlatformPei/Csv.c
diff --git a/OvmfPkg/Include/Library/PlatformInitLib.h b/OvmfPkg/Include/Library/PlatformInitLib.h
index 57b18b94..6c28c7fb 100644
--- a/OvmfPkg/Include/Library/PlatformInitLib.h
+++ b/OvmfPkg/Include/Library/PlatformInitLib.h
@@ -151,6 +151,11 @@ PlatformGetSystemMemorySizeBelow4gb (
IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
);
+UINT64
+EFIAPI
+PlatformGetSystemMemorySizeAbove4gb (
+ );
+
/**
Initialize the PhysMemAddressWidth field in PlatformInfoHob based on guest RAM size.
**/
diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
index 662e7e85..3c9f01cf 100644
--- a/OvmfPkg/Library/PlatformInitLib/MemDetect.c
+++ b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
@@ -402,8 +402,8 @@ PlatformGetSystemMemorySizeBelow4gb (
PlatformInfoHob->LowMemory = (UINT32)(((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);
}
-STATIC
UINT64
+EFIAPI
PlatformGetSystemMemorySizeAbove4gb (
)
{
diff --git a/OvmfPkg/PlatformPei/Csv.c b/OvmfPkg/PlatformPei/Csv.c
new file mode 100644
index 00000000..5ab83312
--- /dev/null
+++ b/OvmfPkg/PlatformPei/Csv.c
@@ -0,0 +1,82 @@
+/** @file
+
+ CSV initialization in PEI
+
+ Copyright (c) 2022, HYGON. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/CsvLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/PlatformInitLib.h>
+
+#include "Platform.h"
+
+VOID
+CsvInitializeMemInfo (
+ IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
+ )
+{
+ UINT64 LowerMemorySize;
+ UINT64 UpperMemorySize;
+
+ if (!CsvIsEnabled ()) {
+ return ;
+ }
+
+ LowerMemorySize = PlatformInfoHob->LowMemory;
+ UpperMemorySize = PlatformGetSystemMemorySizeAbove4gb ();
+
+ CsvUpdateMapLowerMemory (
+ 0,
+ LowerMemorySize >> EFI_PAGE_SHIFT
+ );
+
+ if (UpperMemorySize > 0) {
+ CsvUpdateMapUpperMemory (
+ BASE_4GB,
+ UpperMemorySize >> EFI_PAGE_SHIFT
+ );
+ }
+
+ BuildMemoryAllocationHob (
+ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdCsvDefaultSecureCallBase),
+ (UINT64)(UINTN) FixedPcdGet32 (PcdCsvDefaultSecureCallSize),
+ EfiReservedMemoryType
+ );
+}
+
+VOID
+CsvInitializeGhcb (
+ VOID
+ )
+{
+ RETURN_STATUS EncryptStatus;
+
+ if (!CsvIsEnabled ()) {
+ return ;
+ }
+
+ //
+ // Encrypt the SecGhcb as it's not a Ghcb any more
+ //
+ EncryptStatus = MemEncryptSevSetPageEncMask(
+ 0,
+ PcdGet32 (PcdOvmfSecGhcbBase),
+ 1
+ );
+ ASSERT_RETURN_ERROR (EncryptStatus);
+}
diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c
index f5dc41c3..34d764e4 100644
--- a/OvmfPkg/PlatformPei/Platform.c
+++ b/OvmfPkg/PlatformPei/Platform.c
@@ -345,6 +345,7 @@ InitializePlatform (
PlatformQemuUc32BaseInitialization (PlatformInfoHob);
InitializeRamRegions (PlatformInfoHob);
+ CsvInitializeMemInfo (PlatformInfoHob);
if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) {
if (!PlatformInfoHob->SmmSmramRequire) {
@@ -364,6 +365,7 @@ InitializePlatform (
} else {
MiscInitialization (PlatformInfoHob);
}
+ CsvInitializeGhcb();
IntelTdxInitialize ();
InstallFeatureControlCallback (PlatformInfoHob);
diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h
index 1cf44844..1893f3fe 100644
--- a/OvmfPkg/PlatformPei/Platform.h
+++ b/OvmfPkg/PlatformPei/Platform.h
@@ -106,4 +106,14 @@ SevInitializeRam (
VOID
);
+VOID
+CsvInitializeMemInfo (
+ IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
+ );
+
+VOID
+CsvInitializeGhcb (
+ VOID
+ );
+
#endif // _PLATFORM_PEI_H_INCLUDED_
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index 3934aeed..45d16889 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -32,6 +32,7 @@
Platform.c
Platform.h
IntelTdx.c
+ Csv.c
[Packages]
EmbeddedPkg/EmbeddedPkg.dec
@@ -65,6 +66,7 @@
PcdLib
CcExitLib
PlatformInitLib
+ CsvLib
[Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
@@ -131,6 +133,8 @@
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable
--
2.43.0

View File

@ -0,0 +1,74 @@
From f462635b8603a20615d371f434bfcd561d39f367 Mon Sep 17 00:00:00 2001
From: Liu Zixing <liuzixing@hygon.cn>
Date: Sat, 26 Feb 2022 14:39:06 +0800
Subject: [PATCH 06/11] OvmfPkg/BaseMemcryptSevLib: update page status to
Secure Processor for CSV
For CSV VM, when encrypting/decrypting a shared/private memory region,
guest needs to
- set/clear the c-bit in guest page table
- the Secure Processor should be updated accordingly
The BaseMemcryptSevLib has done the first step.
Calling the secure call library for second step.
Signed-off-by: Xin Jiang <jiangxin@hygon.cn>
---
.../BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf | 1 +
.../BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 14 ++++++++++++++
2 files changed, 15 insertions(+)
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
index cc24961c..3a1d3089 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
@@ -52,6 +52,7 @@
MemoryAllocationLib
PcdLib
CcExitLib
+ CsvLib
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
index dee3fb89..a49cf125 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
@@ -19,6 +19,8 @@
#include "VirtualMemory.h"
#include "SnpPageStateChange.h"
+#include <Library/CsvLib.h>
+
STATIC BOOLEAN mAddressEncMaskChecked = FALSE;
STATIC UINT64 mAddressEncMask;
STATIC PAGE_TABLE_POOL *mPageTablePool = NULL;
@@ -727,6 +729,11 @@ SetMemoryEncDec (
BOOLEAN IsWpEnabled;
UINTN OrigLength;
RETURN_STATUS Status;
+ PHYSICAL_ADDRESS PageAddress;
+ UINTN PageNum;
+
+ PageAddress = PhysicalAddress;
+ PageNum = EFI_SIZE_TO_PAGES (Length);
//
// Set PageMapLevel4Entry to suppress incorrect compiler/analyzer warnings.
@@ -991,6 +998,13 @@ Done:
EnableReadOnlyPageWriteProtect ();
}
+ if (CsvIsEnabled () && Status == EFI_SUCCESS) {
+ if (Mode == ClearCBit)
+ CsvUpdateMemory (PageAddress, PageNum, TRUE);
+ else
+ CsvUpdateMemory (PageAddress, PageNum, FALSE);
+ }
+
return Status;
}
--
2.43.0

View File

@ -0,0 +1,41 @@
From f4621a7af63f9a29e57f563d4a85faa610a8a93b Mon Sep 17 00:00:00 2001
From: Xin Jiang <jiangxin@hygon.cn>
Date: Fri, 18 Aug 2023 17:17:28 +0800
Subject: [PATCH 07/11] OvmfPkg/Tcg: Add CsvLib for TpmMmioSevDecryptPei
Also add CsvLib to OvmfPkg/IntelTdx/IntelTdxX64.dsc to resolve
interface dependencies.
Signed-off-by: Xin Jiang <jiangxin@hygon.cn>
---
OvmfPkg/IntelTdx/IntelTdxX64.dsc | 1 +
OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf | 1 +
2 files changed, 2 insertions(+)
diff --git a/OvmfPkg/IntelTdx/IntelTdxX64.dsc b/OvmfPkg/IntelTdx/IntelTdxX64.dsc
index 193657ff..e9cdd70f 100644
--- a/OvmfPkg/IntelTdx/IntelTdxX64.dsc
+++ b/OvmfPkg/IntelTdx/IntelTdxX64.dsc
@@ -171,6 +171,7 @@
MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
diff --git a/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
index 51ad6d0d..402e4c9a 100644
--- a/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
+++ b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
@@ -29,6 +29,7 @@
PcdLib
PeimEntryPoint
PeiServicesLib
+ CsvLib
[Ppis]
gOvmfTpmMmioAccessiblePpiGuid ## PRODUCES
--
2.43.0

View File

@ -0,0 +1,641 @@
From a0a40a843c2811ab73fec8301697742e0f9ac440 Mon Sep 17 00:00:00 2001
From: Liu Zixing <liuzixing@hygon.cn>
Date: Fri, 25 Feb 2022 16:34:25 +0800
Subject: [PATCH 08/11] OvmfPkg: Add CsvDxe driver
CsvDxe creates and installs the CsvSharedMemory protocol.
CSV VM needs the shared memory to exchange data with external devices.
To improve the performance, CsvSharedMemory protocol pre-allocates
huge shared memory chunk as a pool.
When reqeusted, it allocates small pieces of shared memory from the
pool and records the allocated memory in a list.
When finished, the shared memory pieces are returned to the pool and
removed from the record list.
Signed-off-by: Xin Jiang <jiangxin@hygon.cn>
---
OvmfPkg/AmdSev/AmdSevX64.dsc | 1 +
OvmfPkg/AmdSev/AmdSevX64.fdf | 1 +
OvmfPkg/CsvDxe/CsvDxe.c | 104 +++++++++++
OvmfPkg/CsvDxe/CsvDxe.inf | 45 +++++
OvmfPkg/CsvDxe/CsvSharedMemory.c | 208 +++++++++++++++++++++
OvmfPkg/CsvDxe/CsvSharedMemory.h | 29 +++
OvmfPkg/Include/Protocol/CsvSharedMemory.h | 99 ++++++++++
OvmfPkg/OvmfPkg.dec | 1 +
OvmfPkg/OvmfPkgIa32X64.dsc | 1 +
OvmfPkg/OvmfPkgIa32X64.fdf | 1 +
OvmfPkg/OvmfPkgX64.dsc | 1 +
OvmfPkg/OvmfPkgX64.fdf | 1 +
12 files changed, 492 insertions(+)
create mode 100644 OvmfPkg/CsvDxe/CsvDxe.c
create mode 100644 OvmfPkg/CsvDxe/CsvDxe.inf
create mode 100644 OvmfPkg/CsvDxe/CsvSharedMemory.c
create mode 100644 OvmfPkg/CsvDxe/CsvSharedMemory.h
create mode 100644 OvmfPkg/Include/Protocol/CsvSharedMemory.h
diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc
index c70edd36..31bff348 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.dsc
+++ b/OvmfPkg/AmdSev/AmdSevX64.dsc
@@ -757,6 +757,7 @@
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
}
OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+ OvmfPkg/CsvDxe/CsvDxe.inf
#
# Variable driver stack (non-SMM)
diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf
index 7afa73aa..5d5612ab 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.fdf
+++ b/OvmfPkg/AmdSev/AmdSevX64.fdf
@@ -306,6 +306,7 @@ INF OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
INF OvmfPkg/PlatformDxe/Platform.inf
INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf
INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+INF OvmfPkg/CsvDxe/CsvDxe.inf
#
diff --git a/OvmfPkg/CsvDxe/CsvDxe.c b/OvmfPkg/CsvDxe/CsvDxe.c
new file mode 100644
index 00000000..d7edf3b9
--- /dev/null
+++ b/OvmfPkg/CsvDxe/CsvDxe.c
@@ -0,0 +1,104 @@
+/** @file
+
+ Hygon CSV DXE.
+
+ Copyright (c) 2022, HYGON. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/CsvLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/CsvSharedMemory.h>
+#include <Library/MemEncryptSevLib.h>
+#include "CsvSharedMemory.h"
+
+
+#define HUGE_PAGE_SIZE 0x200000ULL
+
+EFI_STATUS
+EFIAPI
+CsvDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ RETURN_STATUS DecryptStatus;
+ CSV_SHARED_MEMORY_PROTOCOL *SharedMemory;
+ EFI_PHYSICAL_ADDRESS Memory;
+ EFI_PHYSICAL_ADDRESS EndMemory;
+ EFI_ALLOCATE_TYPE AllocateType;
+ UINT64 Size;
+
+ Status = CsvInstallSharedMemoryProtocol ();
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "fail to install CsvSharedMemory protocol\n"));
+ return Status;
+ }
+
+ //
+ // Do nothing more when CSV is not enabled
+ //
+ if (!CsvIsEnabled ()) {
+ return EFI_SUCCESS;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gCsvSharedMemoryProtocolGuid,
+ NULL,
+ (VOID**)&SharedMemory
+ );
+
+ if (Status == EFI_SUCCESS) {
+
+ AllocateType = AllocateMaxAddress;
+ Memory = BASE_4GB - 1;
+
+ Status = gBS->AllocatePages (
+ AllocateType,
+ EfiBootServicesData,
+ CSV_SHARED_MEMORY_PAGE_NUMBER,
+ &Memory
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "fail to allocate CsvSharedMemory\n", SharedMemory));
+ } else {
+ //Align to huge page
+ EndMemory = (Memory + CSV_SHARED_MEMORY_SIZE) & (~(HUGE_PAGE_SIZE - 1));
+ Memory = ALIGN_VALUE(Memory, HUGE_PAGE_SIZE);
+ Size = (EndMemory > Memory) ? EndMemory - Memory : 0;
+ DecryptStatus = MemEncryptSevClearPageEncMask (
+ 0,
+ Memory,
+ Size >> EFI_PAGE_SHIFT
+ );
+ ASSERT_RETURN_ERROR (DecryptStatus);
+
+ SharedMemory->CsvInitializeSharedMemoryList (
+ SharedMemory,
+ (UINT64)Memory,
+ Size
+ );
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "fail to LocateProtocol gCsvSharedMemoryProtocolGuid\n"));
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/CsvDxe/CsvDxe.inf b/OvmfPkg/CsvDxe/CsvDxe.inf
new file mode 100644
index 00000000..0dc88605
--- /dev/null
+++ b/OvmfPkg/CsvDxe/CsvDxe.inf
@@ -0,0 +1,45 @@
+#/** @file
+#
+# Secure Isolated Virtualization
+#
+# Copyright (c) 2022, HYGON Inc. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License which accompanies this
+# distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 1.25
+ BASE_NAME = CsvDxe
+ FILE_GUID = 829310c0-b9c4-11e9-9e16-9b10d744f884
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = CsvDxeEntryPoint
+
+[Sources]
+ CsvDxe.c
+ CsvSharedMemory.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ CsvLib
+ UefiDriverEntryPoint
+
+[Depex]
+ TRUE
+
+[Protocols]
+ gCsvSharedMemoryProtocolGuid
diff --git a/OvmfPkg/CsvDxe/CsvSharedMemory.c b/OvmfPkg/CsvDxe/CsvSharedMemory.c
new file mode 100644
index 00000000..fbebc615
--- /dev/null
+++ b/OvmfPkg/CsvDxe/CsvSharedMemory.c
@@ -0,0 +1,208 @@
+/** @file
+
+ The protocol provides allocate, free the CSV shared memory.
+
+ Copyright (c) 2022, HYGON. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/CsvLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/CsvSharedMemory.h>
+
+
+STATIC LIST_ENTRY CsvSharedMemoryList = INITIALIZE_LIST_HEAD_VARIABLE (CsvSharedMemoryList);
+
+//
+// Insert the initial shared memory address and length to list.
+//
+
+EFI_STATUS
+EFIAPI
+CsvInitializeSharedMemoryList (
+ IN CSV_SHARED_MEMORY_PROTOCOL *Protocol,
+ IN UINT64 Address,
+ IN UINT64 Length
+ )
+{
+ CsvSharedMemoryEntry *Entry;
+
+ if (Length == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Entry = AllocatePool (sizeof (*Entry));
+ if (Entry == NULL) {
+ DEBUG((DEBUG_ERROR, "CsvInitializeSharedMemoryList AllocatePool error\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Entry->Start = Address;
+ Entry->Length = Length;
+ Entry->Signature = CSV_SHARED_MEMORY_SIGNATURE;
+
+ InsertTailList (&CsvSharedMemoryList, &Entry->Link);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+CsvAllocateSharedMemory (
+ IN CSV_SHARED_MEMORY_PROTOCOL *Protocol,
+ IN UINTN NumberOfPages,
+ OUT UINT64 *Memory
+ )
+{
+ LIST_ENTRY *Link;
+ CsvSharedMemoryEntry *Entry;
+ UINT64 MemoryLength;
+
+ MemoryLength = (UINT64)NumberOfPages << EFI_PAGE_SHIFT;
+
+ for (Link = CsvSharedMemoryList.ForwardLink; Link != &CsvSharedMemoryList; Link = Link->ForwardLink) {
+ Entry = CR (Link, CsvSharedMemoryEntry, Link, CSV_SHARED_MEMORY_SIGNATURE);
+ if (Entry->Length > MemoryLength) {
+ *Memory = (EFI_PHYSICAL_ADDRESS)Entry->Start;
+ Entry->Start = *Memory + MemoryLength;
+ Entry->Length -= MemoryLength;
+ break;
+ } else if (Entry->Length == MemoryLength) {
+ *Memory = (EFI_PHYSICAL_ADDRESS)Entry->Start;
+ RemoveEntryList (&Entry->Link);
+ FreePool (Entry);
+ break;
+ }
+ }
+
+
+
+ if (Link == &CsvSharedMemoryList) {
+ DEBUG ((EFI_D_ERROR, "CsvAllocateSharedMemory fail to allocate %u pages\n", NumberOfPages));
+ return EFI_NOT_FOUND;
+ }
+ else {
+ return EFI_SUCCESS;
+ }
+}
+
+
+
+EFI_STATUS
+EFIAPI
+CsvFreeSharedMemory (
+ IN CSV_SHARED_MEMORY_PROTOCOL *Protocol,
+ IN UINTN Pages,
+ IN UINT64 HostAddress
+ )
+{
+ LIST_ENTRY *Link;
+ CsvSharedMemoryEntry *Entry;
+ CsvSharedMemoryEntry *NewEntry;
+ UINT64 Memory;
+ UINT64 MemoryLength;
+ CsvSharedMemoryEntry *Previous = NULL;
+ BOOLEAN Inserted = FALSE;
+
+ Memory = (UINT64)HostAddress;
+ MemoryLength = (UINT64)Pages << EFI_PAGE_SHIFT;
+
+ for (Link = CsvSharedMemoryList.ForwardLink;
+ Link != &CsvSharedMemoryList;
+ Link = Link->ForwardLink) {
+ Entry = CR (Link, CsvSharedMemoryEntry, Link, CSV_SHARED_MEMORY_SIGNATURE);
+ if (Inserted)
+ goto Merge;
+ if (Entry->Start + Entry->Length == Memory) {
+ Entry->Length += MemoryLength;
+ Inserted = TRUE;
+ goto Merge;
+ } else if (Memory + MemoryLength < Entry->Start) {
+ NewEntry = AllocatePool (sizeof *NewEntry);
+ if (NewEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewEntry->Start = Memory;
+ NewEntry->Length = MemoryLength;
+ NewEntry->Signature = CSV_SHARED_MEMORY_SIGNATURE;
+
+ InsertTailList (&Entry->Link, &NewEntry->Link);
+ break;
+ } else if (Memory + MemoryLength == Entry->Start) {
+ Entry->Start = Memory;
+ Entry->Length += MemoryLength;
+ break;
+ } else if (Link->ForwardLink == &CsvSharedMemoryList) {
+ //
+ // Insert to tail
+ //
+ NewEntry = AllocatePool (sizeof *NewEntry);
+ if (NewEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewEntry->Start = Memory;
+ NewEntry->Length = MemoryLength;
+ NewEntry->Signature = CSV_SHARED_MEMORY_SIGNATURE;
+ InsertHeadList (Link, &NewEntry->Link);
+ break;
+ }
+
+Merge:
+ if (Previous) {
+ if (Previous->Start + Previous->Length == Entry->Start) {
+ Entry->Start = Previous->Start;
+ Entry->Length += Previous->Length;
+ RemoveEntryList (&Previous->Link);
+ FreePool (Previous);
+ }
+ break;
+ } else {
+ Previous = Entry;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+CSV_SHARED_MEMORY_PROTOCOL mCsvSharedMemory = {
+ CsvInitializeSharedMemoryList,
+ CsvAllocateSharedMemory,
+ CsvFreeSharedMemory
+};
+
+/**
+ Initialize CsvSharedMemory Protocol.
+
+**/
+EFI_STATUS
+EFIAPI
+CsvInstallSharedMemoryProtocol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gCsvSharedMemoryProtocolGuid,
+ &mCsvSharedMemory,
+ NULL
+ );
+ return Status;
+}
diff --git a/OvmfPkg/CsvDxe/CsvSharedMemory.h b/OvmfPkg/CsvDxe/CsvSharedMemory.h
new file mode 100644
index 00000000..16348181
--- /dev/null
+++ b/OvmfPkg/CsvDxe/CsvSharedMemory.h
@@ -0,0 +1,29 @@
+/** @file
+ CSV shared memory management protocol
+
+ Copyright (C) 2022 HYGON.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CSV_SHARED_MEMORY_H_
+#define _CSV_SHARED_MEMORY_H_
+
+//
+// Install SHARED_MEMORY protocol .
+//
+
+EFI_STATUS
+EFIAPI
+CsvInstallSharedMemoryProtocol (
+ VOID
+ );
+
+#endif
diff --git a/OvmfPkg/Include/Protocol/CsvSharedMemory.h b/OvmfPkg/Include/Protocol/CsvSharedMemory.h
new file mode 100644
index 00000000..ba62f3a4
--- /dev/null
+++ b/OvmfPkg/Include/Protocol/CsvSharedMemory.h
@@ -0,0 +1,99 @@
+/** @file
+ CSV shared memory management protocol
+
+ Copyright (C) 2022 HYGON.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PROTOCOL_CSV_SHARED_MEMORY_H__
+#define __PROTOCOL_CSV_SHARED_MEMORY_H__
+
+#define CSV_SHARED_MEMORY_PAGE_NUMBER (16384ULL)
+#define CSV_SHARED_MEMORY_SIZE ((CSV_SHARED_MEMORY_PAGE_NUMBER)*(SIZE_4KB))
+
+///
+/// Forward declaration
+///
+typedef struct _CSV_SHARED_MEMORY_PROTOCOL CSV_SHARED_MEMORY_PROTOCOL;
+
+
+///
+/// Function prototypes
+///
+
+/**
+ Initialize the list to manage the CSV shared memory.
+ Insert the start address and length.
+
+ @param This A pointer to CSV_SHARED_MEMORY_PROTOCOL instance.
+ @param Address The start address of the shared memory.
+ @param Length The length of the shared memory.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *CSV_INITIALIZE_SHARED_MEMORY_LIST)(
+ IN CSV_SHARED_MEMORY_PROTOCOL *This,
+ IN UINT64 Address,
+ IN UINT64 Length
+ );
+
+/**
+ Allocate buffer from the shared memory.
+
+ @param This A pointer to CSV_SHARED_MEMORY_PROTOCOL instance.
+ @param NumberOfPages The length of page number.
+ @param Memory When success, allocated memory will be stored in.
+
+ @return On success, EFI_SUCCESS. Otherwise an errno value
+ indicating the type of failure.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *CSV_ALLOCATE_SHARED_MEMORY)(
+ IN CSV_SHARED_MEMORY_PROTOCOL *This,
+ IN UINTN NumberOfPages,
+ OUT UINT64 *Memory
+ );
+
+/**
+ Free buffer to the shared memory.
+
+ @param This A pointer to CSV_SHARED_MEMORY_PROTOCOL instance.
+ @param NumberOfPages The page number.
+ @param Memory The allocated memory to be freed.
+
+ @return On success, EFI_SUCCESS. Otherwise an errno value
+ indicating the type of failure.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *CSV_FREE_SHARED_MEMORY)(
+ IN CSV_SHARED_MEMORY_PROTOCOL *This,
+ IN UINTN NumberOfPages,
+ IN UINT64 Memory
+ );
+
+///
+/// Protocol structure
+///
+struct _CSV_SHARED_MEMORY_PROTOCOL {
+ //
+ // Protocol data fields
+ //
+ CSV_INITIALIZE_SHARED_MEMORY_LIST CsvInitializeSharedMemoryList;
+ CSV_ALLOCATE_SHARED_MEMORY CsvAllocateSharedMemory;
+ CSV_FREE_SHARED_MEMORY CsvFreeSharedMemory;
+};
+
+extern EFI_GUID gCsvSharedMemoryProtocolGuid;
+
+#endif
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index f19a356f..593a5360 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -201,6 +201,7 @@
gQemuAcpiTableNotifyProtocolGuid = {0x928939b2, 0x4235, 0x462f, {0x95, 0x80, 0xf6, 0xa2, 0xb2, 0xc2, 0x1a, 0x4f}}
gEfiMpInitLibMpDepProtocolGuid = {0xbb00a5ca, 0x8ce, 0x462f, {0xa5, 0x37, 0x43, 0xc7, 0x4a, 0x82, 0x5c, 0xa4}}
gEfiMpInitLibUpDepProtocolGuid = {0xa9e7cef1, 0x5682, 0x42cc, {0xb1, 0x23, 0x99, 0x30, 0x97, 0x3f, 0x4a, 0x9f}}
+ gCsvSharedMemoryProtocolGuid = {0x0c795ed0, 0xbf0a, 0x11e9, {0x99, 0xbe, 0x50, 0x9a, 0x4c, 0x01, 0x1e, 0xd1}}
[PcdsFixedAtBuild]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 80849705..577583d0 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -976,6 +976,7 @@
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
}
OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+ OvmfPkg/CsvDxe/CsvDxe.inf
!if $(SMM_REQUIRE) == TRUE
OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 7f599f15..429c0eb2 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -345,6 +345,7 @@ INF OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
INF OvmfPkg/PlatformDxe/Platform.inf
INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf
INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+INF OvmfPkg/CsvDxe/CsvDxe.inf
!if $(SMM_REQUIRE) == TRUE
INF OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 7b276916..9e018485 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -1043,6 +1043,7 @@
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
}
OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+ OvmfPkg/CsvDxe/CsvDxe.inf
OvmfPkg/TdxDxe/TdxDxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 41fdb8b8..597c9def 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -375,6 +375,7 @@ INF OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
INF OvmfPkg/PlatformDxe/Platform.inf
INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf
INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+INF OvmfPkg/CsvDxe/CsvDxe.inf
!if $(SMM_REQUIRE) == TRUE
INF OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
--
2.43.0

View File

@ -0,0 +1,725 @@
From 00de2f4a698ec30eff79f115c4f35d3ff6cf84f8 Mon Sep 17 00:00:00 2001
From: Liu Zixing <liuzixing@hygon.cn>
Date: Fri, 25 Feb 2022 16:54:44 +0800
Subject: [PATCH 09/11] OvmfPkg/IoMmuDxe: Add CsvIoMmu protocol
Create the dedicated IoMmu protocol for CSV virtual machine.
And Install it during CSV VM boots up.
It calls the CsvSharedMemoryProtocol to allocate shared memory
for DMA operations.
- AllocateBuffer() allocates the shared memory.
- FreeBuffer() frees the shared memory.
- Map() does nothing when BusMasterCommonBuffer[64] is requested
Otherwise, Map() allocates shared memory.
- Unmap() does nothing when cleaning up a BusMasterCommonBuffer[64]
operation. Otherwise, Unmap() frees the shared memory.
Signed-off-by: Xin Jiang <jiangxin@hygon.cn>
---
OvmfPkg/IoMmuDxe/CsvIoMmu.c | 592 ++++++++++++++++++++++++++++++++++
OvmfPkg/IoMmuDxe/CsvIoMmu.h | 29 ++
OvmfPkg/IoMmuDxe/IoMmuDxe.c | 10 +
OvmfPkg/IoMmuDxe/IoMmuDxe.inf | 6 +-
4 files changed, 636 insertions(+), 1 deletion(-)
create mode 100644 OvmfPkg/IoMmuDxe/CsvIoMmu.c
create mode 100644 OvmfPkg/IoMmuDxe/CsvIoMmu.h
diff --git a/OvmfPkg/IoMmuDxe/CsvIoMmu.c b/OvmfPkg/IoMmuDxe/CsvIoMmu.c
new file mode 100644
index 00000000..2a46e984
--- /dev/null
+++ b/OvmfPkg/IoMmuDxe/CsvIoMmu.c
@@ -0,0 +1,592 @@
+/** @file
+
+ The protocol provides support to allocate, free, map and umap a DMA buffer
+ for bus master (e.g PciHostBridge). When CSV is enabled, the DMA operations
+ must be performed on non-secure memory so we have to allocate the DMA buffer
+ from non-secure memory.
+
+ Copyright (c) 2022, HYGON. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Protocol/IoMmu.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/CsvLib.h>
+#include <Protocol/CsvSharedMemory.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include "CsvIoMmu.h"
+
+#define MAP_INFO_SIG SIGNATURE_64 ('M', 'A', 'P', '_', 'I', 'N', 'F', 'O')
+
+typedef struct {
+ UINT64 Signature;
+ LIST_ENTRY Link;
+ EDKII_IOMMU_OPERATION Operation;
+ UINTN NumberOfBytes;
+ UINTN NumberOfPages;
+ EFI_PHYSICAL_ADDRESS SecureAddress;
+ EFI_PHYSICAL_ADDRESS UnSecureAddress;
+} MAP_INFO;
+
+//
+// List of the MAP_INFO structures that have been set up by IoMmuMap() and not
+// yet torn down by IoMmuUnmap(). The list represents the full set of mappings
+// currently in effect.
+//
+STATIC LIST_ENTRY mMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (mMapInfos);
+
+//
+// ASCII names for EDKII_IOMMU_OPERATION constants, for debug logging.
+//
+STATIC CONST CHAR8 * CONST
+mBusMasterOperationName[EdkiiIoMmuOperationMaximum] = {
+ "Read",
+ "Write",
+ "CommonBuffer",
+ "Read64",
+ "Write64",
+ "CommonBuffer64"
+};
+
+STATIC CSV_SHARED_MEMORY_PROTOCOL *SharedMemory;
+STATIC
+EFI_STATUS
+EFIAPI
+CsvAllocSharedPage(
+ IN UINTN Pages,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+{
+ EFI_STATUS Status;
+
+ Status = SharedMemory->CsvAllocateSharedMemory (
+ SharedMemory,
+ Pages,
+ (UINT64*)Address
+ );
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+CsvFreeSharedPage(
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+{
+ EFI_STATUS Status;
+
+ Status = SharedMemory->CsvFreeSharedMemory (
+ SharedMemory,
+ Pages,
+ (UINTN)HostAddress
+ );
+
+ return Status;
+}
+
+/**
+ Provides the controller-specific addresses required to access system memory
+ from a DMA bus master.
+ On CSV guest, the DMA openerations must be done on non-secure memory which
+ is the shared memory between the guest and QEMU.
+
+ @param This The protocol instance pointer.
+ @param Operation Indicates if the bus master is going to read or
+ write to system memory.
+ @param HostAddress The system memory address to map to the PCI
+ controller.
+ @param NumberOfBytes On input the number of bytes to map. On output
+ the number of bytes that were mapped.
+ @param DeviceAddress The resulting map address for the bus master
+ PCI controller to use to access the hosts
+ HostAddress.
+ @param Mapping A resulting value to pass to Unmap().
+
+ @retval EFI_SUCCESS The range was mapped for the returned
+ NumberOfBytes.
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common
+ buffer.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested
+ address.
+
+**/
+EFI_STATUS
+EFIAPI
+CsvIoMmuMap (
+ IN EDKII_IOMMU_PROTOCOL *This,
+ IN EDKII_IOMMU_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ EFI_STATUS Status;
+ MAP_INFO *MapInfo;
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a: Operation=%a Operation=%u Host=0x%p Bytes=0x%Lx\n",
+ __FUNCTION__,
+ ((Operation >= 0 &&
+ Operation < ARRAY_SIZE (mBusMasterOperationName)) ?
+ mBusMasterOperationName[Operation] :
+ "Invalid"),
+ Operation,
+ HostAddress,
+ (UINT64)((NumberOfBytes == NULL) ? 0 : *NumberOfBytes)
+ ));
+
+ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL ||
+ Mapping == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
+ // called later.
+ //
+ MapInfo = AllocatePool (sizeof (MAP_INFO));
+ if (MapInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Failed;
+ }
+
+ ZeroMem (&MapInfo->Link, sizeof MapInfo->Link);
+ MapInfo->Operation = Operation;
+ MapInfo->NumberOfBytes = *NumberOfBytes;
+ MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes);
+ MapInfo->Signature = MAP_INFO_SIG;
+
+ switch (Operation) {
+ //
+ // For BusMasterRead[64] and BusMasterWrite[64] operations, a bounce buffer
+ // is necessary regardless of whether the original (crypted) buffer crosses
+ // the 4GB limit or not -- we have to allocate a separate plaintext buffer.
+ // The only variable is whether the plaintext buffer should be under 4GB.
+ //
+ case EdkiiIoMmuOperationBusMasterRead:
+ case EdkiiIoMmuOperationBusMasterWrite:
+ //
+ // fall through
+ //
+ case EdkiiIoMmuOperationBusMasterRead64:
+ case EdkiiIoMmuOperationBusMasterWrite64:
+ //
+ // Allocate the implicit plaintext bounce buffer.
+ //
+ Status = CsvAllocSharedPage (
+ MapInfo->NumberOfPages,
+ &MapInfo->UnSecureAddress
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreeMapInfo;
+ }
+ MapInfo->SecureAddress = (UINTN)HostAddress;
+ if (Operation == EdkiiIoMmuOperationBusMasterRead ||
+ Operation == EdkiiIoMmuOperationBusMasterRead64) {
+ CopyMem (
+ (VOID *) (UINTN) MapInfo->UnSecureAddress,
+ (VOID *) (UINTN) MapInfo->SecureAddress,
+ MapInfo->NumberOfBytes
+ );
+ }
+ break;
+
+ //
+ // For BusMasterCommonBuffer[64] operations,
+ // AllocateBuffer already returns the plain-text,
+ // No need to decrypt the data.
+ //
+ case EdkiiIoMmuOperationBusMasterCommonBuffer:
+ case EdkiiIoMmuOperationBusMasterCommonBuffer64:
+ MapInfo->UnSecureAddress = (UINTN)HostAddress;
+ MapInfo->SecureAddress = (UINTN)HostAddress;
+ break;
+
+ default:
+ //
+ // Operation is invalid
+ //
+ Status = EFI_INVALID_PARAMETER;
+ goto FreeMapInfo;
+ }
+
+ //
+ // Track all MAP_INFO structures.
+ //
+ InsertHeadList (&mMapInfos, &MapInfo->Link);
+ //
+ // Populate output parameters.
+ //
+ *DeviceAddress = MapInfo->UnSecureAddress;
+ *Mapping = MapInfo;
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a: Mapping=0x%p Device=0x%Lx Host=0x%Lx Pages=0x%Lx\n",
+ __FUNCTION__,
+ MapInfo,
+ MapInfo->UnSecureAddress,
+ MapInfo->SecureAddress,
+ (UINT64)MapInfo->NumberOfPages
+ ));
+
+ return EFI_SUCCESS;
+
+FreeMapInfo:
+ FreePool (MapInfo);
+
+Failed:
+ *NumberOfBytes = 0;
+ return Status;
+}
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ This is an internal worker function that only extends the Map() API with
+ the MemoryMapLocked parameter.
+
+ @param This The protocol instance pointer.
+ @param Mapping The mapping value returned from Map().
+ @param MemoryMapLocked The function is executing on the stack of
+ gBS->ExitBootServices(); changes to the UEFI
+ memory map are forbidden.
+
+ @retval EFI_SUCCESS The range was unmapped.
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by
+ Map().
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system
+ memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CsvIoMmuUnmapWorker (
+ IN EDKII_IOMMU_PROTOCOL *This,
+ IN VOID *Mapping,
+ IN BOOLEAN MemoryMapLocked
+ )
+{
+ MAP_INFO *MapInfo;
+ EDKII_IOMMU_OPERATION Operation;
+
+ if (Mapping == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MapInfo = (MAP_INFO *)Mapping;
+ Operation = MapInfo->Operation;
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a: Mapping=0x%p MemoryMapLocked=%d Operation %a Operation %d\n",
+ __FUNCTION__,
+ Mapping,
+ MemoryMapLocked,
+ ((Operation >= 0 &&
+ Operation < ARRAY_SIZE (mBusMasterOperationName)) ?
+ mBusMasterOperationName[Operation] :
+ "Invalid"),
+ Operation
+ ));
+
+ switch (MapInfo->Operation) {
+ case EdkiiIoMmuOperationBusMasterWrite:
+ case EdkiiIoMmuOperationBusMasterWrite64:
+ CopyMem (
+ (VOID *) (UINTN) MapInfo->SecureAddress,
+ (VOID *) (UINTN) MapInfo->UnSecureAddress,
+ MapInfo->NumberOfBytes
+ );
+ case EdkiiIoMmuOperationBusMasterRead:
+ case EdkiiIoMmuOperationBusMasterRead64:
+ ZeroMem (
+ (VOID *)(UINTN)MapInfo->UnSecureAddress,
+ EFI_PAGES_TO_SIZE (MapInfo->NumberOfPages)
+ );
+ CsvFreeSharedPage(
+ MapInfo->NumberOfPages,
+ (VOID*)(UINTN)MapInfo->UnSecureAddress
+ );
+
+ default:
+ break;
+ }
+
+ //
+ // Forget the MAP_INFO structure, then free it (unless the UEFI memory map is
+ // locked).
+ //
+ RemoveEntryList (&MapInfo->Link);
+ if (!MemoryMapLocked) {
+ FreePool (MapInfo);
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ @param This The protocol instance pointer.
+ @param Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by
+ Map().
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system
+ memory.
+**/
+EFI_STATUS
+EFIAPI
+CsvIoMmuUnmap (
+ IN EDKII_IOMMU_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ return CsvIoMmuUnmapWorker (
+ This,
+ Mapping,
+ FALSE // MemoryMapLocked
+ );
+}
+
+/**
+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
+ OperationBusMasterCommonBuffer64 mapping.
+
+ @param This The protocol instance pointer.
+ @param Type This parameter is not used and must be ignored.
+ @param MemoryType The type of memory to allocate,
+ EfiBootServicesData or EfiRuntimeServicesData.
+ @param Pages The number of pages to allocate.
+ @param HostAddress A pointer to store the base system memory
+ address of the allocated range.
+ @param Attributes The requested bit mask of attributes for the
+ allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal
+ attribute bits are MEMORY_WRITE_COMBINE and
+ MEMORY_CACHED.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+CsvIoMmuAllocateBuffer (
+ IN EDKII_IOMMU_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ IN OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a: MemoryType=%u Pages=0x%Lx Attributes=0x%Lx\n",
+ __FUNCTION__,
+ (UINT32)MemoryType,
+ (UINT64)Pages,
+ Attributes
+ ));
+
+ //
+ // Validate Attributes
+ //
+ if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check for invalid inputs
+ //
+ if (HostAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The only valid memory types are EfiBootServicesData and
+ // EfiRuntimeServicesData
+ //
+ if (MemoryType != EfiBootServicesData &&
+ MemoryType != EfiRuntimeServicesData) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // We'll need a header page for the COMMON_BUFFER_HEADER structure.
+ //
+ if (Pages > MAX_UINTN - 1) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = CsvAllocSharedPage (Pages,&PhysicalAddress);
+ if (Status != EFI_SUCCESS){
+ goto error;
+ }
+
+
+ *HostAddress = (VOID *)(UINTN)PhysicalAddress;
+
+ return EFI_SUCCESS;
+
+error:
+ return Status;
+}
+
+/**
+ Frees memory that was allocated with AllocateBuffer().
+
+ @param This The protocol instance pointer.
+ @param Pages The number of pages to free.
+ @param HostAddress The base system memory address of the allocated
+ range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
+ Pages was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+CsvIoMmuFreeBuffer (
+ IN EDKII_IOMMU_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+{
+
+ EFI_STATUS Status;
+
+ if (HostAddress == NULL || Pages == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a: Host=0x%p Pages=0x%Lx\n",
+ __FUNCTION__,
+ HostAddress,
+ (UINT64)Pages
+ ));
+
+ Status = CsvFreeSharedPage (Pages, HostAddress);
+
+ return Status;
+}
+
+
+/**
+ Set IOMMU attribute for a system memory.
+
+ @param[in] This The protocol instance pointer.
+ @param[in] DeviceHandle The device who initiates the DMA access
+ request.
+ @param[in] Mapping The mapping value returned from Map().
+ @param[in] IoMmuAccess The IOMMU access.
+
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory range
+ specified by DeviceAddress and Length.
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by
+ Map().
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination
+ of access.
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported
+ by the IOMMU.
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory range
+ specified by Mapping.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
+ modify the IOMMU access.
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while
+ attempting the operation.
+
+**/
+EFI_STATUS
+EFIAPI
+CsvIoMmuSetAttribute (
+ IN EDKII_IOMMU_PROTOCOL *This,
+ IN EFI_HANDLE DeviceHandle,
+ IN VOID *Mapping,
+ IN UINT64 IoMmuAccess
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+EDKII_IOMMU_PROTOCOL mCsv = {
+ EDKII_IOMMU_PROTOCOL_REVISION,
+ CsvIoMmuSetAttribute,
+ CsvIoMmuMap,
+ CsvIoMmuUnmap,
+ CsvIoMmuAllocateBuffer,
+ CsvIoMmuFreeBuffer,
+};
+
+/**
+ Initialize Iommu Protocol.
+
+**/
+EFI_STATUS
+EFIAPI
+CsvInstallIoMmuProtocol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ Status = gBS->LocateProtocol (
+ &gCsvSharedMemoryProtocolGuid,
+ NULL,
+ (VOID**)&SharedMemory
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto error;
+ }
+
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEdkiiIoMmuProtocolGuid,
+ &mCsv,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto error;
+ }
+
+ return EFI_SUCCESS;
+
+error:
+ return Status;
+}
diff --git a/OvmfPkg/IoMmuDxe/CsvIoMmu.h b/OvmfPkg/IoMmuDxe/CsvIoMmu.h
new file mode 100644
index 00000000..431d2843
--- /dev/null
+++ b/OvmfPkg/IoMmuDxe/CsvIoMmu.h
@@ -0,0 +1,29 @@
+/** @file
+
+ The protocol provides support to allocate, free, map and umap a DMA buffer
+ for bus master (e.g PciHostBridge). When CSV is enabled, the DMA operations
+ must be performed on unencrypted buffer hence protocol clear the encryption
+ bit from the DMA buffer.
+
+ Copyright (c) 2022, HYGON. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CSV_IOMMU_H_
+#define _CSV_IOMMU_H_
+
+EFI_STATUS
+EFIAPI
+CsvInstallIoMmuProtocol (
+ VOID
+ );
+
+#endif
diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.c b/OvmfPkg/IoMmuDxe/IoMmuDxe.c
index aab6d8b9..cd03ca90 100644
--- a/OvmfPkg/IoMmuDxe/IoMmuDxe.c
+++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.c
@@ -10,6 +10,8 @@
**/
#include "CcIoMmu.h"
+#include <Library/CsvLib.h>
+#include "CsvIoMmu.h"
EFI_STATUS
EFIAPI
@@ -21,6 +23,14 @@ IoMmuDxeEntryPoint (
EFI_STATUS Status;
EFI_HANDLE Handle;
+ if (CsvIsEnabled ()) {
+ Status = CsvInstallIoMmuProtocol ();
+ if (Status != EFI_SUCCESS) {
+ DEBUG((EFI_D_ERROR, "fail to install CSV IOMMU\n"));
+ }
+ return Status;
+ }
+
//
// When SEV or TDX is enabled, install IoMmu protocol otherwise install the
// placeholder protocol so that other dependent module can run.
diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf
index 17fca528..37d0d819 100644
--- a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf
@@ -22,6 +22,8 @@
CcIoMmu.h
IoMmuDxe.c
IoMmuBuffer.c
+ CsvIoMmu.c
+ CsvIoMmu.h
[Packages]
MdePkg/MdePkg.dec
@@ -37,6 +39,7 @@
MemoryAllocationLib
UefiBootServicesTableLib
UefiDriverEntryPoint
+ CsvLib
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr
@@ -44,6 +47,7 @@
[Protocols]
gEdkiiIoMmuProtocolGuid ## SOMETIME_PRODUCES
gIoMmuAbsentProtocolGuid ## SOMETIME_PRODUCES
+ gCsvSharedMemoryProtocolGuid
[Depex]
- TRUE
+ gCsvSharedMemoryProtocolGuid
--
2.43.0

View File

@ -0,0 +1,154 @@
From 7efbcd65c6ec50be3ac691cf859b3d1fea9a73dd Mon Sep 17 00:00:00 2001
From: Xin Jiang <jiangxin@hygon.cn>
Date: Wed, 16 Aug 2023 19:53:27 +0800
Subject: [PATCH 10/11] OvmfPkg: Reserve a CPUID table page for CSV guest
Reserve a page for CPUID table which will be initialized by firmware.
In future, A CSV guest should get CPUID value from a CPUID table
which has been validated by firmware rather than requesting them from
hypervisor via a VMGEXIT.
Signed-off-by: Xin Jiang <jiangxin@hygon.cn>
---
OvmfPkg/AmdSev/AmdSevX64.fdf | 5 ++++-
OvmfPkg/OvmfPkg.dec | 4 ++++
OvmfPkg/OvmfPkgX64.fdf | 5 ++++-
OvmfPkg/PlatformPei/Csv.c | 6 ++++++
OvmfPkg/PlatformPei/PlatformPei.inf | 2 ++
OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 15 +++++++++++++++
OvmfPkg/ResetVector/ResetVector.inf | 2 ++
OvmfPkg/ResetVector/ResetVector.nasmb | 2 ++
8 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf
index 5d5612ab..714ab004 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.fdf
+++ b/OvmfPkg/AmdSev/AmdSevX64.fdf
@@ -77,7 +77,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp
0x010000|0x002000
gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize
-0x012000|0x00E000
+0x012000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize
+
+0x013000|0x00D000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 593a5360..34bca309 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -438,6 +438,10 @@
gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|0|UINT32|0x70
gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize|0|UINT32|0x71
+ ## the base address of the cpuid table page used by CSV.
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|0|UINT32|0x72
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize|0|UINT32|0x73
+
[PcdsDynamic, PcdsDynamicEx]
gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 597c9def..b1cf0d99 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -97,7 +97,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp
0x00F000|0x002000
gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize
-0x011000|0x00F000
+0x011000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize
+
+0x012000|0x00E000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
diff --git a/OvmfPkg/PlatformPei/Csv.c b/OvmfPkg/PlatformPei/Csv.c
index 5ab83312..a52112d5 100644
--- a/OvmfPkg/PlatformPei/Csv.c
+++ b/OvmfPkg/PlatformPei/Csv.c
@@ -57,6 +57,12 @@ CsvInitializeMemInfo (
(UINT64)(UINTN) FixedPcdGet32 (PcdCsvDefaultSecureCallSize),
EfiReservedMemoryType
);
+
+ BuildMemoryAllocationHob (
+ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdOvmfCsvCpuidBase),
+ (UINT64)(UINTN) FixedPcdGet32 (PcdOvmfCsvCpuidSize),
+ EfiReservedMemoryType
+ );
}
VOID
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index 45d16889..07de179f 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -135,6 +135,8 @@
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize
gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase
gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable
diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
index c86b0499..dc7348e9 100644
--- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
+++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
@@ -63,6 +63,21 @@ csvSecureCallBase:
DB 0xAB, 0x21, 0x6B, 0x27, 0x5D, 0x55, 0x56, 0xA5
csvSecureCallEnd:
+;
+; CSV cpuid table
+;
+; Provide cpuid table page when boot up for CSV guest
+;
+; GUID : 1b4c70e6-07e6-4e4e-8f28-0eaf871a0752
+;
+csvCpuidTableBase:
+ DD CSV_CPUID_TABLE_SIZE
+ DD CSV_CPUID_TABLE_BASE
+ DW csvCpuidTableEnd - csvCpuidTableBase
+ DB 0xE6, 0x70, 0x4C, 0x1B, 0xE6, 0x07, 0x4E, 0x4E
+ DB 0x8F, 0x28, 0x0E, 0xAF, 0x87, 0x1A, 0x07, 0x52
+csvCpuidTableEnd:
+
;
; TDX Metadata offset block
;
diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf
index e4adedb8..5dfba883 100644
--- a/OvmfPkg/ResetVector/ResetVector.inf
+++ b/OvmfPkg/ResetVector/ResetVector.inf
@@ -37,6 +37,8 @@
gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase
gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
index d156a511..da4068b7 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -125,6 +125,8 @@
%define CSV_DEFAULT_SECURE_CALL_BASE FixedPcdGet32 (PcdCsvDefaultSecureCallBase)
%define CSV_DEFAULT_SECURE_CALL_SIZE FixedPcdGet32 (PcdCsvDefaultSecureCallSize)
+ %define CSV_CPUID_TABLE_BASE FixedPcdGet32 (PcdOvmfCsvCpuidBase)
+ %define CSV_CPUID_TABLE_SIZE FixedPcdGet32 (PcdOvmfCsvCpuidSize)
%include "X64/IntelTdxMetadata.asm"
%include "Ia32/Flat32ToFlat64.asm"
--
2.43.0

View File

@ -0,0 +1,67 @@
From 26d16863ccb72fd9ac3cbec8d732e0574610893b Mon Sep 17 00:00:00 2001
From: lilu <lilu@hygon.cn>
Date: Thu, 7 Sep 2023 14:44:59 +0800
Subject: [PATCH 11/11] OvmfPkg: Use classic mmio window for CSV guest
For CSV guest, firmware restricts gpa range. Dynamic mmio window
sets Mmio64Base exceeding firmware restriction. Use classic mmio
window for CSV guest. Classic mmio window is less than firmware
restriction under real circumstances.
Signed-off-by: Xin Jiang <jiangxin@hygon.cn>
---
OvmfPkg/Library/CsvLib/CsvLib.inf | 2 +-
OvmfPkg/Library/PlatformInitLib/MemDetect.c | 4 +++-
OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf | 1 +
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/OvmfPkg/Library/CsvLib/CsvLib.inf b/OvmfPkg/Library/CsvLib/CsvLib.inf
index 57efbe70..bcb6546f 100644
--- a/OvmfPkg/Library/CsvLib/CsvLib.inf
+++ b/OvmfPkg/Library/CsvLib/CsvLib.inf
@@ -21,7 +21,7 @@
FILE_GUID = 9460ef3a-b9c3-11e9-8324-7371ac35e1e3
MODULE_TYPE = BASE
VERSION_STRING = 1.0
- LIBRARY_CLASS = CsvLib|PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER
+ LIBRARY_CLASS = CsvLib|SEC PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER
#
# The following information is for reference only and not required by the build
diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
index 3c9f01cf..7eef68a0 100644
--- a/OvmfPkg/Library/PlatformInitLib/MemDetect.c
+++ b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
@@ -40,6 +40,7 @@ Module Name:
#include <Library/QemuFwCfgLib.h>
#include <Library/QemuFwCfgSimpleParserLib.h>
#include <Library/TdxLib.h>
+#include <Library/CsvLib.h>
#include <Library/PlatformInitLib.h>
@@ -687,7 +688,8 @@ PlatformDynamicMmioWindow (
AddrSpace = LShiftU64 (1, PlatformInfoHob->PhysMemAddressWidth);
MmioSpace = LShiftU64 (1, PlatformInfoHob->PhysMemAddressWidth - 3);
- if ((PlatformInfoHob->PcdPciMmio64Size < MmioSpace) &&
+ if (!CsvIsEnabled() &&
+ (PlatformInfoHob->PcdPciMmio64Size < MmioSpace) &&
(PlatformInfoHob->PcdPciMmio64Base + MmioSpace < AddrSpace))
{
DEBUG ((DEBUG_INFO, "%a: using dynamic mmio window\n", __func__));
diff --git a/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf b/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
index 5a79d95b..8fc80f48 100644
--- a/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
+++ b/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
@@ -52,6 +52,7 @@
PcdLib
PciLib
PeiHardwareInfoLib
+ CsvLib
[LibraryClasses.X64]
TdxLib
--
2.43.0

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

@ -0,0 +1,122 @@
From ff113b5d376dd9054aefc8452e7ff04459489a44 Mon Sep 17 00:00:00 2001
From: Bibo Mao <maobibo@loongson.cn>
Date: Mon, 25 Mar 2024 10:50:28 +0800
Subject: [PATCH 1/2] Platform/Loongson: Remove minimium memory size limitation
Temparory stack memory on PEI is hardcoded now, also minimium memory
size 256M is hardcoded now. Here memory map table from fw cfg can be
parsed. If there is memory map entry contains pei stack, it can be
published as usable memory at PEI stage.
Cc: Bibo Mao <maobibo@loongson.cn>
Cc: Chao Li <lichao@loongson.cn>
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
Reviewed-by: Chao Li <lichao@loongson.cn>
---
.../Loongson/LoongArchQemuPkg/Loongson.dec | 2 -
.../Loongson/LoongArchQemuPkg/Loongson.dsc | 6 ---
.../LoongArchQemuPkg/PlatformPei/MemDetect.c | 38 ++++++++++++++++++-
.../PlatformPei/PlatformPei.inf | 2 -
4 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec
index e638b835e4..c2c6cc9596 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec
@@ -48,8 +48,6 @@
gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase|0|UINT64|0x0000000b
gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize|0|UINT32|0x0000000c
- gLoongArchQemuPkgTokenSpaceGuid.PcdUefiRamTop|0x0|UINT64|0x0000000d
- gLoongArchQemuPkgTokenSpaceGuid.PcdRamRegionsBottom|0x0|UINT64|0x0000000e
gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase|0x0|UINT64|0x0000000f
gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize|0x0|UINT32|0x00000010
diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
index 58aa16d3a9..aab2ca9b28 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
@@ -356,12 +356,6 @@
gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase | 0x10000
gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize | 0x10000
gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreeBase | 0x100000
- #
- # minimal memory for uefi bios should be 512M
- # 0x00000000 - 0x10000000
- # 0x90000000 - 0xA0000000
- #
- gLoongArchQemuPkgTokenSpaceGuid.PcdUefiRamTop | 0x10000000
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiExposedTableVersions | 0x06
gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile | { 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/MemDetect.c b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/MemDetect.c
index 7e6a4a3aa9..7aa6fdc175 100644
--- a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/MemDetect.c
+++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/MemDetect.c
@@ -40,12 +40,48 @@ PublishPeiMemory (
UINT64 Base;
UINT64 Size;
UINT64 RamTop;
+ FIRMWARE_CONFIG_ITEM FwCfgItem;
+ UINTN FwCfgSize;
+ UINTN Processed;
+ LOONGARCH_MEMMAP_ENTRY MemoryMapEntry;
//
// Determine the range of memory to use during PEI
//
Base = PcdGet64 (PcdSecPeiTempRamBase) + PcdGet32 (PcdSecPeiTempRamSize);
- RamTop = PcdGet64 (PcdUefiRamTop);
+ RamTop = 0;
+
+ Status = QemuFwCfgFindFile ("etc/memmap", &FwCfgItem, &FwCfgSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (FwCfgSize % sizeof MemoryMapEntry != 0) {
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ QemuFwCfgSelectItem (FwCfgItem);
+ for (Processed = 0; Processed < FwCfgSize; Processed += sizeof MemoryMapEntry) {
+ QemuFwCfgReadBytes (sizeof MemoryMapEntry, &MemoryMapEntry);
+ if (MemoryMapEntry.Type != EfiAcpiAddressRangeMemory) {
+ continue;
+ }
+
+ /*
+ * Find memory map entry where PEI temp stack is located
+ */
+ if ((MemoryMapEntry.BaseAddr <= Base) &&
+ (Base < (MemoryMapEntry.BaseAddr + MemoryMapEntry.Length))) {
+ RamTop = MemoryMapEntry.BaseAddr + MemoryMapEntry.Length;
+ break;
+ }
+ }
+
+ if (RamTop == 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR: No memory map entry contains temp stack \n"));
+ ASSERT (FALSE);
+ }
+
Size = RamTop - Base;
//
diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf
index 6cc3513b63..65591a4d7b 100644
--- a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf
+++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf
@@ -64,8 +64,6 @@
[FixedPcd]
gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvBase
gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvSize
- gLoongArchQemuPkgTokenSpaceGuid.PcdRamRegionsBottom
- gLoongArchQemuPkgTokenSpaceGuid.PcdUefiRamTop
gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase
gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize
gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize
--
2.46.0

View File

@ -0,0 +1,62 @@
From c9cb2611ae34a79c28671a703368e88267d6cc24 Mon Sep 17 00:00:00 2001
From: Xiaotian Wu <wuxiaotian@loongson.cn>
Date: Tue, 19 Nov 2024 19:05:49 +0800
Subject: [PATCH 2/2] Platform/Loongson: Modify loongarch uefi firmware size
After the loongarch flash block size is changed from 128K to 256K,
qemu requires that the UEFI firmware size be aligned with the flash block size(256K).
Otherwise, the firmware cannot be loaded,
Use the following code to resolve the old firmware loading problem:
mv QEMU_EFI.fd QEMU_EFI.fd-bak
cat QEMU_EFI.fd-bak /dev/zero | head -c 16m > ./QEMU_EFI.fd
mv QEMU_VARS.fd QEMU_VARS.fd-bak
cat QEMU_VARS.fd-bak /dev/zero | head -c 16m > ./QEMU_VARS.fd
For the new firmware, we refer to other architecture UEFI and
set the UEFI firmware size to align with the flash block size(256K).
So for this patch, we set the UEFI firmware size to 256K alignment.
---
Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc | 8 ++++----
Platform/Loongson/LoongArchQemuPkg/VarStore.fdf.inc | 4 ++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc
index e30c4629f7..c31909ca9a 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc
@@ -18,12 +18,12 @@ DEFINE FD_SIZE = 0x400000
#flash code layout
#Set Sec base address and size in flash
DEFINE SECFV_OFFSET = 0x00000000
-DEFINE SECFV_SIZE = 0x00010000
+DEFINE SECFV_SIZE = 0x00040000
#Set Pei base address and size in flash
-DEFINE PEIFV_OFFSET = 0x00010000
+DEFINE PEIFV_OFFSET = 0x00040000
DEFINE PEIFV_SIZE = 0x00040000
#Set Dxe base address and size in flash
-DEFINE DXEFV_OFFSET = 0x00050000
-DEFINE DXEFV_SIZE = 0x00350000
+DEFINE DXEFV_OFFSET = 0x00080000
+DEFINE DXEFV_SIZE = 0x00380000
diff --git a/Platform/Loongson/LoongArchQemuPkg/VarStore.fdf.inc b/Platform/Loongson/LoongArchQemuPkg/VarStore.fdf.inc
index 83ce3d8008..f34901950d 100644
--- a/Platform/Loongson/LoongArchQemuPkg/VarStore.fdf.inc
+++ b/Platform/Loongson/LoongArchQemuPkg/VarStore.fdf.inc
@@ -10,8 +10,8 @@
BaseAddress = 0x0
Size = 0x1000000
ErasePolarity = 1
-BlockSize = 0x20000
-NumBlocks = 128
+BlockSize = 0x40000
+NumBlocks = 64
0x00000000|0x00040000
#NV_VARIABLE_STORE
--
2.46.0

View File

@ -0,0 +1,40 @@
From bdbeb6e653d7bbaa5eb4ad104119abfc7030c285 Mon Sep 17 00:00:00 2001
From: Xianglai Li <lixianglai@loongson.cn>
Date: Mon, 25 Nov 2024 16:16:39 +0800
Subject: [PATCH] fixup fdt parse error
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
---
.../Library/SerialPortLib/EarlySerialPortLib16550.c | 2 +-
Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/EarlySerialPortLib16550.c b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/EarlySerialPortLib16550.c
index c713c6e9..dd64a000 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/EarlySerialPortLib16550.c
+++ b/Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/EarlySerialPortLib16550.c
@@ -155,7 +155,7 @@ GetSerialConsolePortAddress (
}
// Determine the actual path length, as a colon terminates the path.
- Path = ScanMem8 (Prop, ':', PropSize);
+ Path = ScanMem8 (Prop, PropSize, (UINT8)":");
if (Path == NULL) {
PathLen = AsciiStrLen (Prop);
} else {
diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.c b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.c
index 84bb8e8a..02982cd0 100644
--- a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.c
+++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.c
@@ -193,7 +193,7 @@ GetSerialConsolePortAddress (
}
// Determine the actual path length, as a colon terminates the path.
- Path = ScanMem8 (Prop, ':', PropSize);
+ Path = ScanMem8 (Prop, PropSize, (UINT8)":");
if (Path == NULL) {
PathLen = AsciiStrLen (Prop);
} else {
--
2.41.0

View File

@ -7,7 +7,7 @@
Name: edk2
Version: %{stable_date}
Release: 11
Release: 17
Summary: EFI Development Kit II
License: BSD-2-Clause-Patent and OpenSSL and MIT
URL: https://github.com/tianocore/edk2
@ -90,6 +90,48 @@ patch52: 0052-Revert-LoongArchQemuPkg-auto-gen-fix-SEC-ProcessLibr.patch
# Fix edk2 build errror with gcc-14
patch53: 0053-relax_edk2_gcc14.patch
# Fix CVE-2024-38796
patch54: 0054-MdePkg-Fix-overflow-issue-in-BasePeCoffLib.patch
# Fix CVE-2023-45236、CVE-2023-45237
patch55: 0055-NetworkPkg-SECURITY-PATCH-CVE-2023-45237.patch
patch56: 0056-NetworkPkg-TcpDxe-SECURITY-PATCH-CVE-2023-45236.patch
# Support Hygon CSV3
patch57: 0057-MdePkg-Add-StandardSignatureIsHygonGenuine-in-BaseCp.patch
patch58: 0058-UefiCpuPkg-LocalApicLib-Exclude-second-SendIpi-seque.patch
patch59: 0059-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-CPU.patch
patch60: 0060-OvmfPkg-ResetVector-Support-CSV-in-ResetVector-phase.patch
patch61: 0061-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memory.patch
patch62: 0062-OvmfPkg-BaseMemcryptSevLib-update-page-status-to-Sec.patch
patch63: 0063-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptPei.patch
patch64: 0064-OvmfPkg-Add-CsvDxe-driver.patch
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
# Support Loongarch firmware size
patch80: 0080-Platform-Loongson-Remove-minimium-memory-size-limita.patch
patch81: 0081-Platform-Loongson-Modify-loongarch-uefi-firmware-siz.patch
patch82: 0082-fixup-fdt-parse-error.patch
BuildRequires: acpica-tools gcc gcc-c++ libuuid-devel python3 bc nasm python3-unversioned-command isl
%description
@ -359,6 +401,27 @@ chmod +x %{buildroot}%{_bindir}/Rsa2048Sha256GenerateKeys
%endif
%changelog
* Tue Dec 17 2024 Xiaotian Wu <wuxiaotian@loongson.cn> - 202308-17
- Update LoongArch virtual machine
- 0080-Platform-Loongson-Remove-minimium-memory-size-limita.patch
- 0081-Platform-Loongson-Modify-loongarch-uefi-firmware-siz.patch
- 0082-fixup-fdt-parse-error.patch
* 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
* Mon Oct 14 2024 shenyage<shenyage1@huawei.com> - 202308-13
- fix CVE-2023-45236、CVE-2023-45237
* Wed Oct 09 2024 zhangxianting <zhangxianting@uniontech.com> - 202308-12
- fix CVE-2024-38796
* Fri Sep 13 2024 Xiaotian Wu <wuxiaotian@loongson.cn> - 202308-11
- add LoongArch support
- backport edk2-platform to build with edk2-2308