Skip to contentSkip to conversation

Rust PCI capability infrastructure and SR-IOV support

PATCH Superseded Zhi Wang 4 participants 8 messages Aug 27 – Oct 1

Subsystems (3)

v9 of 10 Superseded Latest is v10 →

lore
Share & tools
lore

Zhi Wang

author
#0 lore raw

v9 cover Rust PCI capability infrastructure and SR-IOV support

This is a follow-up to v8 [1].

The patch adds typed PCIe extended-capability lookup to the Rust PCI abstraction and an SR-IOV layout used by the nova-core vGPU boot work.

This series is based on current mainline. That base provides the existing num::casts helpers but not const_as!, so the const narrowing call uses the temporary turbofish form discussed during review. It can be converted as part of the subsequent const_as! migration before the old helper is removed.

Changes since v8:
- Made all raw ExtSriovRegs fields private. (Danilo)
- Added a read-only first_vf_offset() accessor for the GSP ABI and documented why pci_iov_virtfn_devfn() cannot replace it. (Danilo, Zhi)
- Simplified VF BAR decoding using a slot iterator and removed ExtSriovVfBars. (Alexandre, Danilo)
- Explained why I/O-space VF BAR encodings are rejected. (Alexandre)
- Clarified that decoded BAR addresses are PCI bus addresses. (Zhi)
- Removed unused ExtCapId::new() and kept as_raw() private. (Danilo)
- Replaced documented integer casts with the num::casts helpers available in current mainline. (Alexandre)
- Rebased onto current mainline.

[1] https://lore.kernel.org/rust-for-linux/[email protected]/

Zhi Wang (1):
rust: pci: add extended capability and SR-IOV support

 rust/helpers/pci.c     |   5 +
 rust/kernel/pci.rs     |   8 ++
 rust/kernel/pci/cap.rs | 290 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 303 insertions(+)
 create mode 100644 rust/kernel/pci/cap.rs

base-commit: 45c13f3f9e3bb15fd89ff2864c6f627a3b4b4229

Signature · 1 line
2.53.0
author
#1 lore raw

PATCH v9 1/1 rust: pci: add extended capability and SR-IOV support

Rust PCI drivers have no typed interface for locating and accessing PCIe extended capabilities.

The SR-IOV extended capability describes VF topology and VF BARs. Expose this information through the Rust PCI abstraction so drivers can use the existing typed configuration-space accessors instead of raw bindings.

Define ExtCapability to associate a capability ID with a register layout, and add ConfigSpace::find_ext_capability() to locate and project that layout. Bound the view at the next capability or the end of extended configuration space. Add ExtSriovRegs and a decoded VF BAR iterator that reads and validates all six VF BAR register slots up front, yields decoded BAR addresses and widths in logical order, and keeps the raw configuration-space slot advancement internal. Since PCI_EXT_CAP_NEXT() is a function-like macro, expose it through a Rust helper.

Keep raw SR-IOV registers private because PCI core owns their state. Expose the current First VF Offset through a read-only accessor because the Nova GSP ABI needs the raw 16-bit First VF Offset in Routing ID space. The pci_iov_virtfn_devfn() helper instead returns the low eight bits of a calculated VF Routing ID.

---
 rust/helpers/pci.c     |   5 +
 rust/kernel/pci.rs     |   8 ++
 rust/kernel/pci/cap.rs | 290 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 303 insertions(+)
 create mode 100644 rust/kernel/pci/cap.rs
rust/helpers/pci.c +5 -0
index a714cc2bfb7a..502f56e02fcc 100644
@@ -29,6 +29,11 @@ __rust_helper unsigned int rust_helper_pci_irq_type(struct pci_dev *pdev)
 	return pci_irq_type(pdev);
 }
 
+__rust_helper u32 rust_helper_pci_ext_cap_next(u32 header)
+{
+	return PCI_EXT_CAP_NEXT(header);
+}
+
 #ifndef CONFIG_PCI_IOV
 __rust_helper unsigned int
 rust_helper_pci_sriov_get_totalvfs(struct pci_dev *pdev)
rust/kernel/pci.rs +8 -0
index 3ec897709e89..77c52fe59551 100644
@@ -32,10 +32,18 @@
     },
 };
 
+mod cap;
 mod id;
 mod io;
 mod irq;
 
