On Wed, 4 Sep 2024 14:10:09 +0800, Wenbo Li <liwenbo.martin@xxxxxxxxxxxxx> wrote: > Currently, the virtio-net driver will perform a pre-dma-mapping for > small or mergeable RX buffer. But for small packets, a mismatched address > 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. > > 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 filling mergeable buffers") > Signed-off-by: Wenbo Li <liwenbo.martin@xxxxxxxxxxxxx> > Signed-off-by: Jiahui Cen <cenjiahui@xxxxxxxxxxxxx> > Signed-off-by: Ying Fang <fangying.tommy@xxxxxxxxxxxxx> > --- > 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(struct receive_queue *rq, u32 *len, void **ctx) > 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); > + } > + > + return buf; > +} > + > static void virtnet_rq_init_one_sg(struct receive_queue *rq, void *buf, u32 len) > { > struct virtnet_rq_dma *dma; > @@ -2692,13 +2709,23 @@ static int virtnet_receive_packets(struct virtnet_info *vi, > 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); > 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; > + > + while (packets < budget && > + (buf = virtnet_rq_get_buf_small(rq, &len, &ctx, header_offset))) { > + receive_buf(vi, rq, buf, len, ctx, xdp_xmit, stats); > + packets++; > + } > } else { > while (packets < budget && > (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) { > -- > 2.20.1 >