> On 6 Jul 2026, at 09:44, Gary Guo <[email protected]> wrote:
> 
> In order to support I/O projection, we are splitting I/O types into two
> categories: owned objects and views. Owned objects have a specific type
> that is related to setting up and tearing down, while views can have their
> type changed with I/O projection.
> 
> Things like `IoMem` or `Bar` are owned objects, which requires setting up
> mapping and cleaning up on drop. On the other side, `ConfigSpace` is really
> just a view, as the resource is associated with the `pci::Device`.
> 
> Remove the `ConfigSpaceKind` bound on `ConfigSpace` and make it a generic
> view. This means that `ConfigSpace` object now represents a subregion and
> therefore encodes offset (as address of pointers) and size (as metadata of
> pointers) itself. The full region case is still supported with offset 0 and
> size of `cfg_size`.
> 
> Reviewed-by: Alexandre Courbot <[email protected]>
> Signed-off-by: Gary Guo <[email protected]>
> ---
> rust/kernel/pci/io.rs | 64 +++++++++++++++++++++++++++++----------------------
> 1 file changed, 36 insertions(+), 28 deletions(-)
> 
> diff --git a/rust/kernel/pci/io.rs b/rust/kernel/pci/io.rs
> index e0acb62f58a2..89f4bb483a7f 100644
> --- a/rust/kernel/pci/io.rs
> +++ b/rust/kernel/pci/io.rs
> @@ -18,7 +18,6 @@
>     ptr::KnownSize, //
> };
> use core::{
> -    marker::PhantomData,
>     ops::Deref, //
> };
> 
> @@ -53,33 +52,42 @@ pub const fn into_raw(self) -> usize {
> /// Alias for extended (4096-byte) PCIe configuration space.
> pub type Extended = Region<4096>;
> 
> -/// Trait for PCI configuration space size markers.
> -///
> -/// This trait is implemented by [`Normal`] and [`Extended`] to provide
> -/// compile-time knowledge of the configuration space size.
> -pub trait ConfigSpaceKind: KnownSize {}
> -
> -impl ConfigSpaceKind for Normal {}
> -
> -impl ConfigSpaceKind for Extended {}
> -
> -/// The PCI configuration space of a device.
> +/// A view of PCI configuration space of a device.
> ///
> /// Provides typed read and write accessors for configuration registers
> /// using the standard `pci_read_config_*` and `pci_write_config_*` helpers.
> ///
> -/// The generic parameter `S` indicates the maximum size of the 
> configuration space.
> -/// Use [`Normal`] for 256-byte legacy configuration space or [`Extended`] 
> for
> -/// 4096-byte PCIe extended configuration space (default).
> -pub struct ConfigSpace<'a, S: ?Sized + ConfigSpaceKind = Extended> {
> +/// The generic parameter `T` is the type of the view. The full 
> configuration space is also a
> +/// special type of view; in such cases, `T` can be [`Normal`] for 256-byte 
> legacy configuration
> +/// space or [`Extended`] for 4096-byte PCIe extended configuration space 
> (default).
> +///
> +/// # Invariants
> +///
> +/// `ptr` is aligned and range `ptr..ptr + KnownSize::size(ptr)` is within
> +/// `0..pdev.cfg_size().into_raw()`.
> +pub struct ConfigSpace<'a, T: ?Sized = Extended> {
>     pub(crate) pdev: &'a Device<device::Bound>,
> -    _marker: PhantomData<S>,
> +    ptr: *mut T,
> }
> 
> +impl<T: ?Sized> Copy for ConfigSpace<'_, T> {}
> +impl<T: ?Sized> Clone for ConfigSpace<'_, T> {
> +    #[inline]
> +    fn clone(&self) -> Self {
> +        *self
> +    }
> +}
> +
> +// SAFETY: `ConfigSpace<'_, T>` is conceptually `&T` but in I/O memory.
> +unsafe impl<T: ?Sized + Sync> Send for ConfigSpace<'_, T> {}
> +
> +// SAFETY: `ConfigSpace<'_, T>` is conceptually `&T` but in I/O memory.
> +unsafe impl<T: ?Sized + Sync> Sync for ConfigSpace<'_, T> {}
> +
> /// Implements [`IoCapable`] on [`ConfigSpace`] for `$ty` using `$read_fn` 
> and `$write_fn`.
> macro_rules! impl_config_space_io_capable {
>     ($ty:ty, $read_fn:ident, $write_fn:ident) => {
> -        impl<'a, S: ?Sized + ConfigSpaceKind> IoCapable<$ty> for 
> &ConfigSpace<'a, S> {
> +        impl<'a, T: ?Sized> IoCapable<$ty> for ConfigSpace<'a, T> {
>             unsafe fn io_read(self, address: usize) -> $ty {
>                 let mut val: $ty = 0;
> 
> @@ -112,19 +120,17 @@ unsafe fn io_write(self, value: $ty, address: usize) {
> impl_config_space_io_capable!(u16, pci_read_config_word, 
> pci_write_config_word);
> impl_config_space_io_capable!(u32, pci_read_config_dword, 
> pci_write_config_dword);
> 
> -impl<'a, S: ?Sized + ConfigSpaceKind> Io for &ConfigSpace<'a, S> {
> -    type Target = S;
> +impl<'a, T: ?Sized + KnownSize> Io for ConfigSpace<'a, T> {
> +    type Target = T;
> 
> -    /// Returns the base address of the I/O region. It is always 0 for 
> configuration space.
>     #[inline]
>     fn addr(self) -> usize {
> -        0
> +        self.ptr.addr()
>     }
> 
> -    /// Returns the maximum size of the configuration space.
>     #[inline]
>     fn maxsize(self) -> usize {
> -        self.pdev.cfg_size().into_raw()
> +        KnownSize::size(self.ptr)
>     }
> }
> 
> @@ -281,23 +287,25 @@ pub fn cfg_size(&self) -> ConfigSpaceSize {
>         }
>     }
> 
> -    /// Return an initialized normal (256-byte) config space object.
> +    /// Return a view of the normal (256-byte) config space.
>     pub fn config_space<'a>(&'a self) -> ConfigSpace<'a, Normal> {
> +        // INVARIANT: null is aligned and the range is within config space.
>         ConfigSpace {
>             pdev: self,
> -            _marker: PhantomData,
> +            ptr: Normal::ptr_from_raw_parts_mut(core::ptr::null_mut(), 
> self.cfg_size().into_raw()),
>         }
>     }
> 
> -    /// Return an initialized extended (4096-byte) config space object.
> +    /// Return a view of the extended (4096-byte) config space.
>     pub fn config_space_extended<'a>(&'a self) -> Result<ConfigSpace<'a, 
> Extended>> {
>         if self.cfg_size() != ConfigSpaceSize::Extended {
>             return Err(EINVAL);
>         }
> 
> +        // INVARIANT: null is aligned and we just checked the `cfg_size`.
>         Ok(ConfigSpace {
>             pdev: self,
> -            _marker: PhantomData,
> +            ptr: Extended::ptr_from_raw_parts_mut(core::ptr::null_mut(), 
> 4096),
>         })
>     }
> }
> 
> -- 
> 2.54.0
> 

Reviewed-by: Daniel Almeida <[email protected]>

Reply via email to