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;
|
||||
|
||||
use std::fs;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
||||
/// 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> {
|
||||
let path = format!("/scheme/pci/{}/config", bdf);
|
||||
let data = fs::read(&path).ok()?;
|
||||
// The MSI-X capability is at offset 0x50 within the config space.
|
||||
// A real implementation would parse the capability chain. We
|
||||
// conservatively report None unless the file is large enough to
|
||||
// contain the capability pointer.
|
||||
if data.len() < 0x60 {
|
||||
let file = fs::File::open(&path).ok()?;
|
||||
let mut data = Vec::new();
|
||||
// The standard capability chain lives in the first 256 bytes of
|
||||
// config space; reading must be bounded because the config file is
|
||||
// a character device (read_to_end streams until EOF otherwise).
|
||||
file.take(256).read_to_end(&mut data).ok()?;
|
||||
if data.len() < 0x40 {
|
||||
return None;
|
||||
}
|
||||
// Look for the MSI-X capability ID (0x11) in the chained list.
|
||||
// Without parsing, return None — the caller uses the default.
|
||||
let _ = bdf;
|
||||
// Status register (0x06) bit 4: capability list present.
|
||||
if data[0x06] & 0x10 == 0 {
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user