When device is behind the IOMMU, driver is require to pass the device
address of caller-supplied transmit buffer for the bus master operations.
The patch uses VirtioNetMapTxBuf() to map caller-supplied Tx packet to a
device-address and enqueue the device address in VRING for transfer and
perform the reverse mapping when transfer is completed so that we can
return the caller-supplied buffer.
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/VirtioNetDxe/SnpGetStatus.c | 41 +++++++++++++++-----
OvmfPkg/VirtioNetDxe/SnpTransmit.c | 27 ++++++++++---
2 files changed, 53 insertions(+), 15 deletions(-)
diff --git a/OvmfPkg/VirtioNetDxe/SnpGetStatus.c b/OvmfPkg/VirtioNetDxe/SnpGetStatus.c
index 694940ea1d97..f817b98801fa 100644
--- a/OvmfPkg/VirtioNetDxe/SnpGetStatus.c
+++ b/OvmfPkg/VirtioNetDxe/SnpGetStatus.c
@@ -61,11 +61,15 @@ VirtioNetGetStatus (
OUT VOID **TxBuf OPTIONAL
)
{
- VNET_DEV *Dev;
- EFI_TPL OldTpl;
- EFI_STATUS Status;
- UINT16 RxCurUsed;
- UINT16 TxCurUsed;
+ VNET_DEV *Dev;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ UINT16 RxCurUsed;
+ UINT16 TxCurUsed;
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
+ UINT32 LocalInterruptStatus;
+
+ LocalInterruptStatus = *InterruptStatus;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
@@ -113,11 +117,11 @@ VirtioNetGetStatus (
//
*InterruptStatus = 0;
if (Dev->RxLastUsed != RxCurUsed) {
- *InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
+ LocalInterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
}
if (Dev->TxLastUsed != TxCurUsed) {
ASSERT (Dev->TxCurPending > 0);
- *InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
+ LocalInterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
}
}
@@ -141,17 +145,36 @@ VirtioNetGetStatus (
ASSERT (DescIdx < (UINT32) (2 * Dev->TxMaxPending - 1));
//
- // report buffer address to caller that has been enqueued by caller
+ // get the device address that has been enqueued for the caller's
+ // transmit buffer
//
- *TxBuf = (VOID *)(UINTN) Dev->TxRing.Desc[DescIdx + 1].Addr;
+ DeviceAddress = Dev->TxRing.Desc[DescIdx + 1].Addr;
//
// now this descriptor can be used again to enqueue a transmit buffer
//
Dev->TxFreeStack[--Dev->TxCurPending] = (UINT16) DescIdx;
+
+ //
+ // Unmap the device address and perform the reverse mapping to find the
+ // caller buffer address.
+ //
+ Status = VirtioNetUnmapTxBuf (
+ Dev,
+ TxBuf,
+ DeviceAddress
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // VirtioNetUnmapTxBuf should never fail, if we have reached here
+ // that means our internal state has been corrupted
+ //
+ ASSERT (FALSE);
+ }
}
}
+ *InterruptStatus = LocalInterruptStatus;
Status = EFI_SUCCESS;
Exit:
diff --git a/OvmfPkg/VirtioNetDxe/SnpTransmit.c b/OvmfPkg/VirtioNetDxe/SnpTransmit.c
index 7ca40d5d0650..b39226e138b9 100644
--- a/OvmfPkg/VirtioNetDxe/SnpTransmit.c
+++ b/OvmfPkg/VirtioNetDxe/SnpTransmit.c
@@ -73,11 +73,12 @@ VirtioNetTransmit (
IN UINT16 *Protocol OPTIONAL
)
{
- VNET_DEV *Dev;
- EFI_TPL OldTpl;
- EFI_STATUS Status;
- UINT16 DescIdx;
- UINT16 AvailIdx;
+ VNET_DEV *Dev;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ UINT16 DescIdx;
+ UINT16 AvailIdx;
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
if (This == NULL || BufferSize == 0 || Buffer == NULL) {
return EFI_INVALID_PARAMETER;
@@ -144,10 +145,24 @@ VirtioNetTransmit (
}
//
+ // Map the transmit buffer system physical address to device address.
+ //
+ Status = VirtioNetMapTxBuf (
+ Dev,
+ Buffer,
+ BufferSize,
+ &DeviceAddress
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ //
// virtio-0.9.5, 2.4.1 Supplying Buffers to The Device
//
DescIdx = Dev->TxFreeStack[Dev->TxCurPending++];
- Dev->TxRing.Desc[DescIdx + 1].Addr = (UINTN) Buffer;
+ Dev->TxRing.Desc[DescIdx + 1].Addr = DeviceAddress;
Dev->TxRing.Desc[DescIdx + 1].Len = (UINT32) BufferSize;
//
--
2.9.5
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
On 09/14/17 13:08, Brijesh Singh wrote:
> When device is behind the IOMMU, driver is require to pass the device
> address of caller-supplied transmit buffer for the bus master operations.
>
> The patch uses VirtioNetMapTxBuf() to map caller-supplied Tx packet to a
> device-address and enqueue the device address in VRING for transfer and
> perform the reverse mapping when transfer is completed so that we can
> return the caller-supplied buffer.
>
> 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/VirtioNetDxe/SnpGetStatus.c | 41 +++++++++++++++-----
> OvmfPkg/VirtioNetDxe/SnpTransmit.c | 27 ++++++++++---
> 2 files changed, 53 insertions(+), 15 deletions(-)
>
> diff --git a/OvmfPkg/VirtioNetDxe/SnpGetStatus.c b/OvmfPkg/VirtioNetDxe/SnpGetStatus.c
> index 694940ea1d97..f817b98801fa 100644
> --- a/OvmfPkg/VirtioNetDxe/SnpGetStatus.c
> +++ b/OvmfPkg/VirtioNetDxe/SnpGetStatus.c
> @@ -61,11 +61,15 @@ VirtioNetGetStatus (
> OUT VOID **TxBuf OPTIONAL
> )
> {
> - VNET_DEV *Dev;
> - EFI_TPL OldTpl;
> - EFI_STATUS Status;
> - UINT16 RxCurUsed;
> - UINT16 TxCurUsed;
> + VNET_DEV *Dev;
> + EFI_TPL OldTpl;
> + EFI_STATUS Status;
> + UINT16 RxCurUsed;
> + UINT16 TxCurUsed;
> + EFI_PHYSICAL_ADDRESS DeviceAddress;
> + UINT32 LocalInterruptStatus;
> +
> + LocalInterruptStatus = *InterruptStatus;
>
> if (This == NULL) {
> return EFI_INVALID_PARAMETER;
> @@ -113,11 +117,11 @@ VirtioNetGetStatus (
> //
> *InterruptStatus = 0;
> if (Dev->RxLastUsed != RxCurUsed) {
> - *InterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
> + LocalInterruptStatus |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
> }
> if (Dev->TxLastUsed != TxCurUsed) {
> ASSERT (Dev->TxCurPending > 0);
> - *InterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
> + LocalInterruptStatus |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
> }
> }
>
I must have been unclear in my v2 review, sorry about that. My point was
that, given the changes that I requested in points v2/3 and v2/4, the
handling of "InterruptStatus" was fine as it was.
(1) Therefore please undo the v3 "InterruptStatus" changes -- the
"LocalInterruptStatus" variable is unnecessary.
> @@ -141,17 +145,36 @@ VirtioNetGetStatus (
> ASSERT (DescIdx < (UINT32) (2 * Dev->TxMaxPending - 1));
>
> //
> - // report buffer address to caller that has been enqueued by caller
> + // get the device address that has been enqueued for the caller's
> + // transmit buffer
> //
> - *TxBuf = (VOID *)(UINTN) Dev->TxRing.Desc[DescIdx + 1].Addr;
> + DeviceAddress = Dev->TxRing.Desc[DescIdx + 1].Addr;
>
> //
> // now this descriptor can be used again to enqueue a transmit buffer
> //
> Dev->TxFreeStack[--Dev->TxCurPending] = (UINT16) DescIdx;
> +
> + //
> + // Unmap the device address and perform the reverse mapping to find the
> + // caller buffer address.
> + //
> + Status = VirtioNetUnmapTxBuf (
> + Dev,
> + TxBuf,
> + DeviceAddress
> + );
> + if (EFI_ERROR (Status)) {
> + //
> + // VirtioNetUnmapTxBuf should never fail, if we have reached here
> + // that means our internal state has been corrupted
> + //
> + ASSERT (FALSE);
The rest of VirtioNetGetStatus() looks good, but here's the other
misunderstanding:
(2) Please *keep* the ASSERT() that you are adding above, and below it,
*add back* what you had in v2:
Status = EFI_DEVICE_ERROR;
goto Exit;
The rest looks good.
Can you submit v4 soon please? :)
Thanks,
Laszlo
> + }
> }
> }
>
> + *InterruptStatus = LocalInterruptStatus;
> Status = EFI_SUCCESS;
>
> Exit:
> diff --git a/OvmfPkg/VirtioNetDxe/SnpTransmit.c b/OvmfPkg/VirtioNetDxe/SnpTransmit.c
> index 7ca40d5d0650..b39226e138b9 100644
> --- a/OvmfPkg/VirtioNetDxe/SnpTransmit.c
> +++ b/OvmfPkg/VirtioNetDxe/SnpTransmit.c
> @@ -73,11 +73,12 @@ VirtioNetTransmit (
> IN UINT16 *Protocol OPTIONAL
> )
> {
> - VNET_DEV *Dev;
> - EFI_TPL OldTpl;
> - EFI_STATUS Status;
> - UINT16 DescIdx;
> - UINT16 AvailIdx;
> + VNET_DEV *Dev;
> + EFI_TPL OldTpl;
> + EFI_STATUS Status;
> + UINT16 DescIdx;
> + UINT16 AvailIdx;
> + EFI_PHYSICAL_ADDRESS DeviceAddress;
>
> if (This == NULL || BufferSize == 0 || Buffer == NULL) {
> return EFI_INVALID_PARAMETER;
> @@ -144,10 +145,24 @@ VirtioNetTransmit (
> }
>
> //
> + // Map the transmit buffer system physical address to device address.
> + //
> + Status = VirtioNetMapTxBuf (
> + Dev,
> + Buffer,
> + BufferSize,
> + &DeviceAddress
> + );
> + if (EFI_ERROR (Status)) {
> + Status = EFI_DEVICE_ERROR;
> + goto Exit;
> + }
> +
> + //
> // virtio-0.9.5, 2.4.1 Supplying Buffers to The Device
> //
> DescIdx = Dev->TxFreeStack[Dev->TxCurPending++];
> - Dev->TxRing.Desc[DescIdx + 1].Addr = (UINTN) Buffer;
> + Dev->TxRing.Desc[DescIdx + 1].Addr = DeviceAddress;
> Dev->TxRing.Desc[DescIdx + 1].Len = (UINT32) BufferSize;
>
> //
>
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
On 09/14/2017 03:58 PM, Laszlo Ersek wrote: ...> > The rest of VirtioNetGetStatus() looks good, but here's the other > misunderstanding: > > (2) Please *keep* the ASSERT() that you are adding above, and below it, > *add back* what you had in v2: > > Status = EFI_DEVICE_ERROR; > goto Exit; > > The rest looks good. > > Can you submit v4 soon please? :) > Yes, I should be submitting very soon :) -Brijesh _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2025 Red Hat, Inc.