Rust virtio drivers in Linux

Manos Pitsidianakis <[email protected]> Mon, 18 May 2026 11:12:06 +0300
Newsgroups dev.linux.lists.virtio-dev
Message-ID <CAAjaMXaOm=sOjO4ksM-PcOf4wqez9+ePBdv9U7prHiVaCx7-+Q@mail.gmail.com>
Hello all,

I have a new device type proposal for the virtio spec I hope to
publish to virtio-comment soon and I have a reference C driver
implementation for Linux. However I would prefer to implement the
driver in Rust, and should it be accepted upstream, abandon the C
driver out-of-tree.

In preparation for that, I wrote bindings for the virtio subsystem and
sent them to LKML. I had forgotten to CC virtio-dev.

The RFC I sent 2 weeks ago has a sample virtio-rtc driver that doesn't
register itself to the rtc subsystem. Since then I wrote a virtio-rng
driver instead that is fully equivalent to the C driver. I haven't
sent it yet because my last revision did not receive any comments yet.
My WIP tree is https://github.com/epilys/linux/tree/rust-virtio

I'd like to hear any feedback and suggestions, especially from the
kernel virtio and Rust maintainers.

Note: An issue with virtio drivers is that they require bindings both
for virtio and the device subsystem. For example I had to write hwrng
bindings for the virtio-rng driver. Does this require more
co-operation from kernel maintainers in order to get things merged?

Miguel: WDYT?

Thanks in advance!

---------- Forwarded message ---------
From: Manos Pitsidianakis <[email protected]>
Date: Sun, May 10, 2026 at 4:38=E2=80=AFPM
Subject: [PATCH RFC v3 0/6] Add Rust virtio bindings and sample device
To: Miguel Ojeda <[email protected]>
Cc: Manos Pitsidianakis <[email protected]>, Peter Hilber
<[email protected]>, Stefano Garzarella
<[email protected]>, Stefan Hajnoczi <[email protected]>, Viresh
Kumar <[email protected]>, Michael S. Tsirkin <[email protected]>,
Boqun Feng <[email protected]>, Gary Guo <[email protected]>, Bj=C3=B6rn Roy
Baron <[email protected]>, Benno Lossin <[email protected]>,
Andreas Hindborg <[email protected]>, Alice Ryhl
<[email protected]>, Trevor Gross <[email protected]>, Danilo
Krummrich <[email protected]>, Daniel Almeida
<[email protected]>, <[email protected]>,
Jason Wang <[email protected]>, Xuan Zhuo
<[email protected]>, Eugenio P=C3=A9rez <[email protected]>,
<[email protected]>, <[email protected]>,
Manos Pitsidianakis <[email protected]>


Hi all, this RFC series adds Rust bindings for Virtio drivers
(frontends in virtio parlance).

As a PoC, it also adds a sample virtio-rtc driver which performs
capability discovery through the virtqueue without registering any clock.

Before I send a cleaned-up non-RFC I would like some initial feedback
(i.e. is it something the upstream wants?)

This was tested with the rust-vmm vhost-device-rtc device backend that I
wrote[^0]:

[^0]: https://github.com/rust-vmm/vhost-device/tree/main/vhost-device-rtc

Instructions:

  Run the daemon in a separate terminal:

  $ cargo run --bin vhost-device-rtc -- -s /tmp/rtc.sock

  Then run the VM:

  $ qemu-system-aarch64 \
    -machine type=3Dvirt,virtualization=3Doff,acpi=3Don \
    -cpu host \
    -smp 8 \
    -accel kvm \
    -drive if=3Dvirtio,format=3Dqcow2,file=3D./debian-13-nocloud-arm64-dail=
y.qcow2 \
    -device virtio-net-pci,netdev=3Dunet \
    -device virtio-scsi-pci \
    -serial mon:stdio \
    -m 8192 \
    -object memory-backend-memfd,id=3Dmem,size=3D8G,share=3Don \
    -numa node,memdev=3Dmem \
    -display none \
    -vga none \
    -kernel /path/to/linux/build/arch/arm64/boot/Image \
    -device vhost-user-test-device,chardev=3Drtc,id=3Drtc,virtio-id=3D17,nu=
m_vqs=3D2,vq_size=3D1024
\
    -chardev socket,path=3D/tmp/rtc.sock,id=3Drtc \
    ...

  Example output:
    [    1.105238] rust_virtio_rtc: Probe Rust virtio driver sample.
    [    1.105645] rust_virtio_rtc: Found 1 vqs.
    [    1.136050] rust_virtio_rtc: process_requestq got buf 16 bytes
    [    1.136125] rust_virtio_rtc: Got response! Ok(RespCfg { head:
ReqHead { msg_type: Le16(0), reserved: [0, 0, 0, 0, 0, 0] },
num_clocks: Le16(3), reserved: [0, 0, 0, 0, 0, 0] })
    [    1.136701] rust_virtio_rtc: Got response! Ok(RespClockCap {
head: ReqHead { msg_type: Le16(0), reserved: [0, 0, 0, 0, 0, 0] },
clock_type: 3, leap_second_smearing: 0, flags: 0, reserved: [0, 0, 0,
0, 0] })
    [    1.136724] rust_virtio_rtc virtio0: cannot expose clock 0
(type 3, variant 0, flags 0) to userspace
    [    1.137259] rust_virtio_rtc: Got response! Ok(RespRead { head:
ReqHead { msg_type: Le16(0), reserved: [0, 0, 0, 0, 0, 0] },
clock_reading: Le64(1777890485031060388) })
    [    1.137277] rust_virtio_rtc: #0 clock reading =3D 177789048503106038=
