From: Zhi Wang <zhiw@nvidia.com>
To: <dakr@kernel.org>, <acourbot@nvidia.com>
Cc: <alex@shazbot.org>, <jgg@nvidia.com>, <yishaih@nvidia.com>,
<skolothumtho@nvidia.com>, <kevin.tian@intel.com>,
<airlied@gmail.com>, <simona@ffwll.ch>, <ojeda@kernel.org>,
<alex.gaynor@gmail.com>, <boqun.feng@gmail.com>,
<gary@garyguo.net>, <bjorn3_gh@protonmail.com>,
<lossin@kernel.org>, <a.hindborg@kernel.org>,
<aliceryhl@google.com>, <tmgross@umich.edu>,
<jhubbard@nvidia.com>, <ecourtney@nvidia.com>, <cjia@nvidia.com>,
<smitra@nvidia.com>, <kjaju@nvidia.com>, <alkumar@nvidia.com>,
<ankita@nvidia.com>, <aniketa@nvidia.com>, <kwankhede@nvidia.com>,
<targupta@nvidia.com>, <nova-gpu@lists.linux.dev>,
<linux-kernel@vger.kernel.org>, <rust-for-linux@vger.kernel.org>,
<zhiwang@kernel.org>, Zhi Wang <zhiw@nvidia.com>
Subject: [PATCH 12/14] samples: rust: add C SR-IOV VF driver that calls into a Rust PF driver
Date: Tue, 15 Sep 2026 23:56:56 +0300 [thread overview]
Message-ID: <20260915205659.76841-13-zhiw@nvidia.com> (raw)
In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com>
C drivers need a type-checked way to invoke functionality implemented by
Rust PF drivers without receiving the PF driver's complete private data.
The Rust SR-IOV sample currently demonstrates only a Rust VF consumer.
Add an optional C VF module that borrows the sample's published PF data
through a `struct rust_ffi` descriptor. Validate the ABI token, version,
and operations-table size before calling an automatically generated Rust
trampoline.
Route Rust and C VF requests through the same PF handler. The generated C
callback forwards the requester's PCI ID and translates the Rust `Result`
into the C errno convention. The C driver uses the borrow only while its
VF remains bound, so all users must be drained before its remove callback
returns.
Signed-off-by: Zhi Wang <zhiw@nvidia.com>
---
MAINTAINERS | 2 +-
rust/bindings/bindings_helper.h | 4 ++
samples/rust/Kconfig | 17 +++++++-
samples/rust/Makefile | 1 +
samples/rust/rust_driver_sriov.h | 27 ++++++++++++
samples/rust/rust_driver_sriov.rs | 43 ++++++++++++++++---
samples/rust/rust_driver_sriov_c_vf.c | 61 +++++++++++++++++++++++++++
7 files changed, 146 insertions(+), 9 deletions(-)
create mode 100644 samples/rust/rust_driver_sriov.h
create mode 100644 samples/rust/rust_driver_sriov_c_vf.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 9f70dc14bf78..e03ebe44c341 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21141,7 +21141,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
+F: samples/rust/rust_driver_sriov*
PCIE BANDWIDTH CONTROLLER
M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 6a30455768b4..2467305c4842 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -112,6 +112,10 @@
#include <drm/drm_panic.h>
#endif
+#if IS_ENABLED(CONFIG_SAMPLE_RUST_DRIVER_SRIOV)
+#include "../../samples/rust/rust_driver_sriov.h"
+#endif
+
/* `bindgen` gets confused at certain things. */
const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
const size_t RUST_CONST_HELPER_ARCH_KMALLOC_MINALIGN = ARCH_KMALLOC_MINALIGN;
diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
index 737670fd68f8..3747f3fe23dd 100644
--- a/samples/rust/Kconfig
+++ b/samples/rust/Kconfig
@@ -132,13 +132,28 @@ config SAMPLE_RUST_DRIVER_SRIOV
tristate "SR-IOV Driver"
depends on PCI_IOV
help
- This option builds the Rust SR-IOV driver sample.
+ This option builds the Rust SR-IOV PF and VF 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_SRIOV_C_VF
+ tristate "C VF consumer for the Rust SR-IOV driver"
+ depends on SAMPLE_RUST_DRIVER_SRIOV
+ help
+ This option builds a C VF driver that accesses PF data through FFI
+ published by the Rust SR-IOV PF sample.
+
+ To compile this as a module, choose M here: the module will be called
+ rust_driver_sriov_c_vf. Load it before rust_driver_sriov and enable
+ VFs only after both drivers are registered. Ensure that no other VF
+ driver has claimed the device; driver_override may be used for a
+ deterministic test.
+
+ If unsure, say N.
+
config SAMPLE_RUST_DRIVER_USB
tristate "USB Driver"
depends on USB = y
diff --git a/samples/rust/Makefile b/samples/rust/Makefile
index 238a11d5ec39..b52f07df52de 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_C_VF) += rust_driver_sriov_c_vf.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
diff --git a/samples/rust/rust_driver_sriov.h b/samples/rust/rust_driver_sriov.h
new file mode 100644
index 000000000000..1d4dff4e3414
--- /dev/null
+++ b/samples/rust/rust_driver_sriov.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SAMPLES_RUST_DRIVER_SRIOV_H
+#define _SAMPLES_RUST_DRIVER_SRIOV_H
+
+#include <linux/rust_ffi.h>
+
+#define RUST_DRIVER_SRIOV_FFI_TOKEN_HIGH 0x6c8686c04f7a4ba1ULL
+#define RUST_DRIVER_SRIOV_FFI_TOKEN_LOW 0x77ab9a3c4d3cfb34ULL
+#define RUST_DRIVER_SRIOV_FFI_ABI_MAJOR 1U
+#define RUST_DRIVER_SRIOV_FFI_ABI_MINOR 0U
+
+/**
+ * struct rust_driver_sriov_ops - Operations published by the Rust PF sample
+ * @submit: Submit one request for a requester ID and return 0 or a negative
+ * errno
+ *
+ * The context passed to each operation must be the context from the borrowed
+ * struct rust_ffi. It remains valid until the VF driver is fully unbound,
+ * including the return of its remove() callback when present.
+ *
+ * @submit may sleep and must not be called from atomic context.
+ */
+struct rust_driver_sriov_ops {
+ int (*submit)(const void *context, u16 requester_id);
+};
+
+#endif /* _SAMPLES_RUST_DRIVER_SRIOV_H */
diff --git a/samples/rust/rust_driver_sriov.rs b/samples/rust/rust_driver_sriov.rs
index ae1e1babb66b..f3e37586b0f4 100644
--- a/samples/rust/rust_driver_sriov.rs
+++ b/samples/rust/rust_driver_sriov.rs
@@ -10,15 +10,24 @@
//!
//! and append `intel_iommu=on` to the guest kernel arguments.
//!
+//! The optional `rust_driver_sriov_c_vf` module demonstrates a C VF calling the same PF data
+//! through an FFI operations table.
+//! Load that module before this one and enable VFs only after both drivers are registered.
+//!
//! [igb]: https://www.qemu.org/docs/master/system/devices/igb.html
//! [vIOMMU]: https://wiki.qemu.org/Features/VT-d
use kernel::{
+ bindings,
device::{
Bound,
Core, //
},
driver,
+ interop::ffi::{
+ Abi,
+ Token, //
+ },
new_mutex,
pci,
prelude::*,
@@ -45,8 +54,9 @@ struct PfApi<'bound> {
type PfApiForLt = CovariantForLt!(PfApi<'_>);
+#[kernel::macros::ffi_vtable(SAMPLE_FFI_OPS: bindings::rust_driver_sriov_ops)]
impl PfApi<'_> {
- fn submit(self: Pin<&Self>, vf: &pci::Device<Bound>) -> Result<u64> {
+ fn submit(self: Pin<&Self>, requester_id: u16) -> Result {
let mut requests = self.requests.lock();
let request = (*requests).checked_add(1).ok_or(EOVERFLOW)?;
*requests = request;
@@ -54,15 +64,34 @@ fn submit(self: Pin<&Self>, vf: &pci::Device<Bound>) -> Result<u64> {
dev_info!(
self.pdev,
- "Handle PF request {} from VF devfn {:#x}.\n",
+ "Handle PF request {} from VF requester ID {:#06x}.\n",
request,
- vf.dev_id()
+ requester_id
);
- Ok(request)
+ Ok(())
}
}
+struct SampleFfiAbi;
+
+// SAFETY:
+// - `RawOps` and the token/version constants come from the C header shared with consumers;
+// - `SAMPLE_FFI_OPS` is initialized as that raw type by `ffi_vtable`; and
+// - every callback recovers the context as the pinned `PfApi` published below.
+unsafe impl Abi for SampleFfiAbi {
+ type Context = PfApiForLt;
+ type RawOps = bindings::rust_driver_sriov_ops;
+
+ const OPS: &'static Self::RawOps = &SAMPLE_FFI_OPS;
+ const TOKEN: Token = Token::new(
+ bindings::RUST_DRIVER_SRIOV_FFI_TOKEN_HIGH,
+ bindings::RUST_DRIVER_SRIOV_FFI_TOKEN_LOW,
+ );
+ const ABI_MAJOR: u16 = bindings::RUST_DRIVER_SRIOV_FFI_ABI_MAJOR as u16;
+ const ABI_MINOR: u16 = bindings::RUST_DRIVER_SRIOV_FFI_ABI_MINOR as u16;
+}
+
#[pin_data(PinnedDrop)]
struct PfDriverData<'bound> {
// Keep the device alive until the registration stops exposing `PfApi::pdev`.
@@ -125,7 +154,7 @@ fn probe<'bound>(
// - no other registration is created for this PF; and
// - VFs are enabled only after probe by `sriov_configure`.
_registration <- unsafe {
- pci::VfRegistration::new(
+ pci::VfRegistration::new_ffi::<SampleFfiAbi, _>(
pdev,
try_pin_init!(PfApi {
pdev,
@@ -191,8 +220,8 @@ fn probe<'bound>(
pdev.enable_device_mem()?;
pdev.set_master();
- let request = pf_api.submit(pdev)?;
- dev_info!(pdev, "Submitted request {} through PF data.\n", request);
+ pf_api.submit(pdev.dev_id())?;
+ dev_info!(pdev, "Submitted request through PF data.\n");
Ok(try_pin_init!(VfDriverData { pdev: pdev.into() }))
})
diff --git a/samples/rust/rust_driver_sriov_c_vf.c b/samples/rust/rust_driver_sriov_c_vf.c
new file mode 100644
index 000000000000..50df98867361
--- /dev/null
+++ b/samples/rust/rust_driver_sriov_c_vf.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "rust_driver_sriov.h"
+
+#define E1000_DEV_ID_82576_VF 0x10ca
+
+static const struct rust_ffi_token ffi_token = {
+ .high = RUST_DRIVER_SRIOV_FFI_TOKEN_HIGH,
+ .low = RUST_DRIVER_SRIOV_FFI_TOKEN_LOW,
+};
+
+static int rust_driver_sriov_c_vf_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ const struct rust_driver_sriov_ops *ops;
+ const struct rust_ffi *ffi;
+ int ret;
+
+ ffi = pci_iov_borrow_rust_pf_data(pdev, &ffi_token,
+ RUST_DRIVER_SRIOV_FFI_ABI_MAJOR,
+ RUST_DRIVER_SRIOV_FFI_ABI_MINOR,
+ sizeof(*ops));
+ if (IS_ERR(ffi))
+ return dev_err_probe(&pdev->dev, PTR_ERR(ffi),
+ "failed to borrow PF FFI\n");
+
+ ops = ffi->ops;
+ if (!ops->submit)
+ return dev_err_probe(&pdev->dev, -EOPNOTSUPP,
+ "PF FFI does not implement submit\n");
+
+ ret = ops->submit(ffi->context, pci_dev_id(pdev));
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to submit through PF FFI\n");
+
+ pci_info(pdev, "submitted request through Rust PF FFI\n");
+
+ return 0;
+}
+
+static const struct pci_device_id rust_driver_sriov_c_vf_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_VF) },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, rust_driver_sriov_c_vf_id_table);
+
+static struct pci_driver rust_driver_sriov_c_vf_driver = {
+ .name = "rust_driver_sriov_c_vf",
+ .id_table = rust_driver_sriov_c_vf_id_table,
+ .probe = rust_driver_sriov_c_vf_probe,
+};
+module_pci_driver(rust_driver_sriov_c_vf_driver);
+
+MODULE_AUTHOR("Rust for Linux Contributors");
+MODULE_DESCRIPTION("C VF consumer for the Rust SR-IOV driver sample");
+MODULE_LICENSE("GPL");
next prev parent reply other threads:[~2026-09-15 20:59 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-15 20:56 [PATCH 00/14] Add Rust PCI SR-IOV support Zhi Wang
2026-09-15 20:56 ` [PATCH 01/14] PCI: add driver flag to opt into disabling SR-IOV on remove() Zhi Wang
2026-09-15 20:56 ` [PATCH 02/14] rust: pci: add {enable,disable}_sriov(), to control SR-IOV capability Zhi Wang
2026-09-15 20:56 ` [PATCH 03/14] rust: pci: add vtable attribute to pci::Driver trait Zhi Wang
2026-09-15 20:56 ` [PATCH 04/14] rust: pci: add bus callback sriov_configure(), to control SR-IOV from sysfs Zhi Wang
2026-09-15 20:56 ` [PATCH 05/14] rust: pci: add is_virtfn(), to check for VFs Zhi Wang
2026-09-15 20:56 ` [PATCH 06/14] rust: pci: add is_physfn(), to check for PFs Zhi Wang
2026-09-15 20:56 ` [PATCH 07/14] rust: pci: add num_vf(), to return number of VFs Zhi Wang
2026-09-15 20:56 ` [PATCH 08/14] rust: pci: add typed SR-IOV PF registration data Zhi Wang
2026-09-15 20:56 ` [PATCH 09/14] samples: rust: add Rust SR-IOV VF driver sample Zhi Wang
2026-09-15 20:56 ` [PATCH 10/14] rust: add C-to-Rust FFI descriptors and trampolines Zhi Wang
2026-09-15 20:56 ` [PATCH 11/14] rust: pci: add C FFI support to typed SR-IOV PF registration data Zhi Wang
2026-09-15 20:56 ` Zhi Wang [this message]
2026-09-15 20:56 ` [PATCH 13/14] gpu: nova-core: publish typed SR-IOV PF data for VF drivers Zhi Wang
2026-09-15 20:56 ` [PATCH 14/14] Documentation: rust: explain SR-IOV PF data sharing with VFs Zhi Wang
2026-09-16 11:10 ` [PATCH 00/14] Add Rust PCI SR-IOV support Danilo Krummrich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260915205659.76841-13-zhiw@nvidia.com \
--to=zhiw@nvidia.com \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=airlied@gmail.com \
--cc=alex.gaynor@gmail.com \
--cc=alex@shazbot.org \
--cc=aliceryhl@google.com \
--cc=alkumar@nvidia.com \
--cc=aniketa@nvidia.com \
--cc=ankita@nvidia.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=cjia@nvidia.com \
--cc=dakr@kernel.org \
--cc=ecourtney@nvidia.com \
--cc=gary@garyguo.net \
--cc=jgg@nvidia.com \
--cc=jhubbard@nvidia.com \
--cc=kevin.tian@intel.com \
--cc=kjaju@nvidia.com \
--cc=kwankhede@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=nova-gpu@lists.linux.dev \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=simona@ffwll.ch \
--cc=skolothumtho@nvidia.com \
--cc=smitra@nvidia.com \
--cc=targupta@nvidia.com \
--cc=tmgross@umich.edu \
--cc=yishaih@nvidia.com \
--cc=zhiwang@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®