Re: [External] Re: [PATCH v2] virtio_net: Fix mismatched buf address when unmapping for small packets
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: 2024-09-04 10:57:47
Also in:
lkml, virtualization
On Wed, Sep 04, 2024 at 03:30:02PM +0800, Xuan Zhuo wrote:
On Wed, 4 Sep 2024 15:21:28 +0800, =?utf-8?b?5paH5Y2a5p2O?= [off-list ref] wrote:quoted
When SWIOTLB is enabled, a DMA map will allocate a bounce buffer for real DMA operations, and when unmapping, SWIOTLB copies the content in the bounce buffer to the driver-allocated buffer (the `buf` variable). Such copy only synchronizes data in the buffer range, not the whole page. So we should give the correct offset for DMA unmapping.I see. But I think we should pass the "correct" buf to virtio core as the "data" by virtqueue_add_inbuf_ctx(). In the merge mode, we pass the pointer that points to the virtnet header. In the small mode, we pass the pointer that points to the virtnet header - offset. But this is not the only problem, we try to get the virtnet header by the buf inside receive_buf(before receive_small). flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags; So I think it is time to unify the buf that passed to the virtio core into a pointer pointed to the virtnet header. Thanks.
Hard to say without seeing what is proposed, but I think data pointer is opaque to virtio, it does not have to point to anything specific - just !NULL.
quoted
Thanks. On Wed, Sep 4, 2024 at 2:46 PM Xuan Zhuo [off-list ref] wrote:quoted
On Wed, 4 Sep 2024 14:10:09 +0800, Wenbo Li [off-list ref]wrote:quoted
quoted
Currently, the virtio-net driver will perform a pre-dma-mapping for small or mergeable RX buffer. But for small packets, a mismatchedaddressquoted
quoted
without VIRTNET_RX_PAD and xdp_headroom is used for unmapping.Will used virt_to_head_page(), so could you say more about it? struct page *page = virt_to_head_page(buf); Thanks.quoted
That will result in unsynchronized buffers when SWIOTLB is enabled, for example, when running as a TDX guest. This patch handles small and mergeable packets separately and fixes the mismatched buffer address. Changes from v1: Use ctx to get xdp_headroom. Fixes: 295525e29a5b ("virtio_net: merge dma operations when fillingmergeable buffers")quoted
quoted
Signed-off-by: Wenbo Li <redacted> Signed-off-by: Jiahui Cen <redacted> Signed-off-by: Ying Fang <redacted> --- drivers/net/virtio_net.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-)diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c6af18948..cbc3c0ae4 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c@@ -891,6 +891,23 @@ static void *virtnet_rq_get_buf(structreceive_queue *rq, u32 *len, void **ctx)quoted
quoted
return buf; } +static void *virtnet_rq_get_buf_small(struct receive_queue *rq, + u32 *len, + void **ctx, + unsigned int header_offset) +{ + void *buf; + unsigned int xdp_headroom; + + buf = virtqueue_get_buf_ctx(rq->vq, len, ctx); + if (buf) { + xdp_headroom = (unsigned long)*ctx; + virtnet_rq_unmap(rq, buf + VIRTNET_RX_PAD + xdp_headroom,*len);quoted
quoted
+ } + + return buf; +} + static void virtnet_rq_init_one_sg(struct receive_queue *rq, void*buf, u32 len)quoted
quoted
{ struct virtnet_rq_dma *dma;@@ -2692,13 +2709,23 @@ static int virtnet_receive_packets(structvirtnet_info *vi,quoted
quoted
int packets = 0; void *buf; - if (!vi->big_packets || vi->mergeable_rx_bufs) { + if (vi->mergeable_rx_bufs) { void *ctx; while (packets < budget && (buf = virtnet_rq_get_buf(rq, &len, &ctx))) { receive_buf(vi, rq, buf, len, ctx, xdp_xmit,stats);quoted
quoted
packets++; } + } else if (!vi->big_packets) { + void *ctx; + unsigned int xdp_headroom = virtnet_get_headroom(vi); + unsigned int header_offset = VIRTNET_RX_PAD +xdp_headroom;quoted
quoted
+ + while (packets < budget && + (buf = virtnet_rq_get_buf_small(rq, &len, &ctx,header_offset))) {quoted
quoted
+ receive_buf(vi, rq, buf, len, ctx, xdp_xmit,stats);quoted
quoted
+ packets++; + } } else { while (packets < budget && (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) { -- 2.20.1