+pub use self::cap::{
+    ExtCapId,
+    ExtCapability,
+    ExtSriovCapability,
+    ExtSriovRegs,
+    ExtSriovVfBar, //
+};
 pub use self::id::{
     Class,
     ClassMask,
rust/kernel/pci/cap.rs new file +290 -0

290 lines not on this page · raw message

Signature · 1 line
2.53.0
#2 lore raw

Re: [PATCH v9 1/1] rust: pci: add extended capability and SR-IOV support

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] Missing `#[inline]` attribute on small abstraction functions or functions forwarding to a C…

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Missing #[inline] attribute on small abstraction functions or functions forwarding to a C binding. --

commit d6c524351183fb31a687066514aecd0e51e1aadf
Author: Zhi Wang <[email protected]>

rust: pci: add extended capability and SR-IOV support

Rust PCI drivers have no typed interface for locating and accessing PCIe extended capabilities. The SR-IOV extended capability describes VF topology and VF BARs. Expose this information through the Rust PCI abstraction so drivers can use the existing typed configuration-space accessors instead of raw bindings.

Quoted 5 lines
rust/kernel/pci/cap.rs new file +0 -0
new file mode 100644
index 0000000000000..74cd9e50e919b

[ ... ]

rust/kernel/pci/cap.rs line 83

Quoted 4 lines
rust/kernel/pci/cap.rs new file +4 -0
+    ///     Ok(())
+    /// }
+    /// ```
+    pub fn find_ext_capability<C: ExtCapability>(&self) -> Result<Option<ConfigSpace<'a, C>>> {

[Severity: Low]
Should this function be annotated with #[inline]?

This abstraction method in rust/kernel/pci/cap.rs forwards directly to the bindings::pci_find_ext_capability C call. According to the Rust subsystem guidelines, small functions or functions forwarding to a C binding call in abstraction crates should be annotated with #[inline].

Quoted 6 lines
rust/kernel/pci/cap.rs new file +6 -0
+        let offset = usize::from(
+            // SAFETY: `self.pdev` is valid by the type invariant of `ConfigSpace`.
+            unsafe {
+                bindings::pci_find_ext_capability(self.pdev.as_raw(), i32::from(C::ID.as_raw()))
+            },
+        );

[ ... ]

rust/kernel/pci/cap.rs line 116

Quoted 7 lines
rust/kernel/pci/cap.rs new file +7 -0
+    /// Calculates the size of the extended capability at `offset`.
+    ///
+    /// The capability extends to the next extended capability, or to the end of the extended
+    /// configuration space if it is the last one. `offset` must be a DWORD-aligned offset within
+    /// the extended configuration space returned by `pci_find_ext_capability`. Returns an error if
+    /// the capability header is outside the extended configuration space.
+    fn calculate_ext_cap_size(&self, offset: usize) -> Result<usize> {

[Severity: Low]
Would it be appropriate to add the #[inline] attribute to this small internal helper function as well?

Quoted 5 lines
rust/kernel/pci/cap.rs new file +5 -0
+        let header = self.try_read32(offset)?;
+        // SAFETY: Pure bit manipulation, no preconditions.
+        let next = casts::u32_as_usize(unsafe { bindings::pci_ext_cap_next(header) });
+
+        Ok(if next > offset {
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/2e9d992509299c2f13de48109c4c933f53817acb.1787830828.git.zhiw@nvidia.com?part=1
#3 lore raw

Re: [PATCH v9 1/1] rust: pci: add extended capability and SR-IOV support

In reply to Zhi Wang
Quoted 274 lines · Zhi Wang

Rust PCI drivers have no typed interface for locating and accessing PCIe extended capabilities.

The SR-IOV extended capability describes VF topology and VF BARs. Expose this information through the Rust PCI abstraction so drivers can use the existing typed configuration-space accessors instead of raw bindings.

Define ExtCapability to associate a capability ID with a register layout, and add ConfigSpace::find_ext_capability() to locate and project that layout. Bound the view at the next capability or the end of extended configuration space. Add ExtSriovRegs and a decoded VF BAR iterator that reads and validates all six VF BAR register slots up front, yields decoded BAR addresses and widths in logical order, and keeps the raw configuration-space slot advancement internal. Since PCI_EXT_CAP_NEXT() is a function-like macro, expose it through a Rust helper.

Keep raw SR-IOV registers private because PCI core owns their state. Expose the current First VF Offset through a read-only accessor because the Nova GSP ABI needs the raw 16-bit First VF Offset in Routing ID space. The pci_iov_virtfn_devfn() helper instead returns the low eight bits of a calculated VF Routing ID.

---
 rust/helpers/pci.c     |   5 +
 rust/kernel/pci.rs     |   8 ++
 rust/kernel/pci/cap.rs | 290 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 303 insertions(+)
 create mode 100644 rust/kernel/pci/cap.rs
rust/helpers/pci.c +5 -0
index a714cc2bfb7a..502f56e02fcc 100644
@@ -29,6 +29,11 @@ __rust_helper unsigned int rust_helper_pci_irq_type(struct pci_dev *pdev)
 	return pci_irq_type(pdev);
 }
 
+__rust_helper u32 rust_helper_pci_ext_cap_next(u32 header)
+{
+	return PCI_EXT_CAP_NEXT(header);
+}
+
 #ifndef CONFIG_PCI_IOV
 __rust_helper unsigned int
 rust_helper_pci_sriov_get_totalvfs(struct pci_dev *pdev)
rust/kernel/pci.rs +8 -0
index 3ec897709e89..77c52fe59551 100644
@@ -32,10 +32,18 @@
     },
 };
 
+mod cap;
 mod id;
 mod io;
 mod irq;
 
+pub use self::cap::{
+    ExtCapId,
+    ExtCapability,
+    ExtSriovCapability,
+    ExtSriovRegs,
+    ExtSriovVfBar, //
+};
 pub use self::id::{
     Class,
     ClassMask,
rust/kernel/pci/cap.rs new file +196 -0
new file mode 100644
index 000000000000..74cd9e50e919
@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! PCI extended capability support.
+
+use super::{
+    io::ConfigSpaceBackend,
+    ConfigSpace,
+    Extended, //
+};
+use crate::{
+    bindings,
+    io::{
+        Io,
+        IoBackend,
+        Region, //
+    },
+    num::{casts, Bounded},
+    prelude::*,
+};
+
+/// Number of VF BAR register slots in an SR-IOV capability.
+const NUM_VF_BARS: usize = casts::u32_as_usize(bindings::PCI_SRIOV_NUM_BARS);
+
+/// PCI extended capability IDs.
+#[repr(transparent)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct ExtCapId(u16);
+
+impl ExtCapId {
+    /// Single Root I/O Virtualization.
+    pub const SRIOV: Self = Self(casts::u32_into_u16::<{ bindings::PCI_EXT_CAP_ID_SRIOV }>());
+
+    /// Returns the raw PCIe extended capability ID.
+    #[inline]
+    const fn as_raw(self) -> u16 {
+        self.0
+    }
+}
+
+/// A typed PCI extended capability register layout.
+///
+/// Implementors describe the register layout of one extended capability. The layout must start at
+/// the extended capability header, and [`Self::ID`] must identify that layout.
+pub trait ExtCapability: FromBytes + IntoBytes {
+    /// PCI extended capability ID for this register layout.
+    const ID: ExtCapId;
+}
+
+impl<'a> ConfigSpace<'a, Extended> {
+    /// Finds and projects an extended capability into its typed register layout.
+    ///
+    /// Returns [`None`] if the device does not implement the capability.
+    ///
+    /// Returns an error if the capability is present but its register span is too small or
+    /// insufficiently aligned for `C`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use kernel::{
+    ///     device::Bound,
+    ///     pci,
+    ///     prelude::*,
+    /// };
+    ///
+    /// fn probe_sriov(pdev: &pci::Device<Bound>) -> Result {
+    ///     let Some(sriov) = pdev
+    ///         .config_space_extended()?
+    ///         .find_ext_capability::<pci::ExtSriovRegs>()?
+    ///     else {
+    ///         return Ok(());
+    ///     };
+    ///
+    ///     let first_vf_offset = sriov.first_vf_offset();
+    ///     let mut vf_bars = sriov.vf_bars()?;
+    ///     let bar0 = vf_bars.next().ok_or(EINVAL)?;
+    ///     let bar1 = vf_bars.next().ok_or(EINVAL)?;
+    ///     let bar2 = vf_bars.next().ok_or(EINVAL)?;
+    ///
+    ///     Ok(())
+    /// }
+    /// ```
+    pub fn find_ext_capability<C: ExtCapability>(&self) -> Result<Option<ConfigSpace<'a, C>>> {
+        let offset = usize::from(
+            // SAFETY: `self.pdev` is valid by the type invariant of `ConfigSpace`.
+            unsafe {
+                bindings::pci_find_ext_capability(self.pdev.as_raw(), i32::from(C::ID.as_raw()))
+            },
+        );
+
+        if offset == 0 {
+            return Ok(None);
+        }
+
+        let size = self.calculate_ext_cap_size(offset)?;
+
+        let base = ConfigSpaceBackend::as_ptr(*self)
+            .cast::<u8>()
+            .wrapping_add(offset);
+        let ptr = Region::<0>::ptr_try_from_raw_parts_mut(base, size)?;
+
+        // SAFETY: `offset` was returned by `pci_find_ext_capability`, and
+        // `calculate_ext_cap_size` bounds `ptr` at the next capability or the end of the extended
+        // configuration space. `ptr_try_from_raw_parts_mut` verified the region layout.
+        let capability = unsafe { ConfigSpaceBackend::project_view(*self, ptr) };
+
+        capability.try_cast::<C>().map(Some)
+    }
+
+    /// Calculates the size of the extended capability at `offset`.
+    ///
+    /// The capability extends to the next extended capability, or to the end of the extended
+    /// configuration space if it is the last one. `offset` must be a DWORD-aligned offset within
+    /// the extended configuration space returned by `pci_find_ext_capability`. Returns an error if
+    /// the capability header is outside the extended configuration space.
+    fn calculate_ext_cap_size(&self, offset: usize) -> Result<usize> {
+        let header = self.try_read32(offset)?;
+        // SAFETY: Pure bit manipulation, no preconditions.
+        let next = casts::u32_as_usize(unsafe { bindings::pci_ext_cap_next(header) });
+
+        Ok(if next > offset {
+            next - offset
+        } else {
+            self.size() - offset
+        })
+    }
+}
+
+/// SR-IOV register layout per PCIe spec (64 bytes starting at cap offset).
+///
+/// The raw registers are private because PCI core owns SR-IOV state management. Drivers should use
+/// PCI core APIs for operations such as enabling VFs and querying their topology.
+#[repr(C)]
+#[derive(FromBytes, IntoBytes)]
+pub struct ExtSriovRegs {
+    /// Extended capability header.
+    _header: u32,
+    /// SR-IOV capabilities.
+    _cap: u32,
+    /// SR-IOV control.
+    _ctrl: u16,
+    /// SR-IOV status.
+    _status: u16,
+    /// Initial VFs.
+    _initial_vfs: u16,
+    /// Total VFs.
+    _total_vfs: u16,
+    /// Number of VFs.
+    _num_vfs: u16,
+    /// Function dependency link.
+    _func_dep_link: u8,
+    _reserved_0: u8,
+    /// First VF offset.
+    vf_offset: u16,
+    /// VF stride.
+    _vf_stride: u16,
+    _reserved_1: u16,
+    /// VF device ID.
+    _vf_device_id: u16,
+    /// Supported page sizes.
+    _supported_page_sizes: u32,
+    /// System page size.
+    _system_page_size: u32,
+    /// VF BARs (BAR0–BAR5).
+    vf_bar: [u32; NUM_VF_BARS],
+    /// VF migration state array offset.
+    _migration_state: u32,
+}
+
+impl ExtCapability for ExtSriovRegs {
+    const ID: ExtCapId = ExtCapId::SRIOV;
+}
+
+/// A typed view of an SR-IOV extended capability.
+pub type ExtSriovCapability<'a> = ConfigSpace<'a, ExtSriovRegs>;
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum VfBarMemoryType {
+    Bits32,
+    Bits64,
+}
+
+impl TryFrom<Bounded<u32, 2>> for VfBarMemoryType {
+    type Error = Error;
+
+    fn try_from(value: Bounded<u32, 2>) -> Result<Self> {
+        match value.get() {
+            0b00 => Ok(Self::Bits32),
+            0b10 => Ok(Self::Bits64),
+            _ => Err(EINVAL),
+        }
+    }
+}
+
+impl From<VfBarMemoryType> for Bounded<u32, 2> {
+    fn from(value: VfBarMemoryType) -> Self {

rust/kernel/pci/cap.rs line 206

Quoted 10 lines
rust/kernel/pci/cap.rs new file +10 -0
+        match value {
+            VfBarMemoryType::Bits32 => Self::new::<0b00>(),
+            VfBarMemoryType::Bits64 => Self::new::<0b10>(),
+        }
+    }
+}
+
+crate::bitfield! {
+    /// Low DWORD of an SR-IOV VF BAR.
+    struct VfBarLow(u32) {

I admit not knowing that much about Rust but this caught my eye...

The PCIe spec says:

"These fields must define the VF’s Base Address Registers (BARs). These fields behave as normal PCI BARs, as described in § Section 7.5.1 ."

So why doesn't Rust just define this as "normal" BARs (given your naming above, I'd expect simply "BarLow") but names it after "VF" specifically? Or does Rust require duplicating things in cases like this for namespacing reasons?

"BarLow" doesn't seem to exist under mainline's rust/, maybe that hasn't been needed so far as C side code will likely be responsible for parsing them.

Quoted 22 lines
rust/kernel/pci/cap.rs new file +22 -0
+        /// Base address bits 31:4.
+        31:4 address;
+        /// Whether the address range is prefetchable.
+        3:3 prefetchable => bool;
+        /// Memory BAR type.
+        2:1 memory_type ?=> VfBarMemoryType;
+        /// Whether this is an I/O-space BAR.
+        0:0 io_space => bool;
+    }
+}
+
+/// A decoded VF BAR register encoding.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct ExtSriovVfBar {
+    /// The PCI bus address encoded by the BAR, without PCI attribute bits.
+    ///
+    /// This is not necessarily the CPU resource address.
+    pub address: u64,
+
+    /// Whether the BAR is 64-bit.
+    pub is_64bit: bool,
+}
Signature · 1 line
 i.
