From e230dfaa3d538011bdd61f94de0385d18dfdd951 Mon Sep 17 00:00:00 2001 From: vasilito Date: Thu, 23 Jul 2026 22:19:19 +0900 Subject: [PATCH] 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. --- .../source/src/modern_technology.rs | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/local/recipes/drivers/redox-driver-core/source/src/modern_technology.rs b/local/recipes/drivers/redox-driver-core/source/src/modern_technology.rs index c76b09b04e..9a9f5abe74 100644 --- a/local/recipes/drivers/redox-driver-core/source/src/modern_technology.rs +++ b/local/recipes/drivers/redox-driver-core/source/src/modern_technology.rs @@ -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 { 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 }