On Wed, 4 Sep 2024 15:21:28 +0800, =?utf-8?b?5paH5Y2a5p2O?= <liwenbo.martin@xxxxxxxxxxxxx> wrote: > 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. > > Thanks. > > On Wed, Sep 4, 2024 at 2:46 PM Xuan Zhuo <xuanzhuo@xxxxxxxxxxxxxxxxx> wrote: > > > > 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 > > > >