Quoted 62 lines
rust/kernel/pci/cap.rs new file +61 -0
+impl ExtSriovCapability<'_> {
+    /// Returns the current PCIe First VF Offset in Routing ID space.
+    ///
+    /// This value may change when NumVFs changes. Drivers should use PCI core helpers when they
+    /// need to calculate a VF BDF; this accessor is intended for interfaces that require the First
+    /// VF Offset itself.
+    #[inline]
+    pub fn first_vf_offset(&self) -> u16 {
+        crate::io_read!(*self, .vf_offset)
+    }
+
+    /// Returns an iterator over decoded VF BAR register encodings.
+    ///
+    /// All six raw VF BAR register slots are read and decoded up front. A 32-bit encoding yields
+    /// one entry; a 64-bit encoding combines two slots into one entry.
+    ///
+    /// A zero-valued low DWORD is yielded as a 32-bit BAR at address zero; this method does not
+    /// probe whether a BAR is implemented.
+    ///
+    /// Returns [`EINVAL`] and logs an error if a BAR low DWORD does not encode a 32-bit or 64-bit
+    /// memory BAR, or if a 64-bit encoding has no upper DWORD.
+    pub fn vf_bars(&self) -> Result<impl Iterator<Item = ExtSriovVfBar>> {
+        let slots: [u32; NUM_VF_BARS] =
+            core::array::from_fn(|slot| crate::io_read!(*self, .vf_bar[panic: slot]));
+        let mut slots = slots.into_iter();
+        let mut bars = [None; NUM_VF_BARS];
+        let mut count = 0;
+
+        let mut decode = || {
+            while let Some(low) = slots.next().map(VfBarLow::from) {
+                // SR-IOV VF BARs describe memory-space apertures; an I/O-space encoding is not
+                // valid for these registers.
+                if low.io_space() {
+                    return Err(EINVAL);
+                }
+
+                let low_address = u64::from(low.address()) << VfBarLow::ADDRESS_SHIFT;
+                let bar = match low.memory_type()? {
+                    VfBarMemoryType::Bits64 => ExtSriovVfBar {
+                        address: (u64::from(slots.next().ok_or(EINVAL)?) << 32) | low_address,
+                        is_64bit: true,
+                    },
+                    VfBarMemoryType::Bits32 => ExtSriovVfBar {
+                        address: low_address,
+                        is_64bit: false,
+                    },
+                };
+
+                bars[count] = Some(bar);
+                count += 1;
+            }
+
+            Ok(())
+        };
+
+        decode().inspect_err(|_| {
+            dev_err!(self.pdev, "invalid VF BAR encoding in SR-IOV capability\n");
+        })?;
+        Ok(bars.into_iter().flatten())
+    }
+}
#4 lore raw

