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 <[email protected]> > Cc: Jordan Justen <[email protected]> > Cc: Laszlo Ersek <[email protected]> > 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 <[email protected]> > --- > 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(-) > [[email protected]: convert pointers to UINTN before converting to UINT64] [[email protected]: fix argument indentation in multi-line function call] [[email protected]: explicitly compare pointers to NULL] Reviewed-by: Laszlo Ersek <[email protected]> Regression-tested-by: Laszlo Ersek <[email protected]> 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); > } > } _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

