lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260130171026.1138617-2-zijing.zhang@ry.rs>
Date: Fri, 30 Jan 2026 17:10:25 +0000
From: Zijing Zhang <zijing.zhang@...rs>
To: dakr@...nel.org,
	ojeda@...nel.org
Cc: bhelgaas@...gle.com,
	kwilczynski@...nel.org,
	boqun.feng@...il.com,
	gary@...yguo.net,
	bjorn3_gh@...tonmail.com,
	lossin@...nel.org,
	a.hindborg@...nel.org,
	aliceryhl@...gle.com,
	tmgross@...ch.edu,
	linux-pci@...r.kernel.org,
	rust-for-linux@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	lianux.mm@...il.com,
	zijing.kernel@...il.com
Subject: [RFC PATCH 1/2] rust: pci: add config space accessors

Add basic PCI config space accessors to kernel::pci::Device.

The underlying C helpers may return positive PCIBIOS status codes; map them
to standard -errno values for Rust callers.

Signed-off-by: Zijing Zhang <zijing.zhang@...rs>
---
 rust/kernel/pci.rs | 86 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index bea76ca9c3da..229290ffde47 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -47,6 +47,26 @@
     IrqVector, //
 };
 
+// Mirrors `pcibios_err_to_errno()` in `include/linux/pci.h`.
+//
+// That helper is a C `static inline` and thus not directly callable from Rust.
+// We keep the mapping local to this module so the `Device` API stays focused.
+fn pcibios_err_to_errno(err: c_int) -> c_int {
+    if err <= 0 {
+        return err;
+    }
+
+    match err as u32 {
+        bindings::PCIBIOS_FUNC_NOT_SUPPORTED => -(bindings::ENOENT as c_int),
+        bindings::PCIBIOS_BAD_VENDOR_ID => -(bindings::ENOTTY as c_int),
+        bindings::PCIBIOS_DEVICE_NOT_FOUND => -(bindings::ENODEV as c_int),
+        bindings::PCIBIOS_BAD_REGISTER_NUMBER => -(bindings::EFAULT as c_int),
+        bindings::PCIBIOS_SET_FAILED => -(bindings::EIO as c_int),
+        bindings::PCIBIOS_BUFFER_TOO_SMALL => -(bindings::ENOSPC as c_int),
+        _ => -(bindings::ERANGE as c_int),
+    }
+}
+
 /// An adapter for the registration of PCI drivers.
 pub struct Adapter<T: Driver>(T);
 
@@ -436,6 +456,72 @@ 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 })
     }
+
+    /// Reads a byte from PCI config space.
+    ///
+    /// `offset` is the config-space offset. For PCIe devices this may cover the extended config
+    /// space.
+    pub fn read_config_u8(&self, offset: u16) -> Result<u8> {
+        let offset = c_int::from(offset);
+        let mut val = 0u8;
+
+        // SAFETY: `self.as_raw()` points to a valid `struct pci_dev` and `val` is a valid out
+        // pointer.
+        let err = unsafe { bindings::pci_read_config_byte(self.as_raw(), offset, &mut val) };
+        to_result(pcibios_err_to_errno(err))?;
+        Ok(val)
+    }
+
+    /// Reads a 16-bit word from PCI config space.
+    pub fn read_config_u16(&self, offset: u16) -> Result<u16> {
+        let offset = c_int::from(offset);
+        let mut val = 0u16;
+
+        // SAFETY: `self.as_raw()` points to a valid `struct pci_dev` and `val` is a valid out
+        // pointer.
+        let err = unsafe { bindings::pci_read_config_word(self.as_raw(), offset, &mut val) };
+        to_result(pcibios_err_to_errno(err))?;
+        Ok(val)
+    }
+
+    /// Reads a 32-bit dword from PCI config space.
+    pub fn read_config_u32(&self, offset: u16) -> Result<u32> {
+        let offset = c_int::from(offset);
+        let mut val = 0u32;
+
+        // SAFETY: `self.as_raw()` points to a valid `struct pci_dev` and `val` is a valid out
+        // pointer.
+        let err = unsafe { bindings::pci_read_config_dword(self.as_raw(), offset, &mut val) };
+        to_result(pcibios_err_to_errno(err))?;
+        Ok(val)
+    }
+
+    /// Writes a byte to PCI config space.
+    pub fn write_config_u8(&self, offset: u16, val: u8) -> Result {
+        let offset = c_int::from(offset);
+
+        // SAFETY: `self.as_raw()` points to a valid `struct pci_dev`.
+        let err = unsafe { bindings::pci_write_config_byte(self.as_raw(), offset, val) };
+        to_result(pcibios_err_to_errno(err))
+    }
+
+    /// Writes a 16-bit word to PCI config space.
+    pub fn write_config_u16(&self, offset: u16, val: u16) -> Result {
+        let offset = c_int::from(offset);
+
+        // SAFETY: `self.as_raw()` points to a valid `struct pci_dev`.
+        let err = unsafe { bindings::pci_write_config_word(self.as_raw(), offset, val) };
+        to_result(pcibios_err_to_errno(err))
+    }
+
+    /// Writes a 32-bit dword to PCI config space.
+    pub fn write_config_u32(&self, offset: u16, val: u32) -> Result {
+        let offset = c_int::from(offset);
+
+        // SAFETY: `self.as_raw()` points to a valid `struct pci_dev`.
+        let err = unsafe { bindings::pci_write_config_dword(self.as_raw(), offset, val) };
+        to_result(pcibios_err_to_errno(err))
+    }
 }
 
 impl Device<device::Core> {
-- 
2.52.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