Skip to content

Comments

fix(virtio): KVM receive path#658

Merged
veqcc merged 1 commit intomainfrom
fix/virtio_kvm_recv_fix
Nov 20, 2025
Merged

fix(virtio): KVM receive path#658
veqcc merged 1 commit intomainfrom
fix/virtio_kvm_recv_fix

Conversation

@Enigamict
Copy link
Contributor

@Enigamict Enigamict commented Nov 7, 2025

Description

First, Under QEMU, both transmit and receive paths worked correctly, but under KVM, only transmission was functional reception failed because no notifications were observed in the host’s used ring.

As a cause, vio_populate_rx_mbufs() was not called before setting the DRIVER_OK status bit.

  1. From the host’s perspective, the used ring was initialized but the RX buffer queue remained empty.

  2. When attaching, the host could not place incoming packets into the RX queue, leading to unstable or nonfunctional RX under KVM.

Reordered the initialization sequence in virtio_attach_finish()

queue setup → RX populate → kick → DRIVER_OK

This ensures that RX buffers are populated before notifying the host (DRIVER_OK), so that incoming data can be received immediately after device setup.

Related links

How was this PR tested?

Notes for reviewers

Signed-off-by: Enigamict <atsuki.takata@tier4.jp>
@veqcc
Copy link
Contributor

veqcc commented Nov 19, 2025

@Enigamict
The code looks good.
Do you have a corresponding OpenBSD/FreeBSD implementation?

@Enigamict
Copy link
Contributor Author

Enigamict commented Nov 19, 2025

@veqcc
Thank you for your review.
How to FreeBSD prepares the RX queue.

vtnet_init_locked() [1]. That is called when initializing the interface; inside it, vtnet_reinit() [2] handles the Virtio reinitialization. Within vtnet_reinit(), the functions vtnet_init_rxtx_queues() [3] and vtnet_init_rx_queues() [4] prepare the RX buffers, which mirrors the Awkernel path where virtio_attach_finish() sets up each queue via virtio_pci_setup_queue() before touching the RX rings. vtnet_init_rxtx_queues() [5] does the RX/TX virtqueue work.

The key part is the RX-side preparation. vtnet_rxq_populate() [6] corresponds to should_notify.push(rx.vio_populate_rx_mbufs());, i.e., it actually populates the virtqueue with RX buffers via vtnet_rxq_new_buf() [7], just as Awkernel’s rx.vio_populate_rx_mbufs() fills the ring. Once RX buffers have been placed on the ring, virtqueue_notify() [8] is used to notify the host. He same step Awkernel implements by looping over should_notify and calling self.virtio_notify(rx_vq_idx) for the queues that need a kick.

[1]https://github.com/freebsd/freebsd-src/blob/9b0102837e305ca75de2bc14d284f786a33f9a6a/sys/dev/virtio/network/if_vtnet.c#L3489
[2]https://github.com/freebsd/freebsd-src/blob/9b0102837e305ca75de2bc14d284f786a33f9a6a/sys/dev/virtio/network/if_vtnet.c#L3452
[3]https://github.com/freebsd/freebsd-src/blob/9b0102837e305ca75de2bc14d284f786a33f9a6a/sys/dev/virtio/network/if_vtnet.c#L3481
[4]https://github.com/freebsd/freebsd-src/blob/9b0102837e305ca75de2bc14d284f786a33f9a6a/sys/dev/virtio/network/if_vtnet.c#L3375
[5]https://github.com/freebsd/freebsd-src/blob/9b0102837e305ca75de2bc14d284f786a33f9a6a/sys/dev/virtio/network/if_vtnet.c#L3371
[6]https://github.com/freebsd/freebsd-src/blob/9b0102837e305ca75de2bc14d284f786a33f9a6a/sys/dev/virtio/network/if_vtnet.c#L1493
[7]https://github.com/freebsd/freebsd-src/blob/9b0102837e305ca75de2bc14d284f786a33f9a6a/sys/dev/virtio/network/if_vtnet.c#L1507
[8]https://github.com/freebsd/freebsd-src/blob/9b0102837e305ca75de2bc14d284f786a33f9a6a/sys/dev/virtio/network/if_vtnet.c#L1514

@veqcc
Copy link
Contributor

veqcc commented Nov 20, 2025

@Enigamict
Thank you for your explanation 👍

@veqcc veqcc merged commit e9ef59c into main Nov 20, 2025
2 checks passed
@veqcc veqcc deleted the fix/virtio_kvm_recv_fix branch November 20, 2025 01:44
@ytakano ytakano linked an issue Jan 8, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support VirtIO network interface

2 participants