[PATCH net v2 0/3] virtio_net: AF_XDP zero-copy fixes for arm64 and suspend

From: Haishuang Yan

Date: Sun Nov 08 2026 - 06:39:54 EST


Three AF_XDP zero-copy fixes for virtio_net.

Patch 1: on arm64, binding a zero-copy socket fails with -ENOMEM and a
"rejecting DMA map of vmalloc memory" warning whenever the device uses
the DMA API (e.g. VIRTIO_F_ACCESS_PLATFORM), because the static TX
header lives in the kernel image, which arm64 maps in the vmalloc area.

Patch 2: removing XDP can leave a zero-copy pool bound to a queue above
curr_queue_pairs. Closing the socket then fails in the driver, and the
queue is refilled from the freed pool.

Patch 3: freeze frees the rx/tx queues while the sockets stay bound in
the xsk core. The driver state of the pools is leaked, and closing the
socket after resume hits a "Missing register" warning and a NULL
pointer dereference in xp_dma_unmap(). v2 keeps the pools DMA mapped
across suspend and only moves the driver state to the new queues.

Freeze also drops the XDP program of virtio_net, so it has to be
attached again after resume. That is an older issue and this series
does not change it.

Testing used x86_64 KASAN kernels in QEMU/KVM (q35, intel-iommu,
virtio-net-pci with iommu_platform=on, x-pcie-pm-init=off) with a
small /init that binds an XDP_ZEROCOPY socket, redirects to it with an
XSKMAP program, and sends an ARP request through the TX ring and waits
for the reply on the RX ring, before suspend and after each of two
suspend cycles (pm_test=devices), then closes the socket:

- net: no TX or RX on the socket after resume, and an oops when it is
closed. With a socket bound to an XDP queue and XDP removed, closing
it gives "Failed to disable zero-copy!" and a KASAN use-after-free in
xp_alloc_batch().
- v1: passes with an aligned umem, but with an unaligned umem nothing
is received after resume. The XDP queue case behaves as on net.
- v2: all cases pass, without warnings, also with an unaligned umem and
with a suspend cycle between removing XDP and closing the socket.

The test program is not part of the series; I can send it if useful.
Patch 1 is unchanged since v1, where it was tested on arm64 (QEMU TCG,
virt) with a KASAN kernel; arm64 was not tested again for v2. Real
hibernation and multiqueue traffic were not tested.

The issues were found with the help of an AI coding assistant.

Changes in v2:
- Patch 1: drop the sentence about cache lines from the changelog
(Sashiko).
- New patch 2, for a pool left on a queue above curr_queue_pairs
(Sashiko).
- Patch 3: keep the pools DMA mapped across suspend and set the driver
state up on the new queues before NAPI is enabled, instead of
disabling and enabling the pools while their sockets are still bound
(Sashiko). This avoids a race with the RX path on freeze, stale DMA
addresses with an unaligned umem, and transmitting before the TX
header is mapped on restore.
- Rebased on net 30c71476d842.

v1: https://lore.kernel.org/netdev/20261107125723.33547-1-yanhaishuang@xxxxxxxxxxxxxxxxxxxx/

Haishuang Yan (3):
virtio_net: Don't DMA map the kernel image for the AF_XDP TX header
virtio_net: Disable AF_XDP pools on queues above curr_queue_pairs
virtio_net: Keep AF_XDP zero-copy pools bound across suspend

drivers/net/virtio_net.c | 177 ++++++++++++++++++++++++++++++++++++---
1 file changed, 166 insertions(+), 11 deletions(-)


base-commit: 30c71476d842b094651bd7712f6c8ee8716147d0
--
2.43.0