8
    [    1.137749] rust_virtio_rtc: Got response! Ok(RespClockCap {
head: ReqHead { msg_type: Le16(0), reserved: [0, 0, 0, 0, 0, 0] },
clock_type: 1, leap_second_smearing: 0, flags: 0, reserved: [0, 0, 0,
0, 0] })
    [    1.137769] rust_virtio_rtc virtio0: cannot expose clock 1
(type 1, variant 0, flags 0) to userspace
    [    1.138247] rust_virtio_rtc: Got response! Ok(RespRead { head:
ReqHead { msg_type: Le16(0), reserved: [0, 0, 0, 0, 0, 0] },
clock_reading: Le64(1777890485032086075) })
    [    1.138264] rust_virtio_rtc: #1 clock reading =3D 177789048503208607=
5
    [    1.138730] rust_virtio_rtc: Got response! Ok(RespClockCap {
head: ReqHead { msg_type: Le16(0), reserved: [0, 0, 0, 0, 0, 0] },
clock_type: 2, leap_second_smearing: 0, flags: 0, reserved: [0, 0, 0,
0, 0] })
    [    1.138751] rust_virtio_rtc virtio0: cannot expose clock 2
(type 2, variant 0, flags 0) to userspace
    [    1.139253] rust_virtio_rtc: Got response! Ok(RespRead { head:
ReqHead { msg_type: Le16(0), reserved: [0, 0, 0, 0, 0, 0] },
clock_reading: Le64(338567896865557) })
    [    1.139270] rust_virtio_rtc: #2 clock reading =3D 338567896865557

Concerns - Notes - TODOs
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

- Virtqueue lifetimes don't neatly apply to Rust as expected, so a lot
  of times we have to go through unsafe pointer dereferences (though
  which are guaranteed by Virtio subsystem to be valid, for example when
  a callback is called with the vq argument). There's a potential for
  misuse and definitely could use better thinking.
- `struct virtio_device` is not reference-counted like other implemented
  device types in rust/kernel. Maybe we need to change C API first to
  make them reference counted, assuming this doesn't break anything?
- The sample driver obviously conflicts with the C implementation, so
  this would either need to move out of samples/ or figure out some way
  to handle this in kbuild.
- kernel::virtio module and its types need a few rustdoc examples that I
  will add in followup series
- Note that the registration of RTC clocks etc in the sample driver is
  not done, I'm putting it off until I receive some feedback first. The
  sample driver otherwise does send and receive data from the virtqueue
  as a PoC.

PS: No LLMs used so any mistakes and goofs are solely written by me.

Signed-off-by: Manos Pitsidianakis <[email protected]>
---
Changes in v3:
- Removed unused methods from virtio API
- Clean up how scattergather lists are added to virtqueues by using
  owned SGTables only, and make the API safe(r)
- Add RAII cleanup for find_vqs return value that calls del_vqs
- Reset device after remove callback
- Significantly clean up sample driver as a result of the other cleanups
- Link to v2: https://lore.kernel.org/r/20260509-rust-virtio-v2-0-c1e30ec2b=
[email protected]

Changes in v2:
- Move helper ifdefs to helper file (thanks Alice)
- Changed CONFIG checks to IS_ENABLED to allow for CONFIG_VIRTIO=3Dm
- Split all use imports to one item per line according to style guide
- Fixed wait_for_completion_interruptible*() rustdocs
- Use Jiffy type alias in wait_for_completion_interruptible_timeout()
- Pepper and salt #[inline]s wherever appropriate as per style guide
- Split probe() into probe() and init() to allow cleaning up if init
  fails
- Remove unnecessary Send and Sync unsafe impls for
  kernel::virtio::Device
- Remove unnecessary LeSize and BeSize
- Accept Option<_> for virtqueue callback when creating a VirtqueueInfo
- Made all vq buffer adding operations unsafe
- Use AtomicU16 instead of Cell<u16> for sample virtio driver
- Fix RespHead field types in sample virtio driver
- Fix response error checking in sample virtio driver
- Change some device contexts in method signatures
- Link to v1: https://lore.kernel.org/r/20260505-rust-virtio-v1-0-956338390=
[email protected]

---
Manos Pitsidianakis (6):
      rust/bindings: generate virtio bindings
      rust/helpers: add virtio.c
      rust/kernel/device: return parent at same context
      rust: add virtio module
      rust: impl interruptible waits for Completion
      samples/rust: Add sample virtio-rtc driver [WIP]

 MAINTAINERS                     |   9 +
 rust/bindings/bindings_helper.h |   5 +
 rust/helpers/helpers.c          |   1 +
 rust/helpers/virtio.c           |  37 ++++
 rust/kernel/device.rs           |   2 +-
 rust/kernel/lib.rs              |   2 +
 rust/kernel/sync/completion.rs  |  42 +++-
 rust/kernel/virtio.rs           | 423 ++++++++++++++++++++++++++++++++++++=
++++
 rust/kernel/virtio/utils.rs     |  57 ++++++
 rust/kernel/virtio/virtqueue.rs | 314 +++++++++++++++++++++++++++++
 samples/rust/Kconfig            |  15 ++
 samples/rust/Makefile           |   1 +
 samples/rust/rust_virtio_rtc.rs | 403 ++++++++++++++++++++++++++++++++++++=
++
 13 files changed, 1309 insertions(+), 2 deletions(-)
---
base-commit: 028ef9c96e96197026887c0f092424679298aae8
change-id: 20260504-rust-virtio-8523b01dfdc2

Best regards,
--
Manos Pitsidianakis <[email protected]>

--=20
Manos Pitsidianakis
Emulation and Virtualization Engineer at Linaro Ltd