* [PATCH v3 0/1] Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS
@ 2017-08-03 23:11 Brijesh Singh
2017-08-03 23:11 ` [PATCH v3 1/1] OvmfPkg/QemuFwCfgLib: " Brijesh Singh
2017-08-04 23:07 ` [PATCH v3 0/1] " Laszlo Ersek
0 siblings, 2 replies; 8+ messages in thread
From: Brijesh Singh @ 2017-08-03 23:11 UTC (permalink / raw)
To: edk2-devel; +Cc: Tom Lendacky, Brijesh Singh
The patch applies on top of Laszlo's IoMmuDxe cleanup series [1].
Commit is also available at https://github.com/codomania/edk2/tree/qemufwcfg-sev
[1] https://lists.01.org/pipermail/edk2-devel/2017-August/012808.html
Changes since v2:
* Changes to address v2 feedbacks.
Changes since v1:
* Drop Patch 1 through 3, they are covered by Laszlo's cleanup series
* Rebase to the latest
Brijesh Singh (1):
OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map
FW_CFG_DMA_ACCESS
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h | 42 +--
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c | 330 ++++++++++++++++----
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c | 130 --------
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c | 99 +++---
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c | 58 +---
5 files changed, 367 insertions(+), 292 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 1/1] OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS
2017-08-03 23:11 [PATCH v3 0/1] Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Brijesh Singh
@ 2017-08-03 23:11 ` Brijesh Singh
2017-08-04 2:47 ` Issue of step by step debugging of OVMF SEC code in QEMU wang xiaofeng
2017-08-05 1:32 ` [PATCH v3 1/1] OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Laszlo Ersek
2017-08-04 23:07 ` [PATCH v3 0/1] " Laszlo Ersek
1 sibling, 2 replies; 8+ messages in thread
From: Brijesh Singh @ 2017-08-03 23:11 UTC (permalink / raw)
To: edk2-devel; +Cc: Tom Lendacky, Brijesh Singh, Jordan Justen, Laszlo Ersek
Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function
for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS
buffer when SEV is active. During initial commits we made assumption that
IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared).
This assumption was wrong, the AllocateBuffer() protocol member is not
expected to produce a buffer that is immediatly usable, and client is
required to call Map() uncondtionally with BusMasterCommonBuffer[64] to
get a mapping which is accessable by both host and device.
The patch refactors code a bit and add the support to Map()
FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after
allocation and Unamp() before free.
The complete discussion about this and recommendation from Laszlo can be
found here [1]
[1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html
Suggested-by: Laszlo Ersek <lersek@redhat.com>
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/QemuFwCfgLibInternal.h | 42 +--
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c | 330 ++++++++++++++++----
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c | 130 --------
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c | 99 +++---
OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c | 58 +---
5 files changed, 367 insertions(+), 292 deletions(-)
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h
index 8cfa7913ffae..327f1d37e17d 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h
@@ -45,39 +45,25 @@ InternalQemuFwCfgDmaIsAvailable (
);
/**
- Returns a boolean indicating whether SEV support is enabled
+ Transfer an array of bytes, or skip a number of bytes, using the DMA
+ interface.
- @retval TRUE SEV is enabled
- @retval FALSE SEV is disabled
-**/
-BOOLEAN
-InternalQemuFwCfgSevIsEnabled (
- VOID
- );
+ @param[in] Size Size in bytes to transfer or skip.
-/**
- Allocate a bounce buffer for SEV DMA.
-
- @param[out] Buffer Allocated DMA Buffer pointer
- @param[in] NumPage Number of pages.
+ @param[in,out] Buffer Buffer to read data into or write data from. Ignored,
+ and may be NULL, if Size is zero, or Control is
+ FW_CFG_DMA_CTL_SKIP.
+ @param[in] Control One of the following:
+ FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
+ FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.
+ FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.
**/
VOID
-InternalQemuFwCfgSevDmaAllocateBuffer (
- OUT VOID **Buffer,
- IN UINT32 NumPages
+InternalQemuFwCfgDmaBytes (
+ IN UINT32 Size,
+ IN OUT VOID *Buffer OPTIONAL,
+ IN UINT32 Control
);
-/**
- 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
- );
#endif
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
index f8eb03bc3a9a..576941749cf2 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
@@ -20,6 +20,7 @@
#include <Protocol/IoMmu.h>
#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
#include <Library/DebugLib.h>
#include <Library/QemuFwCfgLib.h>
#include <Library/UefiBootServicesTableLib.h>
@@ -31,20 +32,6 @@ 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
@@ -110,7 +97,8 @@ QemuFwCfgInitialize (
// 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);
+ Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL,
+ (VOID **)&mIoMmuProtocol);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR,
"QemuFwCfgSevDma %a:%a Failed to locate IOMMU protocol.\n",
@@ -157,74 +145,308 @@ InternalQemuFwCfgDmaIsAvailable (
}
/**
- Allocate a bounce buffer for SEV DMA.
-
- @param[in] NumPage Number of pages.
- @param[out] Buffer Allocated DMA Buffer pointer
+ Function is used for allocating a bi-directional FW_CFG_DMA_ACCESS used
+ between Host and device to exchange the information. The buffer must be free'd
+ using FreeFwCfgDmaAccessBuffer ().
**/
+STATIC
VOID
-InternalQemuFwCfgSevDmaAllocateBuffer (
- OUT VOID **Buffer,
- IN UINT32 NumPages
+AllocFwCfgDmaAccessBuffer (
+ OUT VOID **Access,
+ OUT VOID **MapInfo
)
{
- EFI_STATUS Status;
+ UINTN Size;
+ UINTN NumPages;
+ EFI_STATUS Status;
+ VOID *HostAddress;
+ EFI_PHYSICAL_ADDRESS DmaAddress;
+ VOID *Mapping;
- ASSERT (mIoMmuProtocol != NULL);
+ Size = sizeof (FW_CFG_DMA_ACCESS);
+ NumPages = EFI_SIZE_TO_PAGES (Size);
+ //
+ // As per UEFI spec, in order to map a host address with
+ // BusMasterCommomBuffer64, the buffer must be allocated using the IOMMU
+ // AllocateBuffer()
+ //
Status = mIoMmuProtocol->AllocateBuffer (
- mIoMmuProtocol,
- 0,
- EfiBootServicesData,
- NumPages,
- Buffer,
- EDKII_IOMMU_ATTRIBUTE_MEMORY_CACHED
- );
+ mIoMmuProtocol,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ NumPages,
+ &HostAddress,
+ EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE
+ );
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR,
- "%a:%a failed to allocate %u pages\n", gEfiCallerBaseName, __FUNCTION__,
- NumPages));
+ "%a:%a failed to allocate FW_CFG_DMA_ACCESS\n", gEfiCallerBaseName,
+ __FUNCTION__));
ASSERT (FALSE);
CpuDeadLoop ();
}
- DEBUG ((DEBUG_VERBOSE,
- "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName, __FUNCTION__,
- (UINT64)(UINTN)Buffer, NumPages));
+ //
+ // Map the host buffer with BusMasterCommonBuffer64
+ //
+ Status = mIoMmuProtocol->Map (
+ mIoMmuProtocol,
+ EdkiiIoMmuOperationBusMasterCommonBuffer64,
+ HostAddress,
+ &Size,
+ &DmaAddress,
+ &Mapping
+ );
+ if (EFI_ERROR (Status)) {
+ mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, HostAddress);
+ DEBUG ((DEBUG_ERROR,
+ "%a:%a failed to Map() FW_CFG_DMA_ACCESS\n", gEfiCallerBaseName,
+ __FUNCTION__));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+
+ if (Size < sizeof (FW_CFG_DMA_ACCESS)) {
+ mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping);
+ mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, HostAddress);
+ DEBUG ((DEBUG_ERROR,
+ "%a:%a failed to Map() - requested 0x%Lx got 0x%Lx\n", gEfiCallerBaseName,
+ __FUNCTION__, (UINT64)sizeof (FW_CFG_DMA_ACCESS), (UINT64)Size));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+
+ *Access = HostAddress;
+ *MapInfo = Mapping;
}
/**
- Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer
+ Function is to used for freeing the Access buffer allocated using
+ AllocFwCfgDmaAccessBuffer()
+
+**/
+STATIC
+VOID
+FreeFwCfgDmaAccessBuffer (
+ IN VOID *Access,
+ IN VOID *Mapping
+ )
+{
+ UINTN NumPages;
+ EFI_STATUS Status;
+
+ NumPages = EFI_SIZE_TO_PAGES (sizeof (FW_CFG_DMA_ACCESS));
+
+ Status = mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,
+ "%a:%a failed to UnMap() Mapping 0x%Lx\n", gEfiCallerBaseName,
+ __FUNCTION__, (UINT64)Mapping));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
- @param[in] NumPage Number of pages.
- @param[in] Buffer DMA Buffer pointer
+ Status = mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, Access);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,
+ "%a:%a failed to Free() 0x%Lx\n", gEfiCallerBaseName, __FUNCTION__,
+ (UINT64) Access));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+}
+
+/**
+ Function is used for mapping host address to device address. The buffer must
+ be unmapped with UnmapDmaDataBuffer ().
**/
+STATIC
VOID
-InternalQemuFwCfgSevDmaFreeBuffer (
- IN VOID *Buffer,
- IN UINT32 NumPages
+MapFwCfgDmaDataBuffer (
+ IN BOOLEAN IsWrite,
+ IN VOID *HostAddress,
+ IN UINT32 Size,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **MapInfo
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ UINTN NumberOfBytes;
+ VOID *Mapping;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+
+ NumberOfBytes = Size;
+ Status = mIoMmuProtocol->Map (
+ mIoMmuProtocol,
+ (IsWrite ?
+ EdkiiIoMmuOperationBusMasterRead64 :
+ EdkiiIoMmuOperationBusMasterWrite64),
+ HostAddress,
+ &NumberOfBytes,
+ &PhysicalAddress,
+ &Mapping
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,
+ "%a:%a failed to Map() Address 0x%Lx Size 0x%Lx\n", gEfiCallerBaseName,
+ __FUNCTION__, (UINT64) HostAddress, (UINT64)Size));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+
+ if (NumberOfBytes < Size) {
+ mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping);
+ DEBUG ((DEBUG_ERROR,
+ "%a:%a failed to Map() - requested 0x%x got 0x%Lx\n", gEfiCallerBaseName,
+ __FUNCTION__, Size, (UINT64)NumberOfBytes));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+
+ *DeviceAddress = PhysicalAddress;
+ *MapInfo = Mapping;
+}
- ASSERT (mIoMmuProtocol != NULL);
+STATIC
+VOID
+UnmapFwCfgDmaDataBuffer (
+ IN VOID *Mapping
+ )
+{
+ EFI_STATUS Status;
- Status = mIoMmuProtocol->FreeBuffer (
- mIoMmuProtocol,
- NumPages,
- Buffer
- );
+ Status = mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR,
- "%a:%a failed to free buffer 0x%Lx pages %u\n", gEfiCallerBaseName,
- __FUNCTION__, (UINT64)(UINTN)Buffer, NumPages));
+ "%a:%a failed to UnMap() Mapping 0x%Lx\n", gEfiCallerBaseName,
+ __FUNCTION__, (UINT64)Mapping));
ASSERT (FALSE);
CpuDeadLoop ();
}
+}
+
+/**
+ Transfer an array of bytes, or skip a number of bytes, using the DMA
+ interface.
+
+ @param[in] Size Size in bytes to transfer or skip.
+
+ @param[in,out] Buffer Buffer to read data into or write data from. Ignored,
+ and may be NULL, if Size is zero, or Control is
+ FW_CFG_DMA_CTL_SKIP.
+
+ @param[in] Control One of the following:
+ FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
+ FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.
+ FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.
+**/
+VOID
+InternalQemuFwCfgDmaBytes (
+ IN UINT32 Size,
+ IN OUT VOID *Buffer OPTIONAL,
+ IN UINT32 Control
+ )
+{
+ volatile FW_CFG_DMA_ACCESS LocalAccess;
+ volatile FW_CFG_DMA_ACCESS *Access;
+ UINT32 AccessHigh, AccessLow;
+ UINT32 Status;
+ VOID *AccessMapping, *DataMapping;
+ VOID *DataBuffer;
+
+ ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ ||
+ Control == FW_CFG_DMA_CTL_SKIP);
+
+ if (Size == 0) {
+ return;
+ }
+
+ Access = &LocalAccess;
+ AccessMapping = NULL;
+ DataMapping = NULL;
+ DataBuffer = Buffer;
+
+ //
+ // When SEV is enabled, map Buffer to DMA address before issuing the DMA
+ // request
+ //
+ if (MemEncryptSevIsEnabled ()) {
+ VOID *AccessBuffer;
+ EFI_PHYSICAL_ADDRESS DataBufferAddress;
+
+ //
+ // Allocate DMA Access buffer
+ //
+ AllocFwCfgDmaAccessBuffer (&AccessBuffer, &AccessMapping);
+
+ Access = AccessBuffer;
+
+ //
+ // Map actual data buffer
+ //
+ if (Control != FW_CFG_DMA_CTL_SKIP) {
+ MapFwCfgDmaDataBuffer (
+ Control == FW_CFG_DMA_CTL_WRITE,
+ Buffer,
+ Size,
+ &DataBufferAddress,
+ &DataMapping
+ );
+
+ DataBuffer = (VOID *) (UINTN) DataBufferAddress;
+ }
+ }
- DEBUG ((DEBUG_VERBOSE,
- "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName,__FUNCTION__,
- (UINT64)(UINTN)Buffer, NumPages));
+ Access->Control = SwapBytes32 (Control);
+ Access->Length = SwapBytes32 (Size);
+ Access->Address = SwapBytes64 ((UINTN)DataBuffer);
+
+ //
+ // Delimit the transfer from (a) modifications to Access, (b) in case of a
+ // write, from writes to Buffer by the caller.
+ //
+ MemoryFence ();
+
+ //
+ // Start the transfer.
+ //
+ AccessHigh = (UINT32)RShiftU64 ((UINTN)Access, 32);
+ AccessLow = (UINT32)(UINTN)Access;
+ IoWrite32 (FW_CFG_IO_DMA_ADDRESS, SwapBytes32 (AccessHigh));
+ IoWrite32 (FW_CFG_IO_DMA_ADDRESS + 4, SwapBytes32 (AccessLow));
+
+ //
+ // Don't look at Access.Control before starting the transfer.
+ //
+ MemoryFence ();
+
+ //
+ // Wait for the transfer to complete.
+ //
+ do {
+ Status = SwapBytes32 (Access->Control);
+ ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);
+ } while (Status != 0);
+
+ //
+ // After a read, the caller will want to use Buffer.
+ //
+ MemoryFence ();
+
+ //
+ // If Access buffer was dynamically allocated then free it.
+ //
+ if (AccessMapping) {
+ FreeFwCfgDmaAccessBuffer ((VOID *)Access, AccessMapping);
+ }
+
+ //
+ // If DataBuffer was mapped then unmap it.
+ //
+ if (DataMapping) {
+ UnmapFwCfgDmaDataBuffer (DataMapping);
+ }
}
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
index d3bf75498d60..7f42f38d1c05 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
@@ -45,136 +45,6 @@ QemuFwCfgSelectItem (
IoWrite16 (FW_CFG_IO_SELECTOR, (UINT16)(UINTN) QemuFwCfgItem);
}
-
-/**
- Transfer an array of bytes, or skip a number of bytes, using the DMA
- interface.
-
- @param[in] Size Size in bytes to transfer or skip.
-
- @param[in,out] Buffer Buffer to read data into or write data from. Ignored,
- and may be NULL, if Size is zero, or Control is
- FW_CFG_DMA_CTL_SKIP.
-
- @param[in] Control One of the following:
- FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
- FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.
- FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.
-**/
-VOID
-InternalQemuFwCfgDmaBytes (
- IN UINT32 Size,
- IN OUT VOID *Buffer OPTIONAL,
- IN UINT32 Control
- )
-{
- volatile FW_CFG_DMA_ACCESS LocalAccess;
- volatile FW_CFG_DMA_ACCESS *Access;
- UINT32 AccessHigh, AccessLow;
- UINT32 Status;
- UINT32 NumPages;
- VOID *DmaBuffer, *BounceBuffer;
-
- ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ ||
- Control == FW_CFG_DMA_CTL_SKIP);
-
- if (Size == 0) {
- return;
- }
-
- //
- // set NumPages to suppress incorrect compiler/analyzer warnings
- //
- NumPages = 0;
-
- //
- // When SEV is enabled then allocate DMA bounce buffer
- //
- if (InternalQemuFwCfgSevIsEnabled ()) {
- UINTN TotalSize;
-
- TotalSize = sizeof (*Access);
- //
- // Skip operation does not need buffer
- //
- if (Control != FW_CFG_DMA_CTL_SKIP) {
- TotalSize += Size;
- }
-
- //
- // Allocate SEV DMA buffer
- //
- NumPages = (UINT32)EFI_SIZE_TO_PAGES (TotalSize);
- InternalQemuFwCfgSevDmaAllocateBuffer (&BounceBuffer, NumPages);
-
- Access = BounceBuffer;
- DmaBuffer = (UINT8*)BounceBuffer + sizeof (*Access);
-
- //
- // Decrypt data from encrypted guest buffer into DMA buffer
- //
- if (Control == FW_CFG_DMA_CTL_WRITE) {
- CopyMem (DmaBuffer, Buffer, Size);
- }
- } else {
- Access = &LocalAccess;
- DmaBuffer = Buffer;
- BounceBuffer = NULL;
- }
-
- Access->Control = SwapBytes32 (Control);
- Access->Length = SwapBytes32 (Size);
- Access->Address = SwapBytes64 ((UINTN)DmaBuffer);
-
- //
- // Delimit the transfer from (a) modifications to Access, (b) in case of a
- // write, from writes to Buffer by the caller.
- //
- MemoryFence ();
-
- //
- // Start the transfer.
- //
- AccessHigh = (UINT32)RShiftU64 ((UINTN)Access, 32);
- AccessLow = (UINT32)(UINTN)Access;
- IoWrite32 (FW_CFG_IO_DMA_ADDRESS, SwapBytes32 (AccessHigh));
- IoWrite32 (FW_CFG_IO_DMA_ADDRESS + 4, SwapBytes32 (AccessLow));
-
- //
- // Don't look at Access.Control before starting the transfer.
- //
- MemoryFence ();
-
- //
- // Wait for the transfer to complete.
- //
- do {
- Status = SwapBytes32 (Access->Control);
- ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);
- } while (Status != 0);
-
- //
- // After a read, the caller will want to use Buffer.
- //
- MemoryFence ();
-
- //
- // If Bounce buffer was allocated then copy the data into guest buffer and
- // free the bounce buffer
- //
- if (BounceBuffer != NULL) {
- //
- // Encrypt the data from DMA buffer into guest buffer
- //
- if (Control == FW_CFG_DMA_CTL_READ) {
- CopyMem (Buffer, DmaBuffer, Size);
- }
-
- InternalQemuFwCfgSevDmaFreeBuffer (BounceBuffer, NumPages);
- }
-}
-
-
/**
Reads firmware configuration bytes into a buffer
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
index 40f89c3b53e2..471ab0335e64 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
@@ -16,6 +16,7 @@
**/
#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
#include <Library/DebugLib.h>
#include <Library/QemuFwCfgLib.h>
#include <Library/MemEncryptSevLib.h>
@@ -85,7 +86,7 @@ QemuFwCfgInitialize (
// (which need to allocate dynamic memory and allocating a PAGE size'd
// buffer can be challenge in PEI phase)
//
- if (InternalQemuFwCfgSevIsEnabled ()) {
+ if (MemEncryptSevIsEnabled ()) {
DEBUG ((DEBUG_INFO, "SEV: QemuFwCfg fallback to IO Port interface.\n"));
} else {
mQemuFwCfgDmaSupported = TRUE;
@@ -129,56 +130,78 @@ InternalQemuFwCfgDmaIsAvailable (
}
/**
+ Transfer an array of bytes, or skip a number of bytes, using the DMA
+ interface.
- Returns a boolean indicating whether SEV is enabled
+ @param[in] Size Size in bytes to transfer or skip.
- @retval TRUE SEV is enabled
- @retval FALSE SEV is disabled
+ @param[in,out] Buffer Buffer to read data into or write data from. Ignored,
+ and may be NULL, if Size is zero, or Control is
+ FW_CFG_DMA_CTL_SKIP.
+
+ @param[in] Control One of the following:
+ FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
+ FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.
+ FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.
**/
-BOOLEAN
-InternalQemuFwCfgSevIsEnabled (
- VOID
+VOID
+InternalQemuFwCfgDmaBytes (
+ IN UINT32 Size,
+ IN OUT VOID *Buffer OPTIONAL,
+ IN UINT32 Control
)
{
- return MemEncryptSevIsEnabled ();
-}
+ volatile FW_CFG_DMA_ACCESS Access;
+ UINT32 AccessHigh, AccessLow;
+ UINT32 Status;
-/**
- Allocate a bounce buffer for SEV DMA.
+ ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ ||
+ Control == FW_CFG_DMA_CTL_SKIP);
- @param[in] NumPage Number of pages.
- @param[out] Buffer Allocated DMA Buffer pointer
+ if (Size == 0) {
+ return;
+ }
-**/
-VOID
-InternalQemuFwCfgSevDmaAllocateBuffer (
- OUT VOID **Buffer,
- IN UINT32 NumPages
- )
-{
//
- // We should never reach here
+ // SEV does not support DMA operations in PEI stage, we should
+ // not have reached here.
//
- ASSERT (FALSE);
- CpuDeadLoop ();
-}
+ ASSERT (!MemEncryptSevIsEnabled ());
-/**
- Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer
+ Access.Control = SwapBytes32 (Control);
+ Access.Length = SwapBytes32 (Size);
+ Access.Address = SwapBytes64 ((UINTN)Buffer);
- @param[in] NumPage Number of pages.
- @param[in] Buffer DMA Buffer pointer
+ //
+ // Delimit the transfer from (a) modifications to Access, (b) in case of a
+ // write, from writes to Buffer by the caller.
+ //
+ MemoryFence ();
-**/
-VOID
-InternalQemuFwCfgSevDmaFreeBuffer (
- IN VOID *Buffer,
- IN UINT32 NumPages
- )
-{
//
- // We should never reach here
+ // Start the transfer.
+ //
+ AccessHigh = (UINT32)RShiftU64 ((UINTN)&Access, 32);
+ AccessLow = (UINT32)(UINTN)&Access;
+ IoWrite32 (FW_CFG_IO_DMA_ADDRESS, SwapBytes32 (AccessHigh));
+ IoWrite32 (FW_CFG_IO_DMA_ADDRESS + 4, SwapBytes32 (AccessLow));
+
+ //
+ // Don't look at Access.Control before starting the transfer.
+ //
+ MemoryFence ();
+
+ //
+ // Wait for the transfer to complete.
+ //
+ do {
+ Status = SwapBytes32 (Access.Control);
+ ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);
+ } while (Status != 0);
+
+ //
+ // After a read, the caller will want to use Buffer.
//
- ASSERT (FALSE);
- CpuDeadLoop ();
+ MemoryFence ();
}
+
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c
index 071b8d9b91d4..1eadba99e1b3 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c
@@ -17,6 +17,7 @@
WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
+#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/QemuFwCfgLib.h>
@@ -97,57 +98,30 @@ InternalQemuFwCfgDmaIsAvailable (
}
/**
+ Transfer an array of bytes, or skip a number of bytes, using the DMA
+ interface.
- Returns a boolean indicating whether SEV is enabled
+ @param[in] Size Size in bytes to transfer or skip.
- @retval TRUE SEV is enabled
- @retval FALSE SEV is disabled
-**/
-BOOLEAN
-InternalQemuFwCfgSevIsEnabled (
- VOID
- )
-{
- //
- // DMA is not supported in SEC phase hence SEV support is irrelevant
- //
- return FALSE;
-}
-
-/**
- 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
- )
-{
- //
- // We should never reach here
- //
- ASSERT (FALSE);
-}
-
-/**
- Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer
-
- @param[in] NumPage Number of pages.
- @param[in] Buffer DMA Buffer pointer
+ @param[in,out] Buffer Buffer to read data into or write data from. Ignored,
+ and may be NULL, if Size is zero, or Control is
+ FW_CFG_DMA_CTL_SKIP.
+ @param[in] Control One of the following:
+ FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
+ FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.
+ FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.
**/
VOID
-InternalQemuFwCfgSevDmaFreeBuffer (
- IN VOID *Buffer,
- IN UINT32 NumPages
+InternalQemuFwCfgDmaBytes (
+ IN UINT32 Size,
+ IN OUT VOID *Buffer OPTIONAL,
+ IN UINT32 Control
)
{
//
// We should never reach here
//
ASSERT (FALSE);
+ CpuDeadLoop ();
}
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Issue of step by step debugging of OVMF SEC code in QEMU
2017-08-03 23:11 ` [PATCH v3 1/1] OvmfPkg/QemuFwCfgLib: " Brijesh Singh
@ 2017-08-04 2:47 ` wang xiaofeng
[not found] ` <14E6BF08-E850-4DBD-BA6E-EE1ED90B97AA@apple.com>
2017-08-05 1:32 ` [PATCH v3 1/1] OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Laszlo Ersek
1 sibling, 1 reply; 8+ messages in thread
From: wang xiaofeng @ 2017-08-04 2:47 UTC (permalink / raw)
To: edk2-devel
Hello,
I am tring to add my own SEC code base on OVMF and run on QEMU. Since the code cannot run I need to step to step trace the assembly code .
The hang point is very early before I can use either UDK or debug serial output. I tried to use gdb to connect to QEMU.I start gdb in another terminal, and issue the following commands:
(gdb) set architecture i386:x86-64:intel
(gdb) target remote localhost:1234
It really stops at the bios first instruction at 0XFFFFFFF0. But gdb shows eip= 0xFFF0 and CS=0xF000(why it not be 0xfff0). After I trigger the command "display /i $pc"
It shows the assembly code in 0xFFF0 instead of 0XFFFFFFF0, so the information is incorrect.
Anyone knows how to corrently debug the SEC code ? Other debug tool is also ok.
Thanks in advance!
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Issue of step by step debugging of OVMF SEC code in QEMU
[not found] ` <14E6BF08-E850-4DBD-BA6E-EE1ED90B97AA@apple.com>
@ 2017-08-04 3:26 ` wang xiaofeng
2017-08-04 3:41 ` wang xiaofeng
0 siblings, 1 reply; 8+ messages in thread
From: wang xiaofeng @ 2017-08-04 3:26 UTC (permalink / raw)
To: Andrew Fish; +Cc: edk2-devel
HI Andrew,
How can I adjust the debugger to correct mode? Or I have to enable the debug after swtich to protected mode?
At 2017-08-04 10:57:16, "Andrew Fish" <afish@apple.com> wrote:
>The reset vector is 16-bit real mode, so you have the debugger in the wrong mode. The code should transition to 32 bit protected early in the flow.
>
>Sent from my iPhone
>
>> On Aug 3, 2017, at 7:47 PM, wang xiaofeng <winggundum82@163.com> wrote:
>>
>> Hello,
>> I am tring to add my own SEC code base on OVMF and run on QEMU. Since the code cannot run I need to step to step trace the assembly code .
>> The hang point is very early before I can use either UDK or debug serial output. I tried to use gdb to connect to QEMU.I start gdb in another terminal, and issue the following commands:
>> (gdb) set architecture i386:x86-64:intel
>> (gdb) target remote localhost:1234
>> It really stops at the bios first instruction at 0XFFFFFFF0. But gdb shows eip= 0xFFF0 and CS=0xF000(why it not be 0xfff0). After I trigger the command "display /i $pc"
>> It shows the assembly code in 0xFFF0 instead of 0XFFFFFFF0, so the information is incorrect.
>> Anyone knows how to corrently debug the SEC code ? Other debug tool is also ok.
>> Thanks in advance!
>>
>>
>>
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel
>_______________________________________________
>edk2-devel mailing list
>edk2-devel@lists.01.org
>https://lists.01.org/mailman/listinfo/edk2-devel
\x16�&
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Issue of step by step debugging of OVMF SEC code in QEMU
2017-08-04 3:26 ` wang xiaofeng
@ 2017-08-04 3:41 ` wang xiaofeng
2017-08-04 4:35 ` Andrew Fish
0 siblings, 1 reply; 8+ messages in thread
From: wang xiaofeng @ 2017-08-04 3:41 UTC (permalink / raw)
To: wang xiaofeng; +Cc: Andrew Fish, edk2-devel
Hi Andrew,
THe problem is solved, after the SEC code switch to protected mode, gdb can work well now
At 2017-08-04 11:26:16, "wang xiaofeng" <winggundum82@163.com> wrote:
HI Andrew,
How can I adjust the debugger to correct mode? Or I have to enable the debug after swtich to protected mode?
At 2017-08-04 10:57:16, "Andrew Fish" <afish@apple.com> wrote:
>The reset vector is 16-bit real mode, so you have the debugger in the wrong mode. The code should transition to 32 bit protected early in the flow.
>
>Sent from my iPhone
>
>> On Aug 3, 2017, at 7:47 PM, wang xiaofeng <winggundum82@163.com> wrote:
>>
>> Hello,
>> I am tring to add my own SEC code base on OVMF and run on QEMU. Since the code cannot run I need to step to step trace the assembly code .
>> The hang point is very early before I can use either UDK or debug serial output. I tried to use gdb to connect to QEMU.I start gdb in another terminal, and issue the following commands:
>> (gdb) set architecture i386:x86-64:intel
>> (gdb) target remote localhost:1234
>> It really stops at the bios first instruction at 0XFFFFFFF0. But gdb shows eip= 0xFFF0 and CS=0xF000(why it not be 0xfff0). After I trigger the command "display /i $pc"
>> It shows the assembly code in 0xFFF0 instead of 0XFFFFFFF0, so the information is incorrect.
>> Anyone knows how to corrently debug the SEC code ? Other debug tool is also ok.
>> Thanks in advance!
>>
>>
>>
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel
>_______________________________________________
>edk2-devel mailing list
>edk2-devel@lists.01.org
>https://lists.01.org/mailman/listinfo/edk2-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Issue of step by step debugging of OVMF SEC code in QEMU
2017-08-04 3:41 ` wang xiaofeng
@ 2017-08-04 4:35 ` Andrew Fish
0 siblings, 0 replies; 8+ messages in thread
From: Andrew Fish @ 2017-08-04 4:35 UTC (permalink / raw)
To: wang xiaofeng; +Cc: edk2-devel
It is generally hard to debug across x86 processor mode transitions, and to debug 16-bit real mode code with modern tools. There are a few places in the x86 that still require 16-bit real mode for handoffs (like the reset vector) so you tend to hit this issue more in debugging firmware.
Thanks,
Andrew Fish
> On Aug 3, 2017, at 8:41 PM, wang xiaofeng <winggundum82@163.com> wrote:
>
> Hi Andrew,
> THe problem is solved, after the SEC code switch to protected mode, gdb can work well now
>
>
>
>
>
>
> At 2017-08-04 11:26:16, "wang xiaofeng" <winggundum82@163.com> wrote:
> HI Andrew,
> How can I adjust the debugger to correct mode? Or I have to enable the debug after swtich to protected mode?
>
>
>
>
>
>
> At 2017-08-04 10:57:16, "Andrew Fish" <afish@apple.com <mailto:afish@apple.com>> wrote:
> >The reset vector is 16-bit real mode, so you have the debugger in the wrong mode. The code should transition to 32 bit protected early in the flow.
> >
> >Sent from my iPhone
> >
> >> On Aug 3, 2017, at 7:47 PM, wang xiaofeng <winggundum82@163.com <mailto:winggundum82@163.com>> wrote:
> >>
> >> Hello,
> >> I am tring to add my own SEC code base on OVMF and run on QEMU. Since the code cannot run I need to step to step trace the assembly code .
> >> The hang point is very early before I can use either UDK or debug serial output. I tried to use gdb to connect to QEMU.I start gdb in another terminal, and issue the following commands:
> >> (gdb) set architecture i386:x86-64:intel
> >> (gdb) target remote localhost:1234
> >> It really stops at the bios first instruction at 0XFFFFFFF0. But gdb shows eip= 0xFFF0 and CS=0xF000(why it not be 0xfff0). After I trigger the command "display /i $pc"
> >> It shows the assembly code in 0xFFF0 instead of 0XFFFFFFF0, so the information is incorrect.
> >> Anyone knows how to corrently debug the SEC code ? Other debug tool is also ok.
> >> Thanks in advance!
> >>
> >>
> >>
> >> _______________________________________________
> >> edk2-devel mailing list
> >> edk2-devel@lists.01.org <mailto:edk2-devel@lists.01.org>
> >> https://lists.01.org/mailman/listinfo/edk2-devel
> >_______________________________________________
> >edk2-devel mailing list
> >edk2-devel@lists.01.org <mailto:edk2-devel@lists.01.org>
> >https://lists.01.org/mailman/listinfo/edk2-devel
>
>
>
>
>
> 【网易自营|30天无忧退货】不到同款1折价!Tory Burch制造商美式休闲人字拖限时仅29.9元>> <http://you.163.com/item/detail?id=1185012&from=web_gg_mail_jiaobiao_9>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 0/1] Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS
2017-08-03 23:11 [PATCH v3 0/1] Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Brijesh Singh
2017-08-03 23:11 ` [PATCH v3 1/1] OvmfPkg/QemuFwCfgLib: " Brijesh Singh
@ 2017-08-04 23:07 ` Laszlo Ersek
1 sibling, 0 replies; 8+ messages in thread
From: Laszlo Ersek @ 2017-08-04 23:07 UTC (permalink / raw)
To: Brijesh Singh, edk2-devel; +Cc: Tom Lendacky
Hi Brijesh,
On 08/04/17 01:11, Brijesh Singh wrote:
> The patch applies on top of Laszlo's IoMmuDxe cleanup series [1].
>
> Commit is also available at https://github.com/codomania/edk2/tree/qemufwcfg-sev
when pushing a new version of a series, it is best to include the
version number in the branch name, so that the branches of the old
versions are not disturbed.
(No need to do anything about it right now, just saying for the future.)
Thanks,
Laszlo
>
> [1] https://lists.01.org/pipermail/edk2-devel/2017-August/012808.html
>
> Changes since v2:
> * Changes to address v2 feedbacks.
>
> Changes since v1:
> * Drop Patch 1 through 3, they are covered by Laszlo's cleanup series
> * Rebase to the latest
>
> Brijesh Singh (1):
> OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map
> FW_CFG_DMA_ACCESS
>
> OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h | 42 +--
> OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c | 330 ++++++++++++++++----
> OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c | 130 --------
> OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c | 99 +++---
> OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c | 58 +---
> 5 files changed, 367 insertions(+), 292 deletions(-)
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/1] OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS
2017-08-03 23:11 ` [PATCH v3 1/1] OvmfPkg/QemuFwCfgLib: " Brijesh Singh
2017-08-04 2:47 ` Issue of step by step debugging of OVMF SEC code in QEMU wang xiaofeng
@ 2017-08-05 1:32 ` Laszlo Ersek
1 sibling, 0 replies; 8+ messages in thread
From: Laszlo Ersek @ 2017-08-05 1:32 UTC (permalink / raw)
To: Brijesh Singh, edk2-devel; +Cc: Tom Lendacky, Jordan Justen
On 08/04/17 01:11, Brijesh Singh wrote:
> Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function
> for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS
> buffer when SEV is active. During initial commits we made assumption that
> IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared).
> This assumption was wrong, the AllocateBuffer() protocol member is not
> expected to produce a buffer that is immediatly usable, and client is
> required to call Map() uncondtionally with BusMasterCommonBuffer[64] to
> get a mapping which is accessable by both host and device.
>
> The patch refactors code a bit and add the support to Map()
> FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after
> allocation and Unamp() before free.
>
> The complete discussion about this and recommendation from Laszlo can be
> found here [1]
>
> [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html
>
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
For the future: please use version 1.1 of the agreement:
https://github.com/tianocore/edk2/commit/b6538c118ae8
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h | 42 +--
> OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c | 330 ++++++++++++++++----
> OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c | 130 --------
> OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c | 99 +++---
> OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c | 58 +---
> 5 files changed, 367 insertions(+), 292 deletions(-)
>
[lersek@redhat.com: convert pointers to UINTN before converting to UINT64]
[lersek@redhat.com: fix argument indentation in multi-line function call]
[lersek@redhat.com: explicitly compare pointers to NULL]
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Pushed as commit f6c909ae5d65.
(See the fixups below, formatted with function context for easier
understanding.)
Thanks
Laszlo
> diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
> index 576941749cf2..8b98208591e6 100644
> --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
> +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
> @@ -232,34 +232,34 @@ VOID
> FreeFwCfgDmaAccessBuffer (
> IN VOID *Access,
> IN VOID *Mapping
> )
> {
> UINTN NumPages;
> EFI_STATUS Status;
>
> NumPages = EFI_SIZE_TO_PAGES (sizeof (FW_CFG_DMA_ACCESS));
>
> Status = mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping);
> if (EFI_ERROR (Status)) {
> DEBUG ((DEBUG_ERROR,
> "%a:%a failed to UnMap() Mapping 0x%Lx\n", gEfiCallerBaseName,
> - __FUNCTION__, (UINT64)Mapping));
> + __FUNCTION__, (UINT64)(UINTN)Mapping));
> ASSERT (FALSE);
> CpuDeadLoop ();
> }
>
> Status = mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, Access);
> if (EFI_ERROR (Status)) {
> DEBUG ((DEBUG_ERROR,
> "%a:%a failed to Free() 0x%Lx\n", gEfiCallerBaseName, __FUNCTION__,
> - (UINT64) Access));
> + (UINT64)(UINTN)Access));
> ASSERT (FALSE);
> CpuDeadLoop ();
> }
> }
>
> /**
> Function is used for mapping host address to device address. The buffer must
> be unmapped with UnmapDmaDataBuffer ().
>
> **/
> @@ -268,44 +268,44 @@ VOID
> MapFwCfgDmaDataBuffer (
> IN BOOLEAN IsWrite,
> IN VOID *HostAddress,
> IN UINT32 Size,
> OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
> OUT VOID **MapInfo
> )
> {
> EFI_STATUS Status;
> UINTN NumberOfBytes;
> VOID *Mapping;
> EFI_PHYSICAL_ADDRESS PhysicalAddress;
>
> NumberOfBytes = Size;
> Status = mIoMmuProtocol->Map (
> mIoMmuProtocol,
> (IsWrite ?
> EdkiiIoMmuOperationBusMasterRead64 :
> EdkiiIoMmuOperationBusMasterWrite64),
> HostAddress,
> &NumberOfBytes,
> &PhysicalAddress,
> &Mapping
> );
> if (EFI_ERROR (Status)) {
> DEBUG ((DEBUG_ERROR,
> "%a:%a failed to Map() Address 0x%Lx Size 0x%Lx\n", gEfiCallerBaseName,
> - __FUNCTION__, (UINT64) HostAddress, (UINT64)Size));
> + __FUNCTION__, (UINT64)(UINTN)HostAddress, (UINT64)Size));
> ASSERT (FALSE);
> CpuDeadLoop ();
> }
>
> if (NumberOfBytes < Size) {
> mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping);
> DEBUG ((DEBUG_ERROR,
> "%a:%a failed to Map() - requested 0x%x got 0x%Lx\n", gEfiCallerBaseName,
> __FUNCTION__, Size, (UINT64)NumberOfBytes));
> ASSERT (FALSE);
> CpuDeadLoop ();
> }
>
> *DeviceAddress = PhysicalAddress;
> *MapInfo = Mapping;
> }
> @@ -315,31 +315,31 @@ VOID
> UnmapFwCfgDmaDataBuffer (
> IN VOID *Mapping
> )
> {
> EFI_STATUS Status;
>
> Status = mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping);
> if (EFI_ERROR (Status)) {
> DEBUG ((DEBUG_ERROR,
> "%a:%a failed to UnMap() Mapping 0x%Lx\n", gEfiCallerBaseName,
> - __FUNCTION__, (UINT64)Mapping));
> + __FUNCTION__, (UINT64)(UINTN)Mapping));
> ASSERT (FALSE);
> CpuDeadLoop ();
> }
> }
>
> /**
> Transfer an array of bytes, or skip a number of bytes, using the DMA
> interface.
>
> @param[in] Size Size in bytes to transfer or skip.
>
> @param[in,out] Buffer Buffer to read data into or write data from. Ignored,
> and may be NULL, if Size is zero, or Control is
> FW_CFG_DMA_CTL_SKIP.
>
> @param[in] Control One of the following:
> FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
> FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.
> FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.
> **/
> @@ -347,106 +347,106 @@ VOID
> InternalQemuFwCfgDmaBytes (
> IN UINT32 Size,
> IN OUT VOID *Buffer OPTIONAL,
> IN UINT32 Control
> )
> {
> volatile FW_CFG_DMA_ACCESS LocalAccess;
> volatile FW_CFG_DMA_ACCESS *Access;
> UINT32 AccessHigh, AccessLow;
> UINT32 Status;
> VOID *AccessMapping, *DataMapping;
> VOID *DataBuffer;
>
> ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ ||
> Control == FW_CFG_DMA_CTL_SKIP);
>
> if (Size == 0) {
> return;
> }
>
> Access = &LocalAccess;
> AccessMapping = NULL;
> DataMapping = NULL;
> DataBuffer = Buffer;
>
> //
> // When SEV is enabled, map Buffer to DMA address before issuing the DMA
> // request
> //
> if (MemEncryptSevIsEnabled ()) {
> VOID *AccessBuffer;
> EFI_PHYSICAL_ADDRESS DataBufferAddress;
>
> //
> // Allocate DMA Access buffer
> //
> AllocFwCfgDmaAccessBuffer (&AccessBuffer, &AccessMapping);
>
> Access = AccessBuffer;
>
> //
> // Map actual data buffer
> //
> if (Control != FW_CFG_DMA_CTL_SKIP) {
> MapFwCfgDmaDataBuffer (
> - Control == FW_CFG_DMA_CTL_WRITE,
> - Buffer,
> - Size,
> - &DataBufferAddress,
> - &DataMapping
> - );
> + Control == FW_CFG_DMA_CTL_WRITE,
> + Buffer,
> + Size,
> + &DataBufferAddress,
> + &DataMapping
> + );
>
> DataBuffer = (VOID *) (UINTN) DataBufferAddress;
> }
> }
>
> Access->Control = SwapBytes32 (Control);
> Access->Length = SwapBytes32 (Size);
> Access->Address = SwapBytes64 ((UINTN)DataBuffer);
>
> //
> // Delimit the transfer from (a) modifications to Access, (b) in case of a
> // write, from writes to Buffer by the caller.
> //
> MemoryFence ();
>
> //
> // Start the transfer.
> //
> AccessHigh = (UINT32)RShiftU64 ((UINTN)Access, 32);
> AccessLow = (UINT32)(UINTN)Access;
> IoWrite32 (FW_CFG_IO_DMA_ADDRESS, SwapBytes32 (AccessHigh));
> IoWrite32 (FW_CFG_IO_DMA_ADDRESS + 4, SwapBytes32 (AccessLow));
>
> //
> // Don't look at Access.Control before starting the transfer.
> //
> MemoryFence ();
>
> //
> // Wait for the transfer to complete.
> //
> do {
> Status = SwapBytes32 (Access->Control);
> ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);
> } while (Status != 0);
>
> //
> // After a read, the caller will want to use Buffer.
> //
> MemoryFence ();
>
> //
> // If Access buffer was dynamically allocated then free it.
> //
> - if (AccessMapping) {
> + if (AccessMapping != NULL) {
> FreeFwCfgDmaAccessBuffer ((VOID *)Access, AccessMapping);
> }
>
> //
> // If DataBuffer was mapped then unmap it.
> //
> - if (DataMapping) {
> + if (DataMapping != NULL) {
> UnmapFwCfgDmaDataBuffer (DataMapping);
> }
> }
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2017-08-05 1:30 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-08-03 23:11 [PATCH v3 0/1] Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Brijesh Singh
2017-08-03 23:11 ` [PATCH v3 1/1] OvmfPkg/QemuFwCfgLib: " Brijesh Singh
2017-08-04 2:47 ` Issue of step by step debugging of OVMF SEC code in QEMU wang xiaofeng
[not found] ` <14E6BF08-E850-4DBD-BA6E-EE1ED90B97AA@apple.com>
2017-08-04 3:26 ` wang xiaofeng
2017-08-04 3:41 ` wang xiaofeng
2017-08-04 4:35 ` Andrew Fish
2017-08-05 1:32 ` [PATCH v3 1/1] OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Laszlo Ersek
2017-08-04 23:07 ` [PATCH v3 0/1] " Laszlo Ersek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox