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:
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user