CV-Bowen opened a new pull request, #18289:
URL: https://github.com/apache/nuttx/pull/18289
## Summary
This PR contains a series of improvements and fixes for the vhost (Virtual
Host) driver framework in NuttX. The changes enhance the vhost API, fix build
issues, and simplify Kconfig configuration.
### Changes Overview
| Commit | Description |
|--------|-------------|
| 1 | Add vhost helper macros for feature and config access |
| 2 | Add `vhost_get_vq_buffers()` to collect scatter-gather buffers |
| 3 | Auto-select parent config from sub-drivers (virtio/vhost) |
| 4 | Use `MSEC2TICK` for deferred probe period |
| 5 | Add missing `SCHED_WORKQUEUE` dependency |
| 6 | Allow common virtio helpers to be used by vhost |
## Detailed Changes
### 1. drivers/vhost: add vhost helper macros for feature and config access
Add vhost wrapper macros that map to the corresponding virtio helper
functions:
- `vhost_has_feature`: check if a feature is supported
- `vhost_read_config_member`: read a config structure member
- `vhost_write_config_member`: write a config structure member
Also include `virtio-config.h` header to support these macros.
### 2. drivers/vhost: add vhost_get_vq_buffers() to collect scatter-gather
buffers
Add `vhost_get_vq_buffers()` API to retrieve all chained buffers from a
virtqueue in one call. This simplifies handling of scatter-gather I/O where
data spans multiple descriptors.
The function populates an array of `virtqueue_buf` structures with buffer
pointers and lengths, returning the descriptor head index on success.
### 3. drivers/virtio and vhost: auto-select parent config from sub-drivers
Change `DRIVERS_VIRTIO` and `DRIVERS_VHOST` from `menuconfig` to hidden
`config` options. Each virtio/vhost sub-driver now automatically selects its
parent config, eliminating the need to manually enable `DRIVERS_VIRTIO` or
`DRIVERS_VHOST` in defconfig files.
This simplifies board configuration by removing redundant
`CONFIG_DRIVERS_VIRTIO` entries from affected defconfig files.
### 4. drivers/vhost: use MSEC2TICK for deferred probe period
Convert `VHOST_DEFERED_PROBE_PERIOD` from a raw value to use `MSEC2TICK()`
macro, ensuring the delay is correctly converted from milliseconds to system
ticks regardless of the configured tick rate.
### 5. drivers/vhost: add missing SCHED_WORKQUEUE dependency
The vhost driver uses `work_queue()` for deferred probe but was missing the
`SCHED_WORKQUEUE` Kconfig dependency, causing link errors on boards that don't
enable workqueue by default.
### 6. include/nuttx/virtio: allow common virtio helpers to be used by vhost
Move common virtio inline functions (`virtqueue_kick_lock`,
`virtio_malloc_buf`, `virtio_zalloc_buf`, etc.) from `CONFIG_DRIVERS_VIRTIO`
guard to `CONFIG_OPENAMP` guard. This allows vhost drivers to reuse these
helper functions without requiring the full virtio driver framework.
The `virtio_driver` structure and driver registration APIs remain under
`CONFIG_DRIVERS_VIRTIO` as they are specific to virtio device drivers.
## Impact
- **Stability**: No impact - these are improvements and bug fixes
- **Compatibility**: No breaking changes - existing code continues to work
- **Code Quality**: Improved - cleaner Kconfig structure, better code reuse
- **Breaking Changes**: None
## Testing
qemu-armv8a rpproxy and rpserver
```c
❯ qemu-system-aarch64 -cpu cortex-a53 -nographic \
-machine virt,virtualization=on,gic-version=3 \
-chardev stdio,id=con,mux=on -serial chardev:con \
-object
memory-backend-file,discard-data=on,id=shmmem-shmem0,mem-path=/dev/shm/my_shmem0,size=4194304,share=yes
\
-device ivshmem-plain,id=shmem0,memdev=shmmem-shmem0,addr=0xb \
-device virtio-serial-device,bus=virtio-mmio-bus.0 \
-chardev socket,path=/tmp/rpmsg_port_uart_socket,server=on,wait=off,id=foo \
-device virtconsole,chardev=foo \
-mon chardev=con,mode=readline -kernel ./nuttx/cmake_out/v8a_server/nuttx \
-gdb tcp::7775
[ 0.000000] [ 0] [ INFO] [server] pci_register_rptun_ivshmem_driver:
Register ivshmem driver, id=0, cpuname=proxy, master=1
[ 0.000000] [ 3] [ INFO] [server] pci_scan_bus: pci_scan_bus for bus 0
[ 0.000000] [ 3] [ INFO] [server] pci_scan_bus: class = 00000600,
hdr_type = 00000000
[ 0.000000] [ 3] [ INFO] [server] pci_scan_bus: 00:00 [1b36:0008]
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar0 set bad mask
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar1 set bad mask
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar2 set bad mask
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar3 set bad mask
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar4 set bad mask
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar5 set bad mask
[ 0.000000] [ 3] [ INFO] [server] pci_scan_bus: class = 00000200,
hdr_type = 00000000
[ 0.000000] [ 3] [ INFO] [server] pci_scan_bus: 00:08 [1af4:1000]
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar0:
mask64=fffffffe 32bytes
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar1:
mask64=fffffff0 4096bytes
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar2 set bad mask
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar3 set bad mask
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar4:
mask64=fffffffffffffff0 16384bytes
[ 0.000000] [ 3] [ INFO] [server] pci_scan_bus: class = 00000500,
hdr_type = 00000000
[ 0.000000] [ 3] [ INFO] [server] pci_scan_bus: 00:58 [1af4:1110]
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar0:
mask64=fffffff0 256bytes
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar1 set bad mask
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar2:
mask64=fffffffffffffff0 4194304bytes
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar4 set bad mask
[ 0.000000] [ 3] [ INFO] [server] pci_setup_device: pbar5 set bad mask
[ 0.000000] [ 3] [ INFO] [server] ivshmem_probe: shmem addr=0x8000400000
size=4194304 reg=0x10001000
[ 0.000000] [ 3] [ INFO] [server] rptun_ivshmem_probe: shmem
addr=0x8000400000 size=4194304
NuttShell (NSH) NuttX-12.10.0
server>
server>
server> [ 0.000000] [ 0] [ INFO] [proxy]
pci_register_rptun_ivshmem_driver: Register ivshmem driver, id=0,
cpuname=server, master=0
[ 0.000000] [ 3] [ INFO] [proxy] pci_scan_bus: pci_scan_bus for bus 0
[ 0.000000] [ 3] [ INFO] [proxy] pci_scan_bus: class = 00000600,
hdr_type = 00000000
[ 0.000000] [ 3] [ INFO] [proxy] pci_scan_bus: 00:00 [1b36:0008]
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar0 set bad mask
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar1 set bad mask
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar2 set bad mask
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar3 set bad mask
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar4 set bad mask
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar5 set bad mask
[ 0.000000] [ 3] [ INFO] [proxy] pci_scan_bus: class = 00000200,
hdr_type = 00000000
[ 0.000000] [ 3] [ INFO] [proxy] pci_scan_bus: 00:08 [1af4:1000]
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar0:
mask64=fffffffe 32bytes
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar1:
mask64=fffffff0 4096bytes
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar2 set bad mask
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar3 set bad mask
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar4:
mask64=fffffffffffffff0 16384bytes
[ 0.000000] [ 3] [ INFO] [proxy] pci_scan_bus: class = 00000500,
hdr_type = 00000000
[ 0.000000] [ 3] [ INFO] [proxy] pci_scan_bus: 00:58 [1af4:1110]
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar0:
mask64=fffffff0 256bytes
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar1 set bad mask
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar2:
mask64=fffffffffffffff0 4194304bytes
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar4 set bad mask
[ 0.000000] [ 3] [ INFO] [proxy] pci_setup_device: pbar5 set bad mask
[ 0.000000] [ 3] [ INFO] [proxy] ivshmem_probe: shmem addr=0x8000400000
size=4194304 reg=0x10001000
[ 0.000000] [ 3] [ INFO] [proxy] rptun_ivshmem_probe: shmem
addr=0x8000400000 size=4194304
[ 0.000000] [ 3] [ INFO] [proxy] rptun_ivshmem_probe: Start the wdog
server>
server>
server>
server> ps
TID PID PPID PRI POLICY TYPE NPX STATE EVENT SIGMASK
STACK USED FILLED COMMAND
0 0 0 0 FIFO Kthread - Ready
0000000000000000 0008144 0001792 22.0% Idle_Task
1 0 0 192 FIFO Kthread - Waiting Semaphore
0000000000000000 0008080 0001328 16.4% hpwork 0x4047bc60 0x4047bce0
2 0 0 100 FIFO Kthread - Waiting Semaphore
0000000000000000 0008080 0001328 16.4% lpwork 0x4047bd10 0x4047bd90
5 0 0 224 FIFO Kthread - Waiting Semaphore
0000000000000000 0008080 0002384 29.5% rpmsg-uart-rx proxy2 0x404b1048
6 0 0 224 FIFO Kthread - Waiting Event
0000000000000000 0008080 0001856 22.9% rpmsg-uart-tx proxy2 0x404b1048
7 7 0 100 FIFO Task - Running
0000000000000000 0008112 0004176 51.4% nsh_main
8 0 0 224 FIFO Kthread - Waiting Semaphore
0000000000000000 0008080 0001920 23.7% rpmsg-virtio proxy 0x40495b38
server>
server>
server> rpmsg dump all
[ 0.000000] [ 7] [ EMERG] [server] Local: server Remote: proxy Headrx 7
[ 0.000000] [ 7] [ EMERG] [server] Dump rpmsg info between cpu (master:
yes)server <==> proxy:
[ 0.000000] [ 7] [ EMERG] [server] rpmsg vq RX:
[ 0.000000] [ 7] [ EMERG] [server] VQ: rx_vq - size=8; free=0; queued=0;
desc_head_idx=32768; available_idx=0; avail.idx=15; used_cons_idx=7;
used.idx=7; avail.flags=0x0; used.flags=0x1
[ 0.000000] [ 7] [ EMERG] [server] rpmsg vq TX:
[ 0.000000] [ 7] [ EMERG] [server] VQ: tx_vq - size=8; free=6; queued=0;
desc_head_idx=2; available_idx=0; avail.idx=5; used_cons_idx=3; used.idx=5;
avail.flags=0x1; used.flags=0x0
[ 0.000000] [ 7] [ EMERG] [server] rpmsg ept list:
[ 0.000000] [ 7] [ EMERG] [server] ept NS
[ 0.000000] [ 7] [ EMERG] [server] ept rpmsg-sensor
[ 0.000000] [ 7] [ EMERG] [server] ept rpmsg-ping
[ 0.000000] [ 7] [ EMERG] [server] ept rpmsg-syslog
[ 0.000000] [ 7] [ EMERG] [server] rpmsg buffer list:
[ 0.000000] [ 7] [ EMERG] [server] RX buffer, total 8, pending 0
[ 0.000000] [ 7] [ EMERG] [server] TX buffer, total 8, pending 0
[ 0.000000] [ 7] [ EMERG] [server] Remote: proxy2 state: 1
[ 0.000000] [ 7] [ EMERG] [server] ept NS
[ 0.000000] [ 7] [ EMERG] [server] ept rpmsg-sensor
[ 0.000000] [ 7] [ EMERG] [server] ept rpmsg-ping
[ 0.000000] [ 7] [ EMERG] [server] rpmsg_port queue RX: {used: 0, avail:
8}
[ 0.000000] [ 7] [ EMERG] [server] rpmsg buffer list:
[ 0.000000] [ 7] [ EMERG] [server] rpmsg_port queue TX: {used: 0, avail:
8}
[ 0.000000] [ 7] [ EMERG] [server] rpmsg buffer list:
[ 0.000000] [ 7] [ ALERT] [server] sched_dumpstack: backtrace| 5:
0x00000000402a86c0 0x00000000402aa384 0x000000004029c078 0x000000004028cb04
0x00000000402e3de8 0x00000000402e3e98 0x00000000402bcd00 0x00000000402bd188
[ 0.000000] [ 7] [ ALERT] [server] sched_dumpstack: backtrace| 5:
0x00000000402ad044
[ 0.000000] [ 7] [ ALERT] [server] sched_dumpstack: backtrace| 6:
0x00000000402a8ae0 0x00000000402f5ee0 0x00000000402bc0d4 0x00000000402bd270
0x00000000402ad044
server> rpmsg ping all
nsh: rpmsg: missing required argument(s)
server> rpmsg ping all 1 1 1 1
[ 0.000000] [ 7] [ EMERG] [server] ping times: 1
[ 0.000000] [ 7] [ EMERG] [server] buffer_len: 1520, send_len: 17
[ 0.000000] [ 7] [ EMERG] [server] avg: 0 s, 70334352 ns
[ 0.000000] [ 7] [ EMERG] [server] min: 0 s, 70334352 ns
[ 0.000000] [ 7] [ EMERG] [server] max: 0 s, 70334352 ns
[ 0.000000] [ 7] [ EMERG] [server] rate: 0.001933 Mbits/sec
[ 0.000000] [ 7] [ EMERG] [server] ping times: 1
[ 0.000000] [ 7] [ EMERG] [server] buffer_len: 2024, send_len: 17
[ 0.000000] [ 7] [ EMERG] [server] avg: 0 s, 73084720 ns
[ 0.000000] [ 7] [ EMERG] [server] min: 0 s, 73084720 ns
[ 0.000000] [ 7] [ EMERG] [server] max: 0 s, 73084720 ns
[ 0.000000] [ 7] [ EMERG] [server] rate: 0.001860 Mbits/sec
server>
server>
server> ps
TID PID PPID PRI POLICY TYPE NPX STATE EVENT SIGMASK
STACK USED FILLED COMMAND
0 0 0 0 FIFO Kthread - Ready
0000000000000000 0008144 0001792 22.0% Idle_Task
1 0 0 192 FIFO Kthread - Waiting Semaphore
0000000000000000 0008080 0001328 16.4% hpwork 0x4047bc60 0x4047bce0
2 0 0 100 FIFO Kthread - Waiting Semaphore
0000000000000000 0008080 0001328 16.4% lpwork 0x4047bd10 0x4047bd90
5 0 0 224 FIFO Kthread - Waiting Semaphore
0000000000000000 0008080 0002384 29.5% rpmsg-uart-rx proxy2 0x404b1048
6 0 0 224 FIFO Kthread - Waiting Event
0000000000000000 0008080 0001856 22.9% rpmsg-uart-tx proxy2 0x404b1048
7 7 0 100 FIFO Task - Running
0000000000000000 0008112 0004976 61.3% nsh_main
8 0 0 224 FIFO Kthread - Waiting Semaphore
0000000000000000 0008080 0001920 23.7% rpmsg-virtio proxy 0x40495b38
server> uname -a
NuttX server 12.10.0 915513edb10 Jan 31 2026 00:07:59 arm64 qemu-armv8a
server>
```
qemuv8a:netnsh
```c
❯ /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.330000] 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.340000] pci_setup_device: pbar0 set bad mask
[ 0.340000] pci_setup_device: pbar1 set bad mask
[ 0.340000] pci_setup_device: pbar2 set bad mask
[ 0.340000] pci_setup_device: pbar3 set bad mask
[ 0.340000] pci_setup_device: pbar4 set bad mask
[ 0.340000] pci_setup_device: pbar5 set bad mask
telnetd [4:100]
NuttShell (NSH) NuttX-12.12.0
nsh>
nsh>
nsh> ps
TID PID PPID PRI POLICY TYPE NPX STATE EVENT SIGMASK
STACK USED FILLED COMMAND
0 0 0 0 FIFO Kthread - Ready
0000000000000000 0008144 0001568 19.2% Idle_Task
1 0 0 192 RR Kthread - Waiting Semaphore
0000000000000000 0008080 0001040 12.8% hpwork 0x403f36c8 0x403f3748
2 0 0 100 RR Kthread - Waiting Semaphore
0000000000000000 0008080 0001040 12.8% lpwork 0x403f3618 0x403f3698
3 3 0 100 RR Task - Running
0000000000000000 0008112 0003328 41.0% nsh_main
4 4 3 100 RR Task - Waiting Semaphore
0000000000020000 0008112 0001856 22.8% telnetd
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:59952
Interval Transfer Bandwidth
0.00- 1.01 sec 9173756 Bytes 72.66 Mbits/sec
1.01- 2.02 sec 9239272 Bytes 73.18 Mbits/sec
2.02- 3.03 sec 9223012 Bytes 73.05 Mbits/sec
3.03- 4.04 sec 9289624 Bytes 73.58 Mbits/sec
4.04- 5.05 sec 9191424 Bytes 72.80 Mbits/sec
5.05- 6.06 sec 9256632 Bytes 73.32 Mbits/sec
6.06- 7.07 sec 9256960 Bytes 73.32 Mbits/sec
7.07- 8.08 sec 9289428 Bytes 73.58 Mbits/sec
8.08- 9.09 sec 9256960 Bytes 73.32 Mbits/sec
9.09- 10.10 sec 9255512 Bytes 73.31 Mbits/sec
closed by the peer: 10.0.2.2:59952
iperf exit
nsh>
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]