pcid: no panic on PCI 3.0 fallback config access; warning sweep

- fallback.rs: config reads at offset >= 256 (PCIe extended space) now
  return the PCI-standard 0xFFFFFFFF 'absent' value and writes are
  dropped, instead of panicking the PCI daemon. This is the exact
  behavior of real hardware and Linux's CF8 path on MCFG-less machines,
  and it lets MSI-X feature discovery degrade to INTx cleanly. Found by
  the first driver-manager QEMU gate (i440fx): pcid panicked at
  fallback.rs:65 and the boot hung.
- driver_handler.rs: drop vestigial func param from read_full_device_id.
- driver_interface/mod.rs: use Option::insert's return value directly
  (must_use) instead of discarding and re-reading as_ref.
This commit is contained in:
Red Bear OS
2026-07-23 20:13:17 +09:00
parent c72d4247a6
commit b0e760659c
3 changed files with 16 additions and 8 deletions
+12 -4
View File
@@ -61,8 +61,13 @@ impl ConfigRegionAccess for Pci {
Self::set_iopl();
let offset =
u8::try_from(offset).expect("offset too large for PCI 3.0 configuration space");
// PCI 3.0 I/O-port config space is 256 bytes. Reads beyond it
// (PCIe extended space) must return the PCI-standard "absent"
// value, exactly like real hardware and Linux's CF8 path —
// panicking here kills the PCI daemon on MCFG-less machines.
let Ok(offset) = u8::try_from(offset) else {
return u32::MAX;
};
let address = Self::address(address, offset);
Pio::<u32>::new(0xCF8).write(address);
@@ -74,8 +79,11 @@ impl ConfigRegionAccess for Pci {
Self::set_iopl();
let offset =
u8::try_from(offset).expect("offset too large for PCI 3.0 configuration space");
// Writes into PCIe extended space are dropped: the region does
// not exist in PCI 3.0 I/O-port mode.
let Ok(offset) = u8::try_from(offset) else {
return;
};
let address = Self::address(address, offset);
Pio::<u32>::new(0xCF8).write(address);
+2 -2
View File
@@ -8,7 +8,7 @@ use pcid_interface::FullDeviceId;
/// Read the full PCI device ID (vendor, device, class, etc.) from
/// the kernel's PCIe config space. Mirrors the data Linux's
/// xhci-pci.c uses to look up per-vendor quirks.
fn read_full_device_id(pcie: &Pcie, func: &PciFunction, addr: pci_types::PciAddress) -> Option<FullDeviceId> {
fn read_full_device_id(pcie: &Pcie, addr: pci_types::PciAddress) -> Option<FullDeviceId> {
// PCI config space offsets:
// 0x00..0x01: vendor_id
// 0x02..0x03: device_id
@@ -55,7 +55,7 @@ impl<'a> DriverHandler<'a> {
// (offsets 0x00, 0x02, 0x08) and class/subclass/interface
// (offset 0x08 upper bytes). This is what Linux's
// xhci-pci.c uses to look up quirks.
let device_id = read_full_device_id(pcie, &func, func.addr);
let device_id = read_full_device_id(pcie, func.addr);
DriverHandler {
func,
device_id,
+2 -2
View File
@@ -562,10 +562,10 @@ impl PciFunctionHandle {
let ptr = NonNull::new(ptr.cast::<u8>())
.ok_or_else(|| "physmap returned null".to_string())?;
mapped_bar.insert(MappedBar {
return Ok(mapped_bar.insert(MappedBar {
ptr,
bar_size,
});
}));
}
Ok(mapped_bar.as_ref().expect("BAR was just mapped"))
}