summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/VirtioNetDxe
diff options
context:
space:
mode:
authorBrijesh Singh <brijesh.singh@amd.com>2017-09-14 16:22:42 -0500
committerLaszlo Ersek <lersek@redhat.com>2017-09-14 23:54:07 +0200
commit46b11f00ac704ed4a1e3c8c1c3439f914e2dfadc (patch)
tree1dd769f7b42341364f9633203764324c3ca52256 /OvmfPkg/VirtioNetDxe
parent940baec09c8f4664b34842d13a30ce243d0b7b4b (diff)
downloadedk2-46b11f00ac704ed4a1e3c8c1c3439f914e2dfadc.tar.gz
edk2-46b11f00ac704ed4a1e3c8c1c3439f914e2dfadc.tar.bz2
edk2-46b11f00ac704ed4a1e3c8c1c3439f914e2dfadc.zip
OvmfPkg/VirtioNetDxe: alloc RxBuf using AllocateSharedPages()
When device is behind the IOMMU, VirtioNetDxe is required to use the device address in bus master operations. RxBuf is allocated using AllocatePool() which returns the system physical address. The patch uses VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages() to allocate the RxBuf and map with VirtioMapAllBytesInSharedBuffer() so that we can obtain the device address for RxBuf. 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> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Laszlo Ersek <lersek@redhat.com>
Diffstat (limited to 'OvmfPkg/VirtioNetDxe')
-rw-r--r--OvmfPkg/VirtioNetDxe/SnpInitialize.c78
-rw-r--r--OvmfPkg/VirtioNetDxe/SnpReceive.c5
-rw-r--r--OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c7
-rw-r--r--OvmfPkg/VirtioNetDxe/TechNotes.txt2
-rw-r--r--OvmfPkg/VirtioNetDxe/VirtioNet.h4
5 files changed, 75 insertions, 21 deletions
diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
index 8eabdbff6f..b739875d4c 100644
--- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
+++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
@@ -242,8 +242,9 @@ VirtioNetInitTx (
@param[in,out] Dev The VNET_DEV driver instance about to enter the
EfiSimpleNetworkInitialized state.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate RX destination area.
- @return Status codes from VIRTIO_CFG_WRITE().
+ @return Status codes from VIRTIO_CFG_WRITE() or
+ VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages or
+ VirtioMapAllBytesInSharedBuffer().
@retval EFI_SUCCESS RX setup successful. The device is live and may
already be writing to the receive area.
*/
@@ -255,13 +256,15 @@ VirtioNetInitRx (
IN OUT VNET_DEV *Dev
)
{
- EFI_STATUS Status;
- UINTN VirtioNetReqSize;
- UINTN RxBufSize;
- UINT16 RxAlwaysPending;
- UINTN PktIdx;
- UINT16 DescIdx;
- UINT8 *RxPtr;
+ EFI_STATUS Status;
+ UINTN VirtioNetReqSize;
+ UINTN RxBufSize;
+ UINT16 RxAlwaysPending;
+ UINTN PktIdx;
+ UINT16 DescIdx;
+ UINTN NumBytes;
+ EFI_PHYSICAL_ADDRESS RxBufDeviceAddress;
+ VOID *RxBuffer;
//
// In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on
@@ -286,11 +289,39 @@ VirtioNetInitRx (
//
RxAlwaysPending = (UINT16) MIN (Dev->RxRing.QueueSize / 2, VNET_MAX_PENDING);
- Dev->RxBuf = AllocatePool (RxAlwaysPending * RxBufSize);
- if (Dev->RxBuf == NULL) {
- return EFI_OUT_OF_RESOURCES;
+ //
+ // The RxBuf is shared between guest and hypervisor, use
+ // AllocateSharedPages() to allocate this memory region and map it with
+ // BusMasterCommonBuffer so that it can be accessed by both guest and
+ // hypervisor.
+ //
+ NumBytes = RxAlwaysPending * RxBufSize;
+ Dev->RxBufNrPages = EFI_SIZE_TO_PAGES (NumBytes);
+ Status = Dev->VirtIo->AllocateSharedPages (
+ Dev->VirtIo,
+ Dev->RxBufNrPages,
+ &RxBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
}
+ ZeroMem (RxBuffer, NumBytes);
+
+ Status = VirtioMapAllBytesInSharedBuffer (
+ Dev->VirtIo,
+ VirtioOperationBusMasterCommonBuffer,
+ RxBuffer,
+ NumBytes,
+ &Dev->RxBufDeviceBase,
+ &Dev->RxBufMap
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreeSharedBuffer;
+ }
+
+ Dev->RxBuf = RxBuffer;
+
//
// virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device
//
@@ -310,7 +341,7 @@ VirtioNetInitRx (
// link each chain into (from) the available ring as well
//
DescIdx = 0;
- RxPtr = Dev->RxBuf;
+ RxBufDeviceAddress = Dev->RxBufDeviceBase;
for (PktIdx = 0; PktIdx < RxAlwaysPending; ++PktIdx) {
//
// virtio-0.9.5, 2.4.1.2 Updating the Available Ring
@@ -321,16 +352,16 @@ VirtioNetInitRx (
//
// virtio-0.9.5, 2.4.1.1 Placing Buffers into the Descriptor Table
//
- Dev->RxRing.Desc[DescIdx].Addr = (UINTN) RxPtr;
+ Dev->RxRing.Desc[DescIdx].Addr = RxBufDeviceAddress;
Dev->RxRing.Desc[DescIdx].Len = (UINT32) VirtioNetReqSize;
Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;
Dev->RxRing.Desc[DescIdx].Next = (UINT16) (DescIdx + 1);
- RxPtr += Dev->RxRing.Desc[DescIdx++].Len;
+ RxBufDeviceAddress += Dev->RxRing.Desc[DescIdx++].Len;
- Dev->RxRing.Desc[DescIdx].Addr = (UINTN) RxPtr;
+ Dev->RxRing.Desc[DescIdx].Addr = RxBufDeviceAddress;
Dev->RxRing.Desc[DescIdx].Len = (UINT32) (RxBufSize - VirtioNetReqSize);
Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE;
- RxPtr += Dev->RxRing.Desc[DescIdx++].Len;
+ RxBufDeviceAddress += Dev->RxRing.Desc[DescIdx++].Len;
}
//
@@ -351,10 +382,21 @@ VirtioNetInitRx (
Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);
if (EFI_ERROR (Status)) {
Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
- FreePool (Dev->RxBuf);
+ goto UnmapSharedBuffer;
}
return Status;
+
+UnmapSharedBuffer:
+ Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);
+
+FreeSharedBuffer:
+ Dev->VirtIo->FreeSharedPages (
+ Dev->VirtIo,
+ Dev->RxBufNrPages,
+ RxBuffer
+ );
+ return Status;
}
diff --git a/OvmfPkg/VirtioNetDxe/SnpReceive.c b/OvmfPkg/VirtioNetDxe/SnpReceive.c
index 99abd7ebe4..c42489636e 100644
--- a/OvmfPkg/VirtioNetDxe/SnpReceive.c
+++ b/OvmfPkg/VirtioNetDxe/SnpReceive.c
@@ -82,6 +82,7 @@ VirtioNetReceive (
UINT8 *RxPtr;
UINT16 AvailIdx;
EFI_STATUS NotifyStatus;
+ UINTN RxBufOffset;
if (This == NULL || BufferSize == NULL || Buffer == NULL) {
return EFI_INVALID_PARAMETER;
@@ -143,7 +144,9 @@ VirtioNetReceive (
*HeaderSize = Dev->Snm.MediaHeaderSize;
}
- RxPtr = (UINT8 *)(UINTN) Dev->RxRing.Desc[DescIdx + 1].Addr;
+ RxBufOffset = (UINTN)(Dev->RxRing.Desc[DescIdx + 1].Addr -
+ Dev->RxBufDeviceBase);
+ RxPtr = Dev->RxBuf + RxBufOffset;
CopyMem (Buffer, RxPtr, RxLen);
if (DestAddr != NULL) {
diff --git a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
index 57c7395848..ee4f9ed36e 100644
--- a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
+++ b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
@@ -39,7 +39,12 @@ VirtioNetShutdownRx (
IN OUT VNET_DEV *Dev
)
{
- FreePool (Dev->RxBuf);
+ Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);
+ Dev->VirtIo->FreeSharedPages (
+ Dev->VirtIo,
+ Dev->RxBufNrPages,
+ Dev->RxBuf
+ );
}
diff --git a/OvmfPkg/VirtioNetDxe/TechNotes.txt b/OvmfPkg/VirtioNetDxe/TechNotes.txt
index 37250b14a9..fedbaee07e 100644
--- a/OvmfPkg/VirtioNetDxe/TechNotes.txt
+++ b/OvmfPkg/VirtioNetDxe/TechNotes.txt
@@ -247,7 +247,7 @@ In VirtioNetInitRx, the guest allocates the fixed size Receive Destination
Area, which accommodates all packets delivered asynchronously by the host. To
each packet, a slice of this area is dedicated; each slice is further
subdivided into virtio-net request header and network packet data. The
-(guest-physical) addresses of these sub-slices are denoted with A2, A3, A4 and
+(device-physical) addresses of these sub-slices are denoted with A2, A3, A4 and
so on. Importantly, an even-subscript "A" always belongs to a virtio-net
request header, while an odd-subscript "A" always belongs to a packet
sub-slice.
diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.h b/OvmfPkg/VirtioNetDxe/VirtioNet.h
index 6762fc9d1d..995593f4b2 100644
--- a/OvmfPkg/VirtioNetDxe/VirtioNet.h
+++ b/OvmfPkg/VirtioNetDxe/VirtioNet.h
@@ -4,6 +4,7 @@
Protocol instances for virtio-net devices.
Copyright (C) 2013, 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
@@ -86,6 +87,9 @@ typedef struct {
// VirtioNetInitRing
UINT8 *RxBuf; // VirtioNetInitRx
UINT16 RxLastUsed; // VirtioNetInitRx
+ UINTN RxBufNrPages; // VirtioNetInitRx
+ EFI_PHYSICAL_ADDRESS RxBufDeviceBase; // VirtioNetInitRx
+ VOID *RxBufMap; // VirtioNetInitRx
VRING TxRing; // VirtioNetInitRing
VOID *TxRingMap; // VirtioRingMap and