Skip to content

drivers/virtio: use virtqueue_nused() to check pending buffers#18290

Merged
xiaoxiang781216 merged 1 commit intoapache:masterfrom
CV-Bowen:virtio-irq
Jan 31, 2026
Merged

drivers/virtio: use virtqueue_nused() to check pending buffers#18290
xiaoxiang781216 merged 1 commit intoapache:masterfrom
CV-Bowen:virtio-irq

Conversation

@CV-Bowen
Copy link
Contributor

Summary

This PR optimizes the VirtIO MMIO and PCI interrupt handlers by replacing direct access to virtqueue internal fields with the proper virtqueue_nused() API.

Why this change is needed

The current implementation directly accesses virtqueue internal fields (vq->vq_used_cons_idx and vq->vq_ring.used->idx) to determine if there are pending buffers to process. This approach has several issues:

  1. Breaks encapsulation: Direct field access bypasses the virtqueue abstraction layer
  2. Cache coherency issues: The direct comparison doesn't handle cached memory scenarios properly
  3. Maintainability: Changes to virtqueue internals would require updates in multiple places

What this PR does

  • Replaces vq->vq_used_cons_idx != vq->vq_ring.used->idx with virtqueue_nused(vq) > 0
  • Reorders the condition to check vq->callback != NULL first (short-circuit optimization)
  • Applies the same fix to both virtio-mmio.c and virtio-pci.c

Impact

  • Stability: Improves reliability when using cached memory for virtqueues
  • Compatibility: No API changes, fully backward compatible
  • Code Quality: Better encapsulation and maintainability

Testing

Build Verification

# Build for qemu-armv8a with virtio support
cmake -B cmake_out -DBOARD_CONFIG=qemu-armv8a:netnsh -GNinja
cmake --build cmake_out

Runtime Testing

Tested on QEMU ARM64 with virtio-net device:

VirtIO-MMIO Test

❯ /data/software/qemu/qemu-9.2.3/build/qemu-system-aarch64 -cpu cortex-a53 -nographic \
     -machine virt,virtualization=on,gic-version=3 \
     -chardev stdio,id=con,mux=on -serial chardev:con \
     -global virtio-mmio.force-legacy=false \
     -device virtio-serial-device,bus=virtio-mmio-bus.0 \
     -chardev socket,telnet=on,host=127.0.0.1,port=3450,server=on,wait=off,id=foo \
     -device virtconsole,chardev=foo \
     -device virtio-rng-device,bus=virtio-mmio-bus.1 \
     -netdev user,id=u1,hostfwd=tcp:127.0.0.1:10023-10.0.2.15:23,hostfwd=tcp:127.0.0.1:15001-10.0.2.15:5001 \
     -device virtio-net-device,netdev=u1,bus=virtio-mmio-bus.2 \
     -drive file=./mydisk-1gb.img,if=none,format=raw,id=hd \
     -device virtio-blk-device,bus=virtio-mmio-bus.3,drive=hd \
     -fsdev local,security_model=none,id=fsdev0,path=/data/project/code/apache/nuttx \
     -device virtio-9p-device,id=fs0,fsdev=fsdev0,mount_tag=host \
     -mon chardev=con,mode=readline -kernel ./nuttx/cmake_out/v8a_netnsh/nuttx \
     -gdb tcp::7777

[    0.340000] pci_scan_bus: pci_scan_bus for bus 0
[    0.340000] pci_scan_bus: class = 00000600, hdr_type = 00000000
[    0.340000] pci_scan_bus: 00:00 [1b36:0008]
[    0.350000] pci_setup_device: pbar0 set bad mask
[    0.350000] pci_setup_device: pbar1 set bad mask
[    0.350000] pci_setup_device: pbar2 set bad mask
[    0.350000] pci_setup_device: pbar3 set bad mask
[    0.350000] pci_setup_device: pbar4 set bad mask
[    0.350000] pci_setup_device: pbar5 set bad mask
telnetd [4:100]

NuttShell (NSH) NuttX-12.12.0
nsh> 
nsh> 
nsh> ifconfig
eth0    Link encap:Ethernet HWaddr 00:e0:de:ad:be:ef at RUNNING mtu 1500
        inet addr:10.0.2.15 DRaddr:10.0.2.2 Mask:255.255.255.0

             IPv4   TCP   UDP  ICMP
Received     0000  0000  0000  0000
Dropped      0000  0000  0000  0000
  IPv4        VHL: 0000   Frg: 0000
  Checksum   0000  0000  0000  ----
  TCP         ACK: 0000   SYN: 0000
              RST: 0000  0000
  Type       0000  ----  ----  0000
Sent         0000  0000  0000  0000
  Rexmit     ----  0000  ----  ----
nsh> iperf -s -i 1
     IP: 10.0.2.15

 mode=tcp-server sip=10.0.2.15:5001,dip=0.0.0.0:5001, interval=1, time=0
accept: 10.0.2.2:33612

           Interval         Transfer         Bandwidth

   0.00-   1.01 sec    9500924 Bytes   75.25 Mbits/sec
   1.01-   2.02 sec    9568256 Bytes   75.79 Mbits/sec
   2.02-   3.03 sec    9568256 Bytes   75.79 Mbits/sec
   3.03-   4.04 sec    9551872 Bytes   75.66 Mbits/sec
   4.04-   5.05 sec    9519104 Bytes   75.40 Mbits/sec
   5.05-   6.06 sec    9519104 Bytes   75.40 Mbits/sec
   6.06-   7.07 sec    9517480 Bytes   75.39 Mbits/sec
   7.07-   8.08 sec    9519104 Bytes   75.40 Mbits/sec
   8.08-   9.09 sec    9584640 Bytes   75.92 Mbits/sec
   9.09-  10.10 sec    9583980 Bytes   75.91 Mbits/sec
