Add a new SR-IOV driver sample that demonstrates how to enable and
disable the Single Root I/O Virtualization capability for a PCI device.
The sample may be exercised using QEMU's 82576 (igb) emulation.
Link: https://www.qemu.org/docs/master/system/devices/igb.html
Signed-off-by: Peter Colberg <pcolberg@redhat.com>
---
MAINTAINERS | 1 +
samples/rust/Kconfig | 11 ++++
samples/rust/Makefile | 1 +
samples/rust/rust_driver_sriov.rs | 107 ++++++++++++++++++++++++++++++++++++++
4 files changed, 120 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index b71ea515240a4c5db6d932efce5183386f3a3f79..f2b00c6d9feca43443d3618da32dce2c6ab8c569 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19945,6 +19945,7 @@ F: rust/helpers/pci.c
F: rust/kernel/pci.rs
F: rust/kernel/pci/
F: samples/rust/rust_driver_pci.rs
+F: samples/rust/rust_driver_sriov.rs
PCIE BANDWIDTH CONTROLLER
M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
index b66bed5d3f36d20302bf586dfdb002d39ed9796e..b6154b6cd91f1d733f05b7529f67a79fe032b50c 100644
--- a/samples/rust/Kconfig
+++ b/samples/rust/Kconfig
@@ -128,6 +128,17 @@ config SAMPLE_RUST_DRIVER_PLATFORM
If unsure, say N.
+config SAMPLE_RUST_DRIVER_SRIOV
+ tristate "SR-IOV Driver"
+ depends on PCI_IOV
+ help
+ This option builds the Rust SR-IOV driver sample.
+
+ To compile this as a module, choose M here:
+ the module will be called rust_driver_sriov.
+
+ If unsure, say N.
+
config SAMPLE_RUST_DRIVER_USB
tristate "USB Driver"
depends on USB = y && BROKEN
diff --git a/samples/rust/Makefile b/samples/rust/Makefile
index f65885d1d62bf406b0db13121ef3e5b09829cfbc..a4c12c1200949d0233e08a34e86cea1ff72d0ad7 100644
--- a/samples/rust/Makefile
+++ b/samples/rust/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SAMPLE_RUST_DRIVER_I2C) += rust_driver_i2c.o
obj-$(CONFIG_SAMPLE_RUST_I2C_CLIENT) += rust_i2c_client.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) += rust_driver_platform.o
+obj-$(CONFIG_SAMPLE_RUST_DRIVER_SRIOV) += rust_driver_sriov.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) += rust_driver_usb.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) += rust_driver_auxiliary.o
diff --git a/samples/rust/rust_driver_sriov.rs b/samples/rust/rust_driver_sriov.rs
new file mode 100644
index 0000000000000000000000000000000000000000..a60d58d00a2d24883ddcb7236e525c448ae86b4f
--- /dev/null
+++ b/samples/rust/rust_driver_sriov.rs
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust SR-IOV driver sample based on QEMU's 82576 ([igb]) emulation.
+//!
+//! To make this driver probe, QEMU must be run with `-device igb`.
+//!
+//! Further, enable [vIOMMU] with interrupt remapping using, e.g.,
+//!
+//! `-M q35,accel=kvm,kernel-irqchip=split -device intel-iommu,intremap=on,caching-mode=on`
+//!
+//! and append `intel_iommu=on` to the guest kernel arguments.
+//!
+//! [igb]: https://www.qemu.org/docs/master/system/devices/igb.html
+//! [vIOMMU]: https://wiki.qemu.org/Features/VT-d
+
+use kernel::{device::Core, pci, prelude::*, sync::aref::ARef};
+
+#[pin_data(PinnedDrop)]
+struct SampleDriver {
+ pdev: ARef<pci::Device>,
+}
+
+kernel::pci_device_table!(
+ PCI_TABLE,
+ MODULE_PCI_TABLE,
+ <SampleDriver as pci::Driver>::IdInfo,
+ [
+ // E1000_DEV_ID_82576
+ (pci::DeviceId::from_id(pci::Vendor::INTEL, 0x10c9), ()),
+ // E1000_DEV_ID_82576_VF
+ (pci::DeviceId::from_id(pci::Vendor::INTEL, 0x10ca), ())
+ ]
+);
+
+#[vtable]
+impl pci::Driver for SampleDriver {
+ type IdInfo = ();
+
+ const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
+
+ fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
+ pin_init::pin_init_scope(move || {
+ dev_info!(
+ pdev.as_ref(),
+ "Probe Rust SR-IOV driver sample (PCI ID: {}, 0x{:x}).\n",
+ pdev.vendor_id(),
+ pdev.device_id()
+ );
+
+ if pdev.is_virtfn() {
+ let physfn = pdev.physfn()?;
+ assert!(physfn.is_physfn());
+ dev_info!(
+ pdev.as_ref(),
+ "Parent device is PF (PCI ID: {}, 0x{:x}).\n",
+ physfn.vendor_id(),
+ physfn.device_id()
+ );
+ }
+
+ pdev.enable_device_mem()?;
+ pdev.set_master();
+
+ Ok(try_pin_init!(Self { pdev: pdev.into() }))
+ })
+ }
+
+ fn sriov_configure(pdev: &pci::Device<Core>, nr_virtfn: i32) -> Result<i32> {
+ assert!(pdev.is_physfn());
+
+ if nr_virtfn == 0 {
+ dev_info!(
+ pdev.as_ref(),
+ "Disable SR-IOV (PCI ID: {}, 0x{:x}).\n",
+ pdev.vendor_id(),
+ pdev.device_id()
+ );
+ pdev.disable_sriov();
+ } else {
+ dev_info!(
+ pdev.as_ref(),
+ "Enable SR-IOV (PCI ID: {}, 0x{:x}).\n",
+ pdev.vendor_id(),
+ pdev.device_id()
+ );
+ pdev.enable_sriov(nr_virtfn)?;
+ }
+
+ assert_eq!(pdev.num_vf(), nr_virtfn);
+ Ok(nr_virtfn)
+ }
+}
+
+#[pinned_drop]
+impl PinnedDrop for SampleDriver {
+ fn drop(self: Pin<&mut Self>) {
+ dev_info!(self.pdev.as_ref(), "Remove Rust SR-IOV driver sample.\n");
+ }
+}
+
+kernel::module_pci_driver! {
+ type: SampleDriver,
+ name: "rust_driver_sriov",
+ authors: ["Peter Colberg"],
+ description: "Rust SR-IOV driver",
+ license: "GPL v2",
+}
--
2.51.1
On Wed, 19 Nov 2025 17:19:12 -0500
Peter Colberg <pcolberg@redhat.com> wrote:
> Add a new SR-IOV driver sample that demonstrates how to enable and
> disable the Single Root I/O Virtualization capability for a PCI
> device.
>
> The sample may be exercised using QEMU's 82576 (igb) emulation.
>
snip
> +
> + fn sriov_configure(pdev: &pci::Device<Core>, nr_virtfn: i32) ->
> Result<i32> {
> + assert!(pdev.is_physfn());
> +
> + if nr_virtfn == 0 {
> + dev_info!(
> + pdev.as_ref(),
> + "Disable SR-IOV (PCI ID: {}, 0x{:x}).\n",
> + pdev.vendor_id(),
> + pdev.device_id()
> + );
> + pdev.disable_sriov();
> + } else {
> + dev_info!(
> + pdev.as_ref(),
> + "Enable SR-IOV (PCI ID: {}, 0x{:x}).\n",
> + pdev.vendor_id(),
> + pdev.device_id()
> + );
> + pdev.enable_sriov(nr_virtfn)?;
> + }
> +
IMO, it would be nice to simply demostrate how to reach the driver data
structure (struct SampleDriver) and its members (I think accessing one
dummy member in the SampleDriver is good enough, not something fancy),
which I believe quite many of the drivers need to do so and they can
take this as the kernel recommended approach instead of inventing
something new differently. :)
Z.
> + assert_eq!(pdev.num_vf(), nr_virtfn);
> + Ok(nr_virtfn)
> + }
> +}
> +
> +#[pinned_drop]
> +impl PinnedDrop for SampleDriver {
> + fn drop(self: Pin<&mut Self>) {
> + dev_info!(self.pdev.as_ref(), "Remove Rust SR-IOV driver
> sample.\n");
> + }
> +}
> +
> +kernel::module_pci_driver! {
> + type: SampleDriver,
> + name: "rust_driver_sriov",
> + authors: ["Peter Colberg"],
> + description: "Rust SR-IOV driver",
> + license: "GPL v2",
> +}
>
On Thu, Nov 20, 2025 at 08:41:32AM +0200, Zhi Wang wrote:
> On Wed, 19 Nov 2025 17:19:12 -0500
> Peter Colberg <pcolberg@redhat.com> wrote:
>
> > Add a new SR-IOV driver sample that demonstrates how to enable and
> > disable the Single Root I/O Virtualization capability for a PCI
> > device.
> >
> > The sample may be exercised using QEMU's 82576 (igb) emulation.
> >
>
> snip
>
> > +
> > + fn sriov_configure(pdev: &pci::Device<Core>, nr_virtfn: i32) ->
> > Result<i32> {
> > + assert!(pdev.is_physfn());
> > +
> > + if nr_virtfn == 0 {
> > + dev_info!(
> > + pdev.as_ref(),
> > + "Disable SR-IOV (PCI ID: {}, 0x{:x}).\n",
> > + pdev.vendor_id(),
> > + pdev.device_id()
> > + );
> > + pdev.disable_sriov();
> > + } else {
> > + dev_info!(
> > + pdev.as_ref(),
> > + "Enable SR-IOV (PCI ID: {}, 0x{:x}).\n",
> > + pdev.vendor_id(),
> > + pdev.device_id()
> > + );
> > + pdev.enable_sriov(nr_virtfn)?;
> > + }
> > +
>
> IMO, it would be nice to simply demostrate how to reach the driver data
> structure (struct SampleDriver) and its members (I think accessing one
> dummy member in the SampleDriver is good enough, not something fancy),
> which I believe quite many of the drivers need to do so and they can
> take this as the kernel recommended approach instead of inventing
> something new differently. :)
Thanks for the suggestion. I added a `private` member to SampleDriver,
similar to the rust_driver_auxiliary sample, and extended the VF-only
path of probe() to demonstrate how to reach the driver data of the PF
device from a VF device.
Peter
>
> Z.
>
> > + assert_eq!(pdev.num_vf(), nr_virtfn);
> > + Ok(nr_virtfn)
> > + }
> > +}
> > +
> > +#[pinned_drop]
> > +impl PinnedDrop for SampleDriver {
> > + fn drop(self: Pin<&mut Self>) {
> > + dev_info!(self.pdev.as_ref(), "Remove Rust SR-IOV driver
> > sample.\n");
> > + }
> > +}
> > +
> > +kernel::module_pci_driver! {
> > + type: SampleDriver,
> > + name: "rust_driver_sriov",
> > + authors: ["Peter Colberg"],
> > + description: "Rust SR-IOV driver",
> > + license: "GPL v2",
> > +}
> >
>
© 2016 - 2025 Red Hat, Inc.