* Rust virtio drivers in Linux
[not found] <20260510-rust-virtio-v3-0-1427f14d67e1@pitsidianak.is>
@ 2026-05-18 8:12 ` Manos Pitsidianakis
2026-05-18 8:44 ` Michael S. Tsirkin
0 siblings, 1 reply; 2+ messages in thread
From: Manos Pitsidianakis @ 2026-05-18 8:12 UTC (permalink / raw)
To: VirtIO Dev List; +Cc: Miguel Ojeda, Michael S. Tsirkin, manos
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 <manos@pitsidianak.is>
Date: Sun, May 10, 2026 at 4:38 PM
Subject: [PATCH RFC v3 0/6] Add Rust virtio bindings and sample device
To: Miguel Ojeda <ojeda@kernel.org>
Cc: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>, Peter Hilber
<peter.hilber@oss.qualcomm.com>, Stefano Garzarella
<sgarzare@redhat.com>, Stefan Hajnoczi <stefanha@redhat.com>, Viresh
Kumar <viresh.kumar@linaro.org>, Michael S. Tsirkin <mst@redhat.com>,
Boqun Feng <boqun@kernel.org>, Gary Guo <gary@garyguo.net>, Björn Roy
Baron <bjorn3_gh@protonmail.com>, Benno Lossin <lossin@kernel.org>,
Andreas Hindborg <a.hindborg@kernel.org>, Alice Ryhl
<aliceryhl@google.com>, Trevor Gross <tmgross@umich.edu>, Danilo
Krummrich <dakr@kernel.org>, Daniel Almeida
<daniel.almeida@collabora.com>, <rust-for-linux@vger.kernel.org>,
Jason Wang <jasowang@redhat.com>, Xuan Zhuo
<xuanzhuo@linux.alibaba.com>, Eugenio Pérez <eperezma@redhat.com>,
<virtualization@lists.linux.dev>, <linux-kernel@vger.kernel.org>,
Manos Pitsidianakis <manos@pitsidianak.is>
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=virt,virtualization=off,acpi=on \
-cpu host \
-smp 8 \
-accel kvm \
-drive if=virtio,format=qcow2,file=./debian-13-nocloud-arm64-daily.qcow2 \
-device virtio-net-pci,netdev=unet \
-device virtio-scsi-pci \
-serial mon:stdio \
-m 8192 \
-object memory-backend-memfd,id=mem,size=8G,share=on \
-numa node,memdev=mem \
-display none \
-vga none \
-kernel /path/to/linux/build/arch/arm64/boot/Image \
-device vhost-user-test-device,chardev=rtc,id=rtc,virtio-id=17,num_vqs=2,vq_size=1024
\
-chardev socket,path=/tmp/rtc.sock,id=rtc \
...
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 = 1777890485031060388
[ 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 = 1777890485032086075
[ 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 = 338567896865557
Concerns - Notes - TODOs
========================
- 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 <manos@pitsidianak.is>
---
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-c1e30ec2bd21@pitsidianak.is
Changes in v2:
- Move helper ifdefs to helper file (thanks Alice)
- Changed CONFIG checks to IS_ENABLED to allow for CONFIG_VIRTIO=m
- 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-9563383909e4@pitsidianak.is
---
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 <manos@pitsidianak.is>
--
Manos Pitsidianakis
Emulation and Virtualization Engineer at Linaro Ltd
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Rust virtio drivers in Linux
2026-05-18 8:12 ` Rust virtio drivers in Linux Manos Pitsidianakis
@ 2026-05-18 8:44 ` Michael S. Tsirkin
0 siblings, 0 replies; 2+ messages in thread
From: Michael S. Tsirkin @ 2026-05-18 8:44 UTC (permalink / raw)
To: Manos Pitsidianakis; +Cc: VirtIO Dev List, Miguel Ojeda, manos
On Mon, May 18, 2026 at 11:12:06AM +0300, Manos Pitsidianakis wrote:
> 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
Yea, sorry I didn't start reviewing yet. My problem is my rust knowledge is
limited, and kernel rust - nonexistent. I did the crab book a while ago
but didn't do much since except a small terminal emulator project.
> 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?
Well the rust kernel doc at Documentation/rust/general-information.rst
says you are supposed to also write
"abstractions" as opposed to just "bindings" and they have to
be "ergonomic". I will be frank I'm not the best judge
about "egonomic". So yes, more kernel maintainers who understand
this thing would help a lot.
> Miguel: WDYT?
>
> Thanks in advance!
>
> ---------- Forwarded message ---------
> From: Manos Pitsidianakis <manos@pitsidianak.is>
> Date: Sun, May 10, 2026 at 4:38 PM
> Subject: [PATCH RFC v3 0/6] Add Rust virtio bindings and sample device
> To: Miguel Ojeda <ojeda@kernel.org>
> Cc: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>, Peter Hilber
> <peter.hilber@oss.qualcomm.com>, Stefano Garzarella
> <sgarzare@redhat.com>, Stefan Hajnoczi <stefanha@redhat.com>, Viresh
> Kumar <viresh.kumar@linaro.org>, Michael S. Tsirkin <mst@redhat.com>,
> Boqun Feng <boqun@kernel.org>, Gary Guo <gary@garyguo.net>, Björn Roy
> Baron <bjorn3_gh@protonmail.com>, Benno Lossin <lossin@kernel.org>,
> Andreas Hindborg <a.hindborg@kernel.org>, Alice Ryhl
> <aliceryhl@google.com>, Trevor Gross <tmgross@umich.edu>, Danilo
> Krummrich <dakr@kernel.org>, Daniel Almeida
> <daniel.almeida@collabora.com>, <rust-for-linux@vger.kernel.org>,
> Jason Wang <jasowang@redhat.com>, Xuan Zhuo
> <xuanzhuo@linux.alibaba.com>, Eugenio Pérez <eperezma@redhat.com>,
> <virtualization@lists.linux.dev>, <linux-kernel@vger.kernel.org>,
> Manos Pitsidianakis <manos@pitsidianak.is>
>
>
> 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=virt,virtualization=off,acpi=on \
> -cpu host \
> -smp 8 \
> -accel kvm \
> -drive if=virtio,format=qcow2,file=./debian-13-nocloud-arm64-daily.qcow2 \
> -device virtio-net-pci,netdev=unet \
> -device virtio-scsi-pci \
> -serial mon:stdio \
> -m 8192 \
> -object memory-backend-memfd,id=mem,size=8G,share=on \
> -numa node,memdev=mem \
> -display none \
> -vga none \
> -kernel /path/to/linux/build/arch/arm64/boot/Image \
> -device vhost-user-test-device,chardev=rtc,id=rtc,virtio-id=17,num_vqs=2,vq_size=1024
> \
> -chardev socket,path=/tmp/rtc.sock,id=rtc \
> ...
>
> 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 = 1777890485031060388
> [ 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 = 1777890485032086075
> [ 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 = 338567896865557
>
> Concerns - Notes - TODOs
> ========================
>
> - 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 <manos@pitsidianak.is>
> ---
> 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-c1e30ec2bd21@pitsidianak.is
>
> Changes in v2:
> - Move helper ifdefs to helper file (thanks Alice)
> - Changed CONFIG checks to IS_ENABLED to allow for CONFIG_VIRTIO=m
> - 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-9563383909e4@pitsidianak.is
>
> ---
> 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 <manos@pitsidianak.is>
>
> --
> Manos Pitsidianakis
> Emulation and Virtualization Engineer at Linaro Ltd
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-05-18 8:44 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260510-rust-virtio-v3-0-1427f14d67e1@pitsidianak.is>
2026-05-18 8:12 ` Rust virtio drivers in Linux Manos Pitsidianakis
2026-05-18 8:44 ` Michael S. Tsirkin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox