From: Laszlo Ersek <lersek@redhat.com>
To: Brijesh Singh <brijesh.singh@amd.com>, edk2-devel@lists.01.org
Cc: Jordan Justen <jordan.l.justen@intel.com>,
Tom Lendacky <thomas.lendacky@amd.com>,
Ard Biesheuvel <ard.biesheuvel@linaro.org>
Subject: Re: [PATCH v1 02/14] OvmfPkg/Virtio10Dxe: Implement new member functions
Date: Wed, 9 Aug 2017 18:50:36 +0200 [thread overview]
Message-ID: <659fe2f7-0d17-cde7-c3d3-36e541ff7805@redhat.com> (raw)
In-Reply-To: <1502107139-412-3-git-send-email-brijesh.singh@amd.com>
(1) For the subject, I suggest again
OvmfPkg/Virtio10Dxe: Implement IOMMU-like member functions
On 08/07/17 13:58, Brijesh Singh wrote:
> The patch implements the newly added member functions by respectively
> delegating the job to:
>
> - EFI_PCI_IO_PROTOCOL.AllocateBuffer() -- with BootServicesData
> - EFI_PCI_IO_PROTOCOL.FreeBuffer()
> - EFI_PCI_IO_PROTOCOL.Map()
> - EFI_PCI_IO_PROTOCOL.Unmap()
(2) looks good, but please spell out the new virtio protocol member
names as well. (This will become more important in the commit
message of the next patch, where the reader has to guess what member
functions exactly get the "no-op" implementation.)
And then we should be consistent in the commit messages.
>
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> OvmfPkg/Virtio10Dxe/Virtio10.c | 114 +++++++++++++++++++-
> 1 file changed, 113 insertions(+), 1 deletion(-)
>
> diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
> index a8a6a58c3f1d..5bc8f1c7ee27 100644
> --- a/OvmfPkg/Virtio10Dxe/Virtio10.c
> +++ b/OvmfPkg/Virtio10Dxe/Virtio10.c
> @@ -2,6 +2,7 @@
> A non-transitional driver for VirtIo 1.0 PCI devices.
>
> Copyright (C) 2016, Red Hat, Inc.
> + Copyright (C) 2017, AMD 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
> @@ -772,6 +773,113 @@ Virtio10ReadDevice (
> return Status;
> }
>
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +Virtio10AllocateSharedPages (
> + IN VIRTIO_DEVICE_PROTOCOL *This,
> + IN UINTN Pages,
> + IN OUT VOID **HostAddress
> + )
> +{
> + VIRTIO_1_0_DEV *Dev;
> + EFI_STATUS Status;
> +
> + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
> +
> + Status = Dev->PciIo->AllocateBuffer (
> + Dev->PciIo,
> + AllocateAnyPages,
> + EfiBootServicesData,
> + Pages,
> + HostAddress,
> + 0
(3) We should pass Attributes=EFI_PCI_ATTRIBUTE_MEMORY_CACHED, even if
only for cosmetic purposes (at the moment).
(4) Independently, this makes me think about
EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE.
* PciIoAllocateBuffer() [MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c]
sets the EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE attribute
internally, before calling out to the PCI Root Bridge IO Protocol,
*if* "PciIoDevice->Attributes" has
EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE set.
In turn:
- If there is an IOMMU protocol in the system, then
RootBridgeIoAllocateBuffer()
[MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c] passes
EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE through to the IOMMU
protocol's AllocateBuffer() member *if* "RootBridge->DmaAbove4G"
is set. Otherwise the DUAL_ADDRESS_CYCLE hint is cleared.
(EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE has the same numeric
value, 0x8000, as EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE.)
- If there is no IOMMU protocol in the system, then
RootBridgeIoAllocateBuffer() itself allocates memory, again
obeying EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE and
"RootBridge->DmaAbove4G".
So regardless of whether there is an IOMMU protocol in the system
or not, on the PCI Root Bridge IO level, 64-bit AllocateBuffer()
is be permitted according to device-level DUAL_ADDRESS_CYCLE *AND*
root-bridge-level DmaAbove4G.
* Let's consider what's going to happen if we convert the virtio
drivers to the new virtio proto member functions, and (in
addition) Virtio10Dxe is converted to explicit
PciIo.AllocateBuffer():
- In OvmfPkg, allocations that used to be plain AllocatePool() or
AllocatePages(), will be restricted to 32-bit, due to two
reasons (either of which is sufficient in this regard):
- In "OvmfPkg/Library/PciHostBridgeLib", we clear DmaAbove4G,
for hysterical raisins.
- In Virtio10Dxe, we don't set
EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE.
- In ArmVirtPkg, allocations that used to be plain AllocatePool()
or AllocatePages(), will also be restricted to 32-bit. While
"ArmVirtPkg/Library/FdtPciHostBridgeLib" *sets* DmaAbove4G, lack
of EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE in Virtio10Dxe alone
is suffices to trigger the restriction.
* Therefore, please extend this patch with the following: in the
Virtio10BindingStart() function [OvmfPkg/Virtio10Dxe/Virtio10.c],
please replace
SetAttributes = 0;
with
SetAttributes = EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
It will not help OvmfPkg, but it will keep the 4GB restriction out
of ArmVirtPkg. (I'm unsure if we can simply flip "DmaAbove4G" to
TRUE in OvmfPkg.)
* (In the past, Ard wrote a number of similar patches for physical
device drivers:
167c3fb45674 MdeModulePkg/EhciDxe: enable 64-bit PCI DMA
4e28ea2c29e0 MdeModulePkg/NvmExpressDxe: enable 64-bit PCI DMA
df0a0e4b6fae MdeModulePkg/SdMmcPciHcDxe: enable 64-bit PCI DMA
5c1b371a8839 MdeModulePkg/XhciDxe: enable 64-bit PCI DMA
e58a71d9c50b MdeModulePkg/PciHostBridgeDxe: restrict 64-bit DMA
to devices that support it
4c0b2d25c61c ArmVirtPkg/FdtPciHostBridgeLib: enable 64-bit PCI
DMA
and that's what we should do here, in separate patches, for the
virtio-pci transport drivers.)
(5) Looking more at the PciIo attribute setting in both virtio-PCI
transport drivers, it seems that I failed to set
EFI_PCI_IO_ATTRIBUTE_BUS_MASTER in both. Virtio devices read and
write guest RAM (they don't just decode their IO and/or MMIO BARs),
which translates to "bus master".
So, please clean up my mess :) , and prepend two separate patches to
the series:
- "OvmfPkg/VirtioPciDeviceDxe: supply missing BUS_MASTER attribute"
Please change
EFI_PCI_IO_ATTRIBUTE_IO
to
EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
in VirtioPciDeviceBindingStart()
[OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c].
- "OvmfPkg/Virtio10Dxe: supply missing BUS_MASTER attribute"
Please change
SetAttributes = 0;
to
SetAttributes = EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
in Virtio10BindingStart() [OvmfPkg/Virtio10Dxe/Virtio10.c].
(And then do point (4) on top of that, separately.)
Okay, summary of points (3), (4) and (5):
- please prepend *two* patches, setting EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
in each virtio-pci transport driver -- point (5)
- please set EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE in the modern-only
driver, in this patch -- point (4)
- please pass Attributes=EFI_PCI_ATTRIBUTE_MEMORY_CACHED to
Dev->PciIo->AllocateBuffer(), in this patch -- point (3).
Phew, this is complex. :)
> + );
> + return Status;
> +}
> +
> +STATIC
> +VOID
> +EFIAPI
> +Virtio10FreeSharedPages (
> + IN VIRTIO_DEVICE_PROTOCOL *This,
> + IN UINTN Pages,
> + IN VOID *HostAddress
> + )
> +{
> + VIRTIO_1_0_DEV *Dev;
> +
> + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
> +
> + Dev->PciIo->FreeBuffer (
> + Dev->PciIo,
> + Pages,
> + HostAddress
> + );
> +}
Looks OK.
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +Virtio10MapSharedBuffer (
> + IN VIRTIO_DEVICE_PROTOCOL *This,
> + IN VIRTIO_MAP_OPERATION Operation,
> + IN VOID *HostAddress,
> + IN OUT UINTN *NumberOfBytes,
> + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
> + OUT VOID **Mapping
> + )
> +{
> + EFI_STATUS Status;
> + VIRTIO_1_0_DEV *Dev;
> + EFI_PCI_IO_PROTOCOL_OPERATION PciIoOperation;
> +
> + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
> +
> + //
> + // Map VIRTIO_MAP_OPERATION to EFI_PCI_IO_PROTOCOL_OPERATION
> + //
> + if (Operation == EfiVirtIoOperationBusMasterRead) {
> + PciIoOperation = EfiPciIoOperationBusMasterRead;
> + } else if (Operation == EfiVirtIoOperationBusMasterWrite) {
> + PciIoOperation = EfiPciIoOperationBusMasterWrite;
> + } else if (Operation == EfiVirtIoOperationBusMasterCommonBuffer) {
> + PciIoOperation = EfiPciIoOperationBusMasterCommonBuffer;
> + } else {
> + return EFI_UNSUPPORTED;
> + }
(6) This mapping lends itself to simplification by virtue of a switch
statement. (Please remember that the "case" labels are indented
*zero* positions relative to the "switch" keyword.)
(7) Rather than EFI_UNSUPPORTED, EFI_INVALID_PARAMETER should be
returned ("One or more parameters are invalid.")
(8) You don't seem to be using "VirtioOperationMaximum" for range
checking (that's fine, with the switch we can check each value
individually, and then add a "default" case) -- please consider
removing VirtioOperationMaximum from the protocol interface then.
Regarding 64-bit transparency: this code is good, as long as we cover
point (4) above:
- EFI_PCI_IO_PROTOCOL_OPERATION has no separate 32-bit and 64-bit
constants,
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION does make such a
distinction,
- PciIoMap() in "MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c" shifts the
former op constants up to the 64-bit latter op constants, if
EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE is enabled for the device
(hence my reference to (4)).
The rest also looks good.
Thanks,
Laszlo
> +
> + Status = Dev->PciIo->Map (
> + Dev->PciIo,
> + PciIoOperation,
> + HostAddress,
> + NumberOfBytes,
> + DeviceAddress,
> + Mapping
> + );
> + return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +Virtio10UnmapSharedBuffer (
> + IN VIRTIO_DEVICE_PROTOCOL *This,
> + IN VOID *Mapping
> + )
> +{
> + EFI_STATUS Status;
> + VIRTIO_1_0_DEV *Dev;
> +
> + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
> +
> + Status = Dev->PciIo->Unmap (
> + Dev->PciIo,
> + Mapping
> + );
> +
> + return Status;
> +}
>
> STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = {
> VIRTIO_SPEC_REVISION (1, 0, 0),
> @@ -788,7 +896,11 @@ STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = {
> Virtio10GetDeviceStatus,
> Virtio10SetDeviceStatus,
> Virtio10WriteDevice,
> - Virtio10ReadDevice
> + Virtio10ReadDevice,
> + Virtio10AllocateSharedPages,
> + Virtio10FreeSharedPages,
> + Virtio10MapSharedBuffer,
> + Virtio10UnmapSharedBuffer
> };
>
>
>
next prev parent reply other threads:[~2017-08-09 16:48 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 01/14] OvmfPkg/Virtio: Introduce new member functions in VIRTIO_DEVICE_PROTOCOL Brijesh Singh
2017-08-09 14:27 ` Laszlo Ersek
2017-08-09 18:23 ` Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 02/14] OvmfPkg/Virtio10Dxe: Implement new member functions Brijesh Singh
2017-08-09 16:50 ` Laszlo Ersek [this message]
2017-08-07 11:58 ` [PATCH v1 03/14] OvmfPkg/VirtioPciDeviceDxe: " Brijesh Singh
2017-08-09 17:09 ` Laszlo Ersek
2017-08-10 18:41 ` Brijesh Singh
2017-08-10 19:47 ` Laszlo Ersek
2017-08-07 11:58 ` [PATCH v1 04/14] OvmfPkg/VirtioLib: Add SharedBuffer helper functions Brijesh Singh
2017-08-09 20:30 ` Laszlo Ersek
2017-08-07 11:58 ` [PATCH v1 05/14] OvmfPkg/VirtioLib: Pass VirtIo instance in VringInit/Uinit() Brijesh Singh
2017-08-09 21:13 ` Laszlo Ersek
2017-08-07 11:58 ` [PATCH v1 06/14] OvmfPkg/VirtioLib: Add functions to map/unmap VRING Brijesh Singh
2017-08-09 23:51 ` Laszlo Ersek
2017-08-07 11:58 ` [PATCH v1 07/14] OvmfPkg/VirtioLib: Use AllocateShared() to allocate vring buffer Brijesh Singh
2017-08-10 0:02 ` Laszlo Ersek
2017-08-07 11:58 ` [PATCH v1 08/14] OvmfPkg/VirtioBlkDxe: Use DeviceAddresses in vring descriptors Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 09/14] OvmfPkg/VirtioScsiDxe: " Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 10/14] OvmfPkg/VirtioNetDxe: Allocate Tx and Rx ring using AllocateSharedPage() Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 11/14] OvmfPkg/VirtioNetDxe: Allocate RxBuf using AllocateSharedPages() Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 12/14] OvmfPkg/VirtioNetDxe: Dynamically allocate transmit header Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 13/14] OvmfPkg/VirtioNetDxe: Use DeviceAddress in transmit vring descriptors Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 14/14] OvmfPkg/VirtioRngDxe: Use DeviceAddresses in " Brijesh Singh
2017-08-10 0:25 ` Laszlo Ersek
2017-08-10 0:46 ` Laszlo Ersek
2017-08-09 14:39 ` [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Laszlo Ersek
2017-08-09 17:35 ` Brijesh Singh
2017-08-09 17:56 ` Laszlo Ersek
2017-08-09 19:29 ` Laszlo Ersek
2017-08-11 22:22 ` Brijesh Singh
2017-08-15 10:42 ` Laszlo Ersek
2017-08-15 19:32 ` Brijesh Singh
2017-08-15 19:48 ` Laszlo Ersek
2017-08-15 20:26 ` Brijesh Singh
2017-08-15 20:39 ` Laszlo Ersek
2017-08-15 20:44 ` Brijesh Singh
2017-08-15 21:57 ` Laszlo Ersek
2017-08-09 22:38 ` Laszlo Ersek
2017-08-09 22:44 ` Brijesh Singh
2017-08-10 9:53 ` 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=659fe2f7-0d17-cde7-c3d3-36e541ff7805@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