When SEV is enabled, the DMA must be performed on unencrypted pages.
So when get asked to perfom FWCFG DMA read or write, we allocate a
intermediate (bounce buffer) unencrypted buffer and use this buffer
for DMA read or write.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf | 7 ++
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c | 108 ++++++++++++++++++++
2 files changed, 115 insertions(+)
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
index d7e368e5435d..ec128f82c702 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
@@ -39,6 +39,7 @@ [Sources]
[Packages]
MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
OvmfPkg/OvmfPkg.dec
[LibraryClasses]
@@ -47,4 +48,10 @@ [LibraryClasses]
DebugLib
IoLib
MemoryAllocationLib
+ MemEncryptSevLib
+[Protocols]
+ gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES
+
+[Depex]
+ gEdkiiIoMmuProtocolGuid OR gIoMmuDetectedProtocolGuid
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
index ac05f4c347f3..bda1a80b5eb9 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
@@ -4,6 +4,7 @@
Copyright (C) 2013, Red Hat, Inc.
Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2017, Advanced Micro Devices. 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
@@ -14,14 +15,36 @@
WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
+#include <Uefi.h>
+
+#include <Protocol/IoMmu.h>
+
+#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/QemuFwCfgLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemEncryptSevLib.h>
#include "QemuFwCfgLibInternal.h"
STATIC BOOLEAN mQemuFwCfgSupported = FALSE;
STATIC BOOLEAN mQemuFwCfgDmaSupported;
+STATIC EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;
+/**
+
+ Returns a boolean indicating whether SEV is enabled
+
+ @retval TRUE SEV is enabled
+ @retval FALSE SEV is disabled
+**/
+BOOLEAN
+InternalQemuFwCfgSevIsEnabled (
+ VOID
+ )
+{
+ return MemEncryptSevIsEnabled ();
+}
/**
Returns a boolean indicating if the firmware configuration interface
@@ -79,6 +102,22 @@ QemuFwCfgInitialize (
mQemuFwCfgDmaSupported = TRUE;
DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n"));
}
+
+ if (mQemuFwCfgDmaSupported && MemEncryptSevIsEnabled ()) {
+ EFI_STATUS Status;
+
+ //
+ // IoMmuDxe driver must have installed the IOMMU protocol. If we are not
+ // able to locate the protocol then something must have gone wrong.
+ //
+ Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmuProtocol);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "QemuwCfgSevDma: failed to locate IOMMU protocol\n"));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+ }
+
return RETURN_SUCCESS;
}
@@ -114,3 +153,72 @@ InternalQemuFwCfgDmaIsAvailable (
{
return mQemuFwCfgDmaSupported;
}
+
+/**
+ Allocate a bounce buffer for SEV DMA.
+
+ @param[in] NumPage Number of pages.
+ @param[out] Buffer Allocated DMA Buffer pointer
+
+**/
+VOID
+InternalQemuFwCfgSevDmaAllocateBuffer (
+ OUT VOID **Buffer,
+ IN UINT32 NumPages
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (mIoMmuProtocol != NULL);
+
+ Status = mIoMmuProtocol->AllocateBuffer (
+ mIoMmuProtocol,
+ 0,
+ EfiBootServicesData,
+ NumPages,
+ Buffer,
+ EDKII_IOMMU_ATTRIBUTE_MEMORY_CACHED
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%a failed to allocate %u pages\n", gEfiCallerBaseName,
+ __FUNCTION__, NumPages));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName,
+ __FUNCTION__, (UINT64)(UINTN)Buffer, NumPages));
+}
+
+/**
+ Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer
+
+ @param[in] NumPage Number of pages.
+ @param[in] Buffer DMA Buffer pointer
+
+**/
+VOID
+InternalQemuFwCfgSevDmaFreeBuffer (
+ IN VOID *Buffer,
+ IN UINT32 NumPages
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (mIoMmuProtocol != NULL);
+
+ Status = mIoMmuProtocol->FreeBuffer (
+ mIoMmuProtocol,
+ NumPages,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%a failed to free buffer 0x%Lx pages %u\n",
+ gEfiCallerBaseName, __FUNCTION__, (UINT64)(UINTN)Buffer, NumPages));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName,
+ __FUNCTION__, (UINT64)(UINTN)Buffer, NumPages));
+}
--
2.7.4
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
comments below: On 05/22/17 17:23, Brijesh Singh wrote: > When SEV is enabled, the DMA must be performed on unencrypted pages. > So when get asked to perfom FWCFG DMA read or write, we allocate a > intermediate (bounce buffer) unencrypted buffer and use this buffer > for DMA read or write. > > > Cc: Jordan Justen <jordan.l.justen@intel.com> > Cc: Laszlo Ersek <lersek@redhat.com> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> > --- > OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf | 7 ++ > OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c | 108 ++++++++++++++++++++ > 2 files changed, 115 insertions(+) > > diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf > index d7e368e5435d..ec128f82c702 100644 > --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf > +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf > @@ -39,6 +39,7 @@ [Sources] > > [Packages] > MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > OvmfPkg/OvmfPkg.dec > > [LibraryClasses] > @@ -47,4 +48,10 @@ [LibraryClasses] > DebugLib > IoLib > MemoryAllocationLib > + MemEncryptSevLib > > +[Protocols] > + gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES > + > +[Depex] > + gEdkiiIoMmuProtocolGuid OR gIoMmuDetectedProtocolGuid I'll comment on the depex elsewhere (returning to an earlier spot in the series). Other than that, I have only cosmetic comments: > diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c > index ac05f4c347f3..bda1a80b5eb9 100644 > --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c > +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c > @@ -4,6 +4,7 @@ > > Copyright (C) 2013, Red Hat, Inc. > Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR> > + Copyright (c) 2017, Advanced Micro Devices. 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 > @@ -14,14 +15,36 @@ > WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > **/ > > +#include <Uefi.h> > + > +#include <Protocol/IoMmu.h> > + > +#include <Library/BaseLib.h> > #include <Library/DebugLib.h> > #include <Library/QemuFwCfgLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/MemEncryptSevLib.h> > > #include "QemuFwCfgLibInternal.h" > > STATIC BOOLEAN mQemuFwCfgSupported = FALSE; > STATIC BOOLEAN mQemuFwCfgDmaSupported; > > +STATIC EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; > +/** > + > + Returns a boolean indicating whether SEV is enabled > + > + @retval TRUE SEV is enabled > + @retval FALSE SEV is disabled > +**/ > +BOOLEAN > +InternalQemuFwCfgSevIsEnabled ( > + VOID > + ) > +{ > + return MemEncryptSevIsEnabled (); > +} > > /** > Returns a boolean indicating if the firmware configuration interface > @@ -79,6 +102,22 @@ QemuFwCfgInitialize ( > mQemuFwCfgDmaSupported = TRUE; > DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n")); > } > + > + if (mQemuFwCfgDmaSupported && MemEncryptSevIsEnabled ()) { > + EFI_STATUS Status; > + > + // > + // IoMmuDxe driver must have installed the IOMMU protocol. If we are not > + // able to locate the protocol then something must have gone wrong. > + // > + Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmuProtocol); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "QemuwCfgSevDma: failed to locate IOMMU protocol\n")); (1) The word "QemuwCfgSevDma" has a typo, it should be "QemuFwCfgSevDma". Also, I recommend printing gEfiCallerBaseName / __FUNCTION__ here as well. (2) A number of DEBUGs are incorrectly indented below. I'm not comfortable giving my R-b in advance, with those fixed, because my comments on the depex (to be made elsewhere in the series) might induce a change to the depex, and I'd like to review that separately. If it turns out that the v5 depex will be fine, then the above two remarks don't necessitate a v6, and I'll be OK to R-b this v5 patch. Thanks, Laszlo > + ASSERT (FALSE); > + CpuDeadLoop (); > + } > + } > + > return RETURN_SUCCESS; > } > > @@ -114,3 +153,72 @@ InternalQemuFwCfgDmaIsAvailable ( > { > return mQemuFwCfgDmaSupported; > } > + > +/** > + Allocate a bounce buffer for SEV DMA. > + > + @param[in] NumPage Number of pages. > + @param[out] Buffer Allocated DMA Buffer pointer > + > +**/ > +VOID > +InternalQemuFwCfgSevDmaAllocateBuffer ( > + OUT VOID **Buffer, > + IN UINT32 NumPages > + ) > +{ > + EFI_STATUS Status; > + > + ASSERT (mIoMmuProtocol != NULL); > + > + Status = mIoMmuProtocol->AllocateBuffer ( > + mIoMmuProtocol, > + 0, > + EfiBootServicesData, > + NumPages, > + Buffer, > + EDKII_IOMMU_ATTRIBUTE_MEMORY_CACHED > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:%a failed to allocate %u pages\n", gEfiCallerBaseName, > + __FUNCTION__, NumPages)); > + ASSERT (FALSE); > + CpuDeadLoop (); > + } > + > + DEBUG ((DEBUG_VERBOSE, "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName, > + __FUNCTION__, (UINT64)(UINTN)Buffer, NumPages)); > +} > + > +/** > + Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer > + > + @param[in] NumPage Number of pages. > + @param[in] Buffer DMA Buffer pointer > + > +**/ > +VOID > +InternalQemuFwCfgSevDmaFreeBuffer ( > + IN VOID *Buffer, > + IN UINT32 NumPages > + ) > +{ > + EFI_STATUS Status; > + > + ASSERT (mIoMmuProtocol != NULL); > + > + Status = mIoMmuProtocol->FreeBuffer ( > + mIoMmuProtocol, > + NumPages, > + Buffer > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:%a failed to free buffer 0x%Lx pages %u\n", > + gEfiCallerBaseName, __FUNCTION__, (UINT64)(UINTN)Buffer, NumPages)); > + ASSERT (FALSE); > + CpuDeadLoop (); > + } > + > + DEBUG ((DEBUG_VERBOSE, "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName, > + __FUNCTION__, (UINT64)(UINTN)Buffer, NumPages)); > +} > _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.