[PATCH v3 3/5] rust: pci: add a helper to query configuration space size

Zhi Wang posted 5 patches 3 months, 1 week ago
There is a newer version of this series
[PATCH v3 3/5] rust: pci: add a helper to query configuration space size
Posted by Zhi Wang 3 months, 1 week ago
Expose a safe Rust wrapper for the `cfg_size` field of `struct pci_dev`,
allowing drivers to query the size of a device's configuration space.

This is useful for code that needs to know whether the device supports
extended configuration space (e.g. 256 vs 4096 bytes) when accessing PCI
configuration registers and apply runtime checks.

Cc: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Zhi Wang <zhiw@nvidia.com>
---
 rust/kernel/pci.rs | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 77a8eb39ad32..9ebba8e08d2e 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -418,6 +418,19 @@ fn as_raw(&self) -> *mut bindings::pci_dev {
     }
 }
 
+/// Represents the size of a PCI configuration space.
+///
+/// PCI devices can have either a *normal* (legacy) configuration space of 256 bytes,
+/// or an *extended* configuration space of 4096 bytes as defined in the PCI Express
+/// specification.
+pub enum ConfigSpaceSize {
+    /// 256-byte legacy PCI configuration space.
+    Normal = 256,
+
+    /// 4096-byte PCIe extended configuration space.
+    Extended = 4096,
+}
+
 impl Device {
     /// Returns the PCI vendor ID as [`Vendor`].
     ///
@@ -514,6 +527,17 @@ pub fn pci_class(&self) -> Class {
         // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`.
         Class::from_raw(unsafe { (*self.as_raw()).class })
     }
+
+    /// Returns the size of configuration space.
+    pub fn cfg_size(&self) -> Result<ConfigSpaceSize> {
+        // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`.
+        let size = unsafe { (*self.as_raw()).cfg_size };
+        match size {
+            256 => Ok(ConfigSpaceSize::Normal),
+            4096 => Ok(ConfigSpaceSize::Extended),
+            _ => Err(EINVAL),
+        }
+    }
 }
 
 impl Device<device::Bound> {
-- 
2.47.3
Re: [PATCH v3 3/5] rust: pci: add a helper to query configuration space size
Posted by Bjorn Helgaas 3 months, 1 week ago
On Thu, Oct 30, 2025 at 03:48:40PM +0000, Zhi Wang wrote:
> Expose a safe Rust wrapper for the `cfg_size` field of `struct pci_dev`,
> allowing drivers to query the size of a device's configuration space.
> 
> This is useful for code that needs to know whether the device supports
> extended configuration space (e.g. 256 vs 4096 bytes) when accessing PCI
> configuration registers and apply runtime checks.

What is the value of knowing the config space size, as opposed to just
having config space accessors return PCIBIOS_BAD_REGISTER_NUMBER or
similar when trying to read past the implemented size?

Apart from pci-sysfs and vfio, I don't really see any drivers that use
pdev->cfg_size today.
Re: [PATCH v3 3/5] rust: pci: add a helper to query configuration space size
Posted by Zhi Wang 3 months, 1 week ago
On Thu, 30 Oct 2025 11:51:15 -0500
Bjorn Helgaas <helgaas@kernel.org> wrote:

> On Thu, Oct 30, 2025 at 03:48:40PM +0000, Zhi Wang wrote:
> > Expose a safe Rust wrapper for the `cfg_size` field of `struct
> > pci_dev`, allowing drivers to query the size of a device's
> > configuration space.
> > 
> > This is useful for code that needs to know whether the device
> > supports extended configuration space (e.g. 256 vs 4096 bytes) when
> > accessing PCI configuration registers and apply runtime checks.
> 
> What is the value of knowing the config space size, as opposed to just
> having config space accessors return PCIBIOS_BAD_REGISTER_NUMBER or
> similar when trying to read past the implemented size?
> 

Per my understading, the Io trait aims to provide a generic I/O
validation that can be reused across different transports -
MMIO, PCI, SPI, and others - with each backend implementing its own
region boundaries while sharing the same pre-access validation logic.

By design, the framework needs to know the valid address range
before performing the actual access. Without exposing
cfg_size(), we would have to add PCI configuration-specific
handling inside the framework.

> Apart from pci-sysfs and vfio, I don't really see any drivers that use
> pdev->cfg_size today.

It is for the framework so far. If we believe that driver doesn't need
this in the near term, I can make it private in the next re-spin.

Z.
Re: [PATCH v3 3/5] rust: pci: add a helper to query configuration space size
Posted by Danilo Krummrich 3 months, 1 week ago
On Fri Oct 31, 2025 at 1:16 PM CET, Zhi Wang wrote:
> On Thu, 30 Oct 2025 11:51:15 -0500
> Bjorn Helgaas <helgaas@kernel.org> wrote:
>> Apart from pci-sysfs and vfio, I don't really see any drivers that use
>> pdev->cfg_size today.
>
> It is for the framework so far. If we believe that driver doesn't need
> this in the near term, I can make it private in the next re-spin.

Device::cfg_size() should indeed be private, I don't see a reason for drivers to
call this directly.

However, enum ConfigSpaceSize has to be public, such that we can implement a
method:

	pub fn config_space<'a, const SIZE: usize>(&'a self) -> Result<ConfigSpace<'a, SIZE>>

so the driver can assert whether it requires the normal or extended
configuration space size with e.g.:

	// Fails if the configuration space does not have an extended size.
	let cfg = pdev.config_space::<ConfigSpaceSize::Extended>()?;

Subsequently, we can do infallible accesses within the corresponding guaranteed
range.

Given that there are only two options, normal or extended, we can also drop the
const generic and just provide two separate methods:

	pub fn config_space<'a>(&'a self) -> Result<ConfigSpace<'a, ConfigSpaceSize::Normal>>

and

	pub fn config_space_extended<'a>(&'a self) -> Result<ConfigSpace<'a, ConfigSpaceSize::Extended>>

Allowing drivers to request a ConfigSpace<'a, 0> with only runtime checks makes
no sense, ConfigSpaceSize::Normal is always the minimum.

- Danilo