From patchwork Mon Mar 14 12:53:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laszlo Ersek X-Patchwork-Id: 63821 Delivered-To: patch@linaro.org Received: by 10.112.199.169 with SMTP id jl9csp18224lbc; Mon, 14 Mar 2016 05:54:13 -0700 (PDT) X-Received: by 10.67.7.1 with SMTP id cy1mr38029501pad.123.1457960051057; Mon, 14 Mar 2016 05:54:11 -0700 (PDT) Return-Path: Received: from ml01.01.org (ml01.01.org. [198.145.21.10]) by mx.google.com with ESMTPS id xu3si17410444pab.174.2016.03.14.05.54.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 14 Mar 2016 05:54:11 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) client-ip=198.145.21.10; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id B136D1A1FA0; Mon, 14 Mar 2016 05:54:16 -0700 (PDT) X-Original-To: edk2-devel@ml01.01.org Delivered-To: edk2-devel@ml01.01.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 10B7C1A1EDC for ; Mon, 14 Mar 2016 05:54:16 -0700 (PDT) Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (Postfix) with ESMTPS id D5952C00356E; Mon, 14 Mar 2016 12:53:57 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-113-101.phx2.redhat.com [10.3.113.101]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u2ECraIR012537; Mon, 14 Mar 2016 08:53:56 -0400 From: Laszlo Ersek To: edk2-devel@ml01.01.org Date: Mon, 14 Mar 2016 13:53:29 +0100 Message-Id: <1457960012-29481-13-git-send-email-lersek@redhat.com> In-Reply-To: <1457960012-29481-1-git-send-email-lersek@redhat.com> References: <56E6B2D9.5010507@redhat.com> <1457960012-29481-1-git-send-email-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 Cc: Jordan Justen , Ard Biesheuvel Subject: [edk2] [wave 3 PATCH 12/15] OvmfPkg: VirtioNetDxe: adapt virtio-net packet header size to virtio-1.0 X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" In virtio-0.9.5, the size of the virtio-net packet header depends on whether the VIRTIO_NET_F_MRG_RXBUF feature is negotiated -- the "num_buffers" field is only appended to the header if the feature is negotiated. Since we never negotiate this feature, VirtioNetDxe never allocates room for the "num_buffers" field. With virtio-1.0, the "num_buffers" field is always there (although it doesn't carry useful information without VIRTIO_NET_F_MRG_RXBUF). Adapt the buffers that depend on the virtio-net header size (otherwise we have skewed / truncated packets). Cc: Ard Biesheuvel Cc: Jordan Justen Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek --- OvmfPkg/VirtioNetDxe/VirtioNet.h | 4 +-- OvmfPkg/VirtioNetDxe/SnpInitialize.c | 36 ++++++++++++++++---- 2 files changed, 31 insertions(+), 9 deletions(-) -- 1.8.3.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.h b/OvmfPkg/VirtioNetDxe/VirtioNet.h index 2d3f3d87eb11..7bd879094d31 100644 --- a/OvmfPkg/VirtioNetDxe/VirtioNet.h +++ b/OvmfPkg/VirtioNetDxe/VirtioNet.h @@ -13,15 +13,15 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #ifndef _VIRTIO_NET_DXE_H_ #define _VIRTIO_NET_DXE_H_ -#include +#include #include #include #include #include #include #include #include @@ -85,15 +85,15 @@ typedef struct { UINT8 *RxBuf; // VirtioNetInitRx UINT16 RxLastUsed; // VirtioNetInitRx VRING TxRing; // VirtioNetInitRing UINT16 TxMaxPending; // VirtioNetInitTx UINT16 TxCurPending; // VirtioNetInitTx UINT16 *TxFreeStack; // VirtioNetInitTx - VIRTIO_NET_REQ TxSharedReq; // VirtioNetInitTx + VIRTIO_1_0_NET_REQ TxSharedReq; // VirtioNetInitTx UINT16 TxLastUsed; // VirtioNetInitTx } VNET_DEV; // // In order to avoid duplication of interface documentation, please find all // leading comments near the respective function / variable definitions (not diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c index 38012a0df8d6..4942b596bb1f 100644 --- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c +++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c @@ -134,52 +134,66 @@ ReleaseQueue: STATIC EFI_STATUS EFIAPI VirtioNetInitTx ( IN OUT VNET_DEV *Dev ) { + UINTN TxSharedReqSize; UINTN PktIdx; Dev->TxMaxPending = (UINT16) MIN (Dev->TxRing.QueueSize / 2, VNET_MAX_PENDING); Dev->TxCurPending = 0; Dev->TxFreeStack = AllocatePool (Dev->TxMaxPending * sizeof *Dev->TxFreeStack); if (Dev->TxFreeStack == NULL) { return EFI_OUT_OF_RESOURCES; } + // + // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on + // VIRTIO_NET_F_MRG_RXBUF, which we never negotiate. + // + TxSharedReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ? + sizeof Dev->TxSharedReq.Legacy : + sizeof Dev->TxSharedReq; + for (PktIdx = 0; PktIdx < Dev->TxMaxPending; ++PktIdx) { UINT16 DescIdx; DescIdx = (UINT16) (2 * PktIdx); Dev->TxFreeStack[PktIdx] = DescIdx; // // For each possibly pending packet, lay out the descriptor for the common // (unmodified by the host) virtio-net request header. // Dev->TxRing.Desc[DescIdx].Addr = (UINTN) &Dev->TxSharedReq; - Dev->TxRing.Desc[DescIdx].Len = sizeof Dev->TxSharedReq; + Dev->TxRing.Desc[DescIdx].Len = (UINT32) TxSharedReqSize; Dev->TxRing.Desc[DescIdx].Flags = VRING_DESC_F_NEXT; Dev->TxRing.Desc[DescIdx].Next = (UINT16) (DescIdx + 1); // // The second descriptor of each pending TX packet is updated on the fly, // but it always terminates the descriptor chain of the packet. // Dev->TxRing.Desc[DescIdx + 1].Flags = 0; } // // virtio-0.9.5, Appendix C, Packet Transmission // - Dev->TxSharedReq.Flags = 0; - Dev->TxSharedReq.GsoType = VIRTIO_NET_HDR_GSO_NONE; + Dev->TxSharedReq.Legacy.Flags = 0; + Dev->TxSharedReq.Legacy.GsoType = VIRTIO_NET_HDR_GSO_NONE; + + // + // For VirtIo 1.0 only -- the field exists, but it is unused + // + Dev->TxSharedReq.NumBuffers = 0; // // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device // MemoryFence (); Dev->TxLastUsed = *Dev->TxRing.Used.Idx; ASSERT (Dev->TxLastUsed == 0); @@ -219,27 +233,36 @@ STATIC EFI_STATUS EFIAPI VirtioNetInitRx ( IN OUT VNET_DEV *Dev ) { EFI_STATUS Status; + UINTN VirtioNetReqSize; UINTN RxBufSize; UINT16 RxAlwaysPending; UINTN PktIdx; UINT16 DescIdx; UINT8 *RxPtr; // + // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on + // VIRTIO_NET_F_MRG_RXBUF, which we never negotiate. + // + VirtioNetReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ? + sizeof (VIRTIO_NET_REQ) : + sizeof (VIRTIO_1_0_NET_REQ); + + // // For each incoming packet we must supply two descriptors: // - the recipient for the virtio-net request header, plus // - the recipient for the network data (which consists of Ethernet header // and Ethernet payload). // - RxBufSize = sizeof (VIRTIO_NET_REQ) + + RxBufSize = VirtioNetReqSize + (Dev->Snm.MediaHeaderSize + Dev->Snm.MaxPacketSize); // // Limit the number of pending RX packets if the queue is big. The division // by two is due to the above "two descriptors per packet" trait. // RxAlwaysPending = (UINT16) MIN (Dev->RxRing.QueueSize / 2, VNET_MAX_PENDING); @@ -276,22 +299,21 @@ VirtioNetInitRx ( // Dev->RxRing.Avail.Ring[PktIdx] = DescIdx; // // 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].Len = sizeof (VIRTIO_NET_REQ); + 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; Dev->RxRing.Desc[DescIdx].Addr = (UINTN) RxPtr; - Dev->RxRing.Desc[DescIdx].Len = (UINT32) (RxBufSize - - sizeof (VIRTIO_NET_REQ)); + Dev->RxRing.Desc[DescIdx].Len = (UINT32) (RxBufSize - VirtioNetReqSize); Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE; RxPtr += Dev->RxRing.Desc[DescIdx++].Len; } // // virtio-0.9.5, 2.4.1.3 Updating the Index Field //