pci: Refactor bus.rs to better fit a PCI bus's semantics

This commit refactors the PCI bus struct. It has two major focuses.
First, we change the type of `device_ids` in `PciBus` to an array. A
fixed-size array better reflects real PCI bus constraints, especially
its limited number of PCI devices. Moreover, it can't be grown
accidentally.

The second focus is changing the type of the key of `devices` in
`PciBus` to `u8`, since device IDs are not allowed to exceed 31. We
furthermore replace magic numbers with constants and make them publicly
available so we can use them in a follow-up change when parsing user
input.

Signed-off-by: Pascal Scholz <pascal.scholz@cyberus-technology.de>
On-behalf-of: SAP pascal.scholz@sap.com
This commit is contained in:
Pascal Scholz
2026-03-16 15:26:12 +01:00
committed by Rob Bradford
parent 43b5a474f9
commit afd155d578
3 changed files with 22 additions and 16 deletions

View File

@@ -20,9 +20,13 @@ use crate::configuration::{
};
use crate::device::{BarReprogrammingParams, DeviceRelocation, Error as PciDeviceError, PciDevice};
/// Denotes the PCI device ID of a bus' root bridge device.
pub const PCI_ROOT_DEVICE_ID: u8 = 0;
/// Denotes the maximum number of PCI devices allowed on a bus. 32 per PCI spec.
pub const NUM_DEVICE_IDS: u8 = 32;
const VENDOR_ID_INTEL: u16 = 0x8086;
const DEVICE_ID_INTEL_VIRT_PCIE_HOST: u16 = 0x0d57;
const NUM_DEVICE_IDS: usize = 32;
/// Errors for device manager.
#[derive(Error, Debug)]
@@ -113,18 +117,18 @@ impl PciDevice for PciRoot {
pub struct PciBus {
/// Devices attached to this bus.
/// Device 0 is host bridge.
devices: HashMap<u32, Arc<Mutex<dyn PciDevice>>>,
devices: HashMap<u8, Arc<Mutex<dyn PciDevice>>>,
device_reloc: Arc<dyn DeviceRelocation>,
device_ids: Vec<bool>,
device_ids: [bool; NUM_DEVICE_IDS as usize],
}
impl PciBus {
pub fn new(pci_root: PciRoot, device_reloc: Arc<dyn DeviceRelocation>) -> Self {
let mut devices: HashMap<u32, Arc<Mutex<dyn PciDevice>>> = HashMap::new();
let mut device_ids: Vec<bool> = vec![false; NUM_DEVICE_IDS];
let mut devices: HashMap<u8, Arc<Mutex<dyn PciDevice>>> = HashMap::new();
let mut device_ids = [false; NUM_DEVICE_IDS as usize];
devices.insert(0, Arc::new(Mutex::new(pci_root)));
device_ids[0] = true;
devices.insert(PCI_ROOT_DEVICE_ID, Arc::new(Mutex::new(pci_root)));
device_ids[PCI_ROOT_DEVICE_ID as usize] = true;
PciBus {
devices,
@@ -158,7 +162,7 @@ impl PciBus {
Ok(())
}
pub fn add_device(&mut self, device_id: u32, device: Arc<Mutex<dyn PciDevice>>) -> Result<()> {
pub fn add_device(&mut self, device_id: u8, device: Arc<Mutex<dyn PciDevice>>) -> Result<()> {
self.devices.insert(device_id, device);
Ok(())
}
@@ -180,7 +184,7 @@ impl PciBus {
}
pub fn get_device_id(&mut self, id: usize) -> Result<()> {
if id < NUM_DEVICE_IDS {
if id < NUM_DEVICE_IDS as usize {
if self.device_ids[id] {
Err(PciRootError::AlreadyInUsePciDeviceSlot(id))
} else {
@@ -193,7 +197,7 @@ impl PciBus {
}
pub fn put_device_id(&mut self, id: usize) -> Result<()> {
if id < NUM_DEVICE_IDS {
if id < NUM_DEVICE_IDS as usize {
self.device_ids[id] = false;
Ok(())
} else {
@@ -240,7 +244,7 @@ impl PciConfigIo {
.lock()
.unwrap()
.devices
.get(&(device as u32))
.get(&(device as u8))
.map_or(0xffff_ffff, |d| {
d.lock().unwrap().read_config_register(register)
})
@@ -265,7 +269,7 @@ impl PciConfigIo {
}
let pci_bus = self.pci_bus.as_ref().lock().unwrap();
if let Some(d) = pci_bus.devices.get(&(device as u32)) {
if let Some(d) = pci_bus.devices.get(&(device as u8)) {
let mut device = d.lock().unwrap();
// Update the register value
@@ -376,7 +380,7 @@ impl PciConfigMmio {
.lock()
.unwrap()
.devices
.get(&(device as u32))
.get(&(device as u8))
.map_or(0xffff_ffff, |d| {
d.lock().unwrap().read_config_register(register)
})
@@ -395,7 +399,7 @@ impl PciConfigMmio {
}
let pci_bus = self.pci_bus.lock().unwrap();
if let Some(d) = pci_bus.devices.get(&(device as u32)) {
if let Some(d) = pci_bus.devices.get(&(device as u8)) {
let mut device = d.lock().unwrap();
// Update the register value

View File

@@ -21,7 +21,9 @@ use std::str::FromStr;
use serde::de::Visitor;
pub use self::bus::{PciBus, PciConfigIo, PciConfigMmio, PciRoot, PciRootError};
pub use self::bus::{
NUM_DEVICE_IDS, PCI_ROOT_DEVICE_ID, PciBus, PciConfigIo, PciConfigMmio, PciRoot, PciRootError,
};
pub use self::configuration::{
PCI_CONFIGURATION_ID, PciBarConfiguration, PciBarPrefetchable, PciBarRegionType, PciCapability,
PciCapabilityId, PciClassCode, PciConfiguration, PciExpressCapabilityId, PciHeaderType,

View File

@@ -4125,7 +4125,7 @@ impl DeviceManager {
.unwrap();
pci_bus
.add_device(bdf.device() as u32, pci_device)
.add_device(bdf.device(), pci_device)
.map_err(DeviceManagerError::AddPciDevice)?;
self.bus_devices.push(Arc::clone(&bus_device));