closed by the peer: 10.0.2.2:33612
iperf exit
nsh> uname -a
NuttX  12.12.0 de88cf07345-dirty Jan 31 2026 00:19:08 arm64 qemu-armv8a
nsh> 
nsh> 
nsh>

VirtIO-PCI Test

qemu-system-aarch64 -cpu cortex-a53 -nographic \
     -machine virt,virtualization=on,gic-version=3 \
     -chardev stdio,id=con,mux=on -serial chardev:con \
     -device virtio-rng-pci \
     -netdev user,id=u1,hostfwd=tcp:127.0.0.1:10023-10.0.2.15:23,hostfwd=tcp:127.0.0.1:15001-10.0.2.15:5001 \
     -device virtio-net-pci,netdev=u1 \
     -mon chardev=con,mode=readline -kernel ./nuttx/cmake_out/v8a_netnsh/nuttx \
     -gdb tcp::7777
[    0.310000] pci_scan_bus: pci_scan_bus for bus 0
[    0.320000] pci_scan_bus: class = 00000600, hdr_type = 00000000
[    0.320000] pci_scan_bus: 00:00 [1b36:0008]
[    0.320000] pci_setup_device: pbar0 set bad mask
[    0.320000] pci_setup_device: pbar1 set bad mask
[    0.320000] pci_setup_device: pbar2 set bad mask
[    0.320000] pci_setup_device: pbar3 set bad mask
[    0.320000] pci_setup_device: pbar4 set bad mask
[    0.320000] pci_setup_device: pbar5 set bad mask
[    0.320000] pci_scan_bus: class = 000000ff, hdr_type = 00000000
[    0.330000] pci_scan_bus: 00:08 [1af4:1005]
[    0.330000] pci_setup_device: pbar0: mask64=fffffffe 32bytes
[    0.330000] pci_setup_device: pbar1: mask64=fffffff0 4096bytes
[    0.330000] pci_setup_device: pbar2 set bad mask
[    0.330000] pci_setup_device: pbar3 set bad mask
[    0.330000] pci_setup_device: pbar4: mask64=fffffffffffffff0 16384bytes
[    0.330000] pci_scan_bus: class = 00000200, hdr_type = 00000000
[    0.330000] pci_scan_bus: 00:10 [1af4:1000]
[    0.330000] pci_setup_device: pbar0: mask64=fffffffe 32bytes
[    0.330000] pci_setup_device: pbar1: mask64=fffffff0 4096bytes
[    0.330000] pci_setup_device: pbar2 set bad mask
[    0.340000] pci_setup_device: pbar3 set bad mask
[    0.340000] pci_setup_device: pbar4: mask64=fffffffffffffff0 16384bytes
telnetd [4:100]

NuttShell (NSH) NuttX-12.12.0
nsh> 
nsh> 
nsh> 
nsh> iperf -s -i 1
     IP: 10.0.2.15

 mode=tcp-server sip=10.0.2.15:5001,dip=0.0.0.0:5001, interval=1, time=0
accept: 10.0.2.2:34508

           Interval         Transfer         Bandwidth

   0.00-   1.01 sec    1680460 Bytes   13.31 Mbits/sec
   1.01-   2.02 sec    1679000 Bytes   13.30 Mbits/sec
   2.02-   3.03 sec    1712580 Bytes   13.56 Mbits/sec
   3.03-   4.04 sec    1679000 Bytes   13.30 Mbits/sec
   4.04-   5.05 sec    1712580 Bytes   13.56 Mbits/sec
   5.05-   6.06 sec    1679000 Bytes   13.30 Mbits/sec
   6.06-   7.07 sec    1712580 Bytes   13.56 Mbits/sec
   7.07-   8.08 sec    1679000 Bytes   13.30 Mbits/sec
   8.08-   9.09 sec    1712580 Bytes   13.56 Mbits/sec
   9.09-  10.10 sec    1679000 Bytes   13.30 Mbits/sec
  10.10-  11.11 sec    1712580 Bytes   13.56 Mbits/sec
  11.11-  12.12 sec    1679000 Bytes   13.30 Mbits/sec
  12.12-  13.13 sec    1712580 Bytes   13.56 Mbits/sec
closed by the peer: 10.0.2.2:34508
iperf exit
nsh> uname -a
NuttX  12.12.0 de88cf07345-dirty Jan 31 2026 00:19:08 arm64 qemu-armv8a
nsh>

Replace direct virtqueue internal field access with virtqueue_nused()
API to check for pending buffers in interrupt handlers. This improves
code maintainability and handles cached memory scenarios correctly.

Signed-off-by: Bowen Wang <wangbowen6@xiaomi.com>
@github-actions github-actions bot added Area: Drivers Drivers issues Size: XS The size of the change in this PR is very small labels Jan 30, 2026
@xiaoxiang781216 xiaoxiang781216 merged commit 3237e25 into apache:master Jan 31, 2026
40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: Drivers Drivers issues Size: XS The size of the change in this PR is very small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants