redox-driver-core: real MSI-X capability parse with bounded read + base bump
read_msix_capability previously read the whole config file unbounded (pc hang: the config char device never EOF'd at the time) and then returned None unconditionally. Now it reads at most 256 bytes (the standard capability chain region) and parses the chain for real: status bit, cap list walk, MSI-X (0x11) message-control table size. Includes base submodule bump for the pcid config EOF fix.
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::io::Read;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
/// IOMMU group for a PCI device. Reads `/scheme/iommu/domain/N` files
|
/// IOMMU group for a PCI device. Reads `/scheme/iommu/domain/N` files
|
||||||
@@ -119,17 +120,32 @@ pub fn propose_msix_vectors(bdf: &str, min: u16, max: u16) -> MsiXProposal {
|
|||||||
|
|
||||||
fn read_msix_capability(bdf: &str) -> Option<u16> {
|
fn read_msix_capability(bdf: &str) -> Option<u16> {
|
||||||
let path = format!("/scheme/pci/{}/config", bdf);
|
let path = format!("/scheme/pci/{}/config", bdf);
|
||||||
let data = fs::read(&path).ok()?;
|
let file = fs::File::open(&path).ok()?;
|
||||||
// The MSI-X capability is at offset 0x50 within the config space.
|
let mut data = Vec::new();
|
||||||
// A real implementation would parse the capability chain. We
|
// The standard capability chain lives in the first 256 bytes of
|
||||||
// conservatively report None unless the file is large enough to
|
// config space; reading must be bounded because the config file is
|
||||||
// contain the capability pointer.
|
// a character device (read_to_end streams until EOF otherwise).
|
||||||
if data.len() < 0x60 {
|
file.take(256).read_to_end(&mut data).ok()?;
|
||||||
|
if data.len() < 0x40 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
// Look for the MSI-X capability ID (0x11) in the chained list.
|
// Status register (0x06) bit 4: capability list present.
|
||||||
// Without parsing, return None — the caller uses the default.
|
if data[0x06] & 0x10 == 0 {
|
||||||
let _ = bdf;
|
return None;
|
||||||
|
}
|
||||||
|
let mut ptr = (data[0x34] & 0xFC) as usize;
|
||||||
|
for _ in 0..48 {
|
||||||
|
if ptr == 0 || ptr + 3 >= data.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if data[ptr] == 0x11 {
|
||||||
|
// MSI-X: Message Control at cap+2, table size in bits 0..10
|
||||||
|
// (encoded as N-1).
|
||||||
|
let ctrl = u16::from_le_bytes([data[ptr + 2], data[ptr + 3]]);
|
||||||
|
return Some((ctrl & 0x07FF) + 1);
|
||||||
|
}
|
||||||
|
ptr = (data[ptr + 1] & 0xFC) as usize;
|
||||||
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user