Re: [PATCH v9 1/1] rust: pci: add extended capability and SR-IOV support

Quoted 1 line · Ilpo Järvinen

On Thu, 27 Aug 2026, Zhi Wang wrote:

<...>

Quoted 11 lines

rust/kernel/pci/cap.rs line 206

Quoted 3 lines
rust/kernel/pci/cap.rs new file +3 -0
+crate::bitfield! {
+    /// Low DWORD of an SR-IOV VF BAR.
+    struct VfBarLow(u32) {

I admit not knowing that much about Rust but this caught my eye...

The PCIe spec says:

"These fields must define the VF’s Base Address Registers (BARs). These fields behave as normal PCI BARs, as described in § Section 7.5.1 ."

Quoted 8 lines

So why doesn't Rust just define this as "normal" BARs (given your naming above, I'd expect simply "BarLow") but names it after "VF" specifically? Or does Rust require duplicating things in cases like this for namespacing reasons?

"BarLow" doesn't seem to exist under mainline's rust/, maybe that hasn't been needed so far as C side code will likely be responsible for parsing them.

Agreed, ultimately this BAR register should be defined in the PCI common code so it can be used across the abstraction without being redefined.

This is not a Rust requirement and technically nothing prevents a common declaration to be shared. It's more that we are still a bit in a phase where we are figuring things out and where the ground is moving under our feet (register definitions are still being actively worked on for instance), so keeping it defined here at first may help reduce churn in the end. But at the very least we can probably drop the Vf prefix from its name (and from VfBarMemoryType) and add a // TODO: comment to eventually move it to the PCI common code.

Unless Danilo already knows where he wants to take this, in which case the register definition can be added in a separate patch.

reviewer Reviewed-by on v9 1/1
#5 lore raw

Re: [PATCH v9 1/1] rust: pci: add extended capability and SR-IOV support

In reply to Zhi Wang
Quoted 22 lines · Zhi Wang

Rust PCI drivers have no typed interface for locating and accessing PCIe extended capabilities.

The SR-IOV extended capability describes VF topology and VF BARs. Expose this information through the Rust PCI abstraction so drivers can use the existing typed configuration-space accessors instead of raw bindings.

Define ExtCapability to associate a capability ID with a register layout, and add ConfigSpace::find_ext_capability() to locate and project that layout. Bound the view at the next capability or the end of extended configuration space. Add ExtSriovRegs and a decoded VF BAR iterator that reads and validates all six VF BAR register slots up front, yields decoded BAR addresses and widths in logical order, and keeps the raw configuration-space slot advancement internal. Since PCI_EXT_CAP_NEXT() is a function-like macro, expose it through a Rust helper.

Keep raw SR-IOV registers private because PCI core owns their state. Expose the current First VF Offset through a read-only accessor because the Nova GSP ABI needs the raw 16-bit First VF Offset in Routing ID space. The pci_iov_virtfn_devfn() helper instead returns the low eight bits of a calculated VF Routing ID.

Quoted 4 lines
author
#6 lore raw

Re: [PATCH v9 1/1] rust: pci: add extended capability and SR-IOV support

On Sun, 06 Sep 2026 10:24:39 +0900
"Alexandre Courbot" <[email protected]> wrote:

Gentle ping for the next step. :)

Quoted 31 lines · Zhi Wang
Quoted 24 lines

Rust PCI drivers have no typed interface for locating and accessing PCIe extended capabilities.

The SR-IOV extended capability describes VF topology and VF BARs. Expose this information through the Rust PCI abstraction so drivers can use the existing typed configuration-space accessors instead of raw bindings.

Define ExtCapability to associate a capability ID with a register layout, and add ConfigSpace::find_ext_capability() to locate and project that layout. Bound the view at the next capability or the end of extended configuration space. Add ExtSriovRegs and a decoded VF BAR iterator that reads and validates all six VF BAR register slots up front, yields decoded BAR addresses and widths in logical order, and keeps the raw configuration-space slot advancement internal. Since PCI_EXT_CAP_NEXT() is a function-like macro, expose it through a Rust helper.

Keep raw SR-IOV registers private because PCI core owns their state. Expose the current First VF Offset through a read-only accessor because the Nova GSP ABI needs the raw 16-bit First VF Offset in Routing ID space. The pci_iov_virtfn_devfn() helper instead returns the low eight bits of a calculated VF Routing ID.

Quoted 4 lines

Link:
https://lore.kernel.org/rust-for-linux/[email protected]/
Cc: Alexandre Courbot <[email protected]> Cc: Gary Guo <[email protected]> Signed-off-by: Zhi Wang <[email protected]>

#7 lore raw

Re: [PATCH v9 1/1] rust: pci: add extended capability and SR-IOV support

Quoted 4 lines · Zhi Wang

On Sun, 06 Sep 2026 10:24:39 +0900
"Alexandre Courbot" <[email protected]> wrote:

Gentle ping for the next step. :)

I don't think we will land any dependency on this in drm-rust-next, so if Danilo is comfortable with it, this can go through the driver tree.