virtio-bindings

Rust FFI bindings to the Linux kernel virtio uapi, generated with bindgen for building VMMs.

Library
Cargo
v0.2.7
470stars
BSD-3-Clause OR Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
73/100Good
Development Activity60
Maintenance60
Community84
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
61/100Good
Architecture70
Code Quality58
Innovation60
Learning Curve55

virtio-bindings is a Rust crate maintained by the rust-vmm project that provides raw FFI bindings to the Linux kernel’s virtio userspace API (virtio_blk, virtio_net, virtio_gpu, virtio_scsi, virtio_mmio, virtio_ring, virtio_config, virtio_ids, and virtio_input), generated with bindgen directly from kernel uapi headers.

It exists so that virtual machine monitors written in Rust — such as Firecracker, Cloud Hypervisor, and crosvm — don’t each have to hand-maintain their own copy of virtio constants and struct layouts. The bindings are pre-generated and checked into the crate for 16 CPU architectures, so consumers get a zero-dependency, build-time-free way to reference the exact same device IDs, feature flags, and descriptor layouts the kernel itself uses.

What You Get

  • Pre-generated Rust FFI bindings for virtio_blk, virtio_net, virtio_gpu, virtio_scsi, virtio_mmio, virtio_ring, virtio_config, virtio_ids, and virtio_input, checked into the crate for 16 target architectures (x86, x86_64, arm, aarch64, riscv32/64, mips variants, powerpc64, s390x, sparc, loongarch64, m68k, hexagon).
  • Automatic per-architecture selection via #[cfg_attr(target_arch = ...)] path attributes in lib.rs, so the correct bindings are picked at compile time with no build script or bindgen dependency for downstream consumers.
  • A bindings module that re-exports every header module in one place (virtio_bindings::bindings::virtio_blk::*) for straightforward importing.
  • A small hand-written virtio_net helper module with unit tests covering the Linux 6.18 hash_value_lo/hash_value_hi field split, for cases where raw bindgen output needs a thin ergonomic wrapper.
  • A scripts/generate-bindings.sh script and documented workflow (see CONTRIBUTING.md) for regenerating all bindings against a new Linux kernel checkout with bindgen-cli 0.71.1.

Common Use Cases

  • Implementing a virtio device backend (block, net, console, vsock, scsi) inside a Rust virtual machine monitor without hand-transcribing kernel struct layouts and constants.
  • Building on top of rust-vmm sibling crates (virtio-queue, virtio-device, virtio-blk, virtio-vsock) that already depend on virtio-bindings for their FFI layer.
  • Cross-compiling a VMM or virtio driver for a non-x86 target (aarch64, riscv64, s390x, etc.) and needing architecture-correct virtio struct layouts without regenerating bindings yourself.
  • Writing tests or fuzz targets that need to construct raw virtio descriptor/queue structures matching exactly what the guest kernel expects.

Under The Hood

Architecture virtio-bindings is a workspace member of rust-vmm’s vm-virtio monorepo, scoped to a single job: exposing the Linux kernel’s virtio uapi headers as Rust types. lib.rs declares one pub mod per virtio header (virtio_blk, virtio_config, virtio_gpu, virtio_ids, virtio_input, virtio_mmio, virtio_net, virtio_ring, virtio_scsi), each annotated with a chain of #[cfg_attr(target_arch = "...", path = "bindings/<arch>/<header>.rs")] attributes so the compiler selects the pre-generated file matching the build’s target architecture — no build.rs, no bindgen invocation at consumer compile time. All modules are re-exported together under a single pub mod bindings for a stable, ergonomic import path. One hand-authored module, virtio_net/mod.rs, sits alongside the generated code to patch in small ergonomic fixes (the Linux 6.18 hash_value_lo/hash_value_hi split) with its own unit tests, showing the maintainers keep generated and hand-written code cleanly separated.

Tech Stack The published crate has an empty [dependencies] table in Cargo.toml — it is a pure data/constants crate at compile time with zero runtime dependencies. Generating (not consuming) the bindings requires bindgen-cli 0.71.1 and a local Linux kernel source checkout, invoked via scripts/generate-bindings.sh, which runs make headers_install against the kernel tree and then bindgen per architecture with --with-derive-default --with-derive-partialeq. The crate targets Rust 2021 edition and sits inside the broader vm-virtio Cargo workspace alongside virtio-queue, virtio-device, virtio-blk, virtio-console, and virtio-vsock. CI runs on Buildkite via the shared rust-vmm-ci submodule, with additional fuzzing and Kani formal-verification proof pipelines defined for the workspace as a whole.

Code Quality The overwhelming majority of the source tree (src/bindings/**, 16 architecture directories) is bindgen-generated boilerplate, so conventional code-quality review doesn’t meaningfully apply there — it is allow-listed at the crate root with #![allow(clippy::all, non_upper_case_globals, non_camel_case_types, clippy::undocumented_unsafe_blocks)], an explicit acknowledgment of the raw-FFI nature of the surface. The one hand-written module, virtio_net/mod.rs, carries three #[test] functions verifying the manual hash-value field split introduced for Linux 6.18. Naming throughout mirrors the C kernel headers verbatim, which is correct and expected for a bindings crate rather than a quality gap. There is no runtime error-handling logic to evaluate, since the crate defines types and constants only.

API Design Getting started is a two-line affair: add virtio-bindings = "0.2" to Cargo.toml and use virtio_bindings::bindings::virtio_blk::*; to pull in a header’s constants and structs — there is no configuration, initialization, or builder pattern to learn. The tradeoff is that the public API is entirely dictated by upstream Linux kernel header names rather than designed for Rust ergonomics, so familiarity with the virtio specification and kernel uapi conventions is assumed. Documentation is minimal — a single-paragraph README with one usage example and a CONTRIBUTING.md describing the regeneration workflow — with no rustdoc narrative beyond what bindgen itself emits, so the practical learning curve depends on virtio/kernel domain knowledge more than on crate-level documentation.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search