From: Laszlo Ersek <lersek@redhat.com>
To: Brijesh Singh <brijesh.singh@amd.com>, edk2-devel@lists.01.org
Cc: Tom Lendacky <thomas.lendacky@amd.com>,
Jordan Justen <jordan.l.justen@intel.com>
Subject: Re: [PATCH v3 1/1] OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS
Date: Sat, 5 Aug 2017 03:32:53 +0200 [thread overview]
Message-ID: <606aa163-8564-9275-8477-fe13ecd7afc9@redhat.com> (raw)
In-Reply-To: <1501801872-22626-2-git-send-email-brijesh.singh@amd.com>
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);
> }
> }
next prev parent reply other threads:[~2017-08-05 1:30 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` Laszlo Ersek [this message]
2017-08-04 23:07 ` [PATCH v3 0/1] Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS Laszlo Ersek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=606aa163-8564-9275-8477-fe13ecd7afc9@redhat.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox