mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-07-09 22:24:51 +00:00
agent: fix OVMF nested PCI path resolution
Treat three-segment PCI paths as pxb-only when the bus indicates pxb, preventing wrong root-bus lookup for nested OVMF hot-plug devices. Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com> Assisted-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
@@ -26,15 +26,29 @@ pub fn create_pci_root_bus_path(root_complex: &str) -> String {
|
||||
format!("/devices/pci0000:{root_complex}")
|
||||
}
|
||||
|
||||
/// Minimum guest PCI bus number used by pxb-pcie NUMA expander bridges in the
|
||||
/// runtime (see `busNrSpacing` in createNUMAPCIeTopology).
|
||||
const PXB_PCIE_ROOT_BUS_MIN: u8 = 0x20;
|
||||
|
||||
fn is_pxb_pcie_root_complex(segment: &str) -> bool {
|
||||
u8::from_str_radix(segment, 16)
|
||||
.map(|bus| bus >= PXB_PCIE_ROOT_BUS_MIN)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
// Parses a device tree path into a (root_complex, PCI path) pair.
|
||||
//
|
||||
// Supports two formats:
|
||||
// - Full NUMA path: "root_complex/bus/device" (e.g. "10/00/02") where the
|
||||
// first segment is the root complex and the rest form the PCI path.
|
||||
// - Legacy path: "bus/device" (e.g. "00/02") which defaults to root complex "00".
|
||||
// Supports three formats:
|
||||
// - NUMA pxb-pcie path: "root_complex/bus/device" (e.g. "20/00/02") where
|
||||
// the first segment is a pxb-pcie guest bus number (>= 0x20) and the rest
|
||||
// form the PCI path under that root complex.
|
||||
// - Nested hot-plug path on pci0000:00: "parent/bridge/device" (e.g.
|
||||
// "02/00/01") used by OVMF Q35 networking; stays on root complex "00".
|
||||
// - Legacy path: "bus/device" (e.g. "00/02") which defaults to root complex
|
||||
// "00".
|
||||
pub fn pcipath_from_dev_tree_path(dev_tree_path: &str) -> Result<(&str, pci::Path)> {
|
||||
let segments: Vec<&str> = dev_tree_path.split('/').collect();
|
||||
if segments.len() >= 3 {
|
||||
if segments.len() >= 3 && is_pxb_pcie_root_complex(segments[0]) {
|
||||
let root_complex = segments[0];
|
||||
let pci_part = &dev_tree_path[root_complex.len() + 1..];
|
||||
let pci_path = pci::Path::from_str(pci_part).with_context(|| {
|
||||
@@ -141,3 +155,36 @@ pub const U_EVENT_SUB_SYSTEM: &str = "SUBSYSTEM";
|
||||
pub const U_EVENT_SEQ_NUM: &str = "SEQNUM";
|
||||
pub const U_EVENT_DEV_NAME: &str = "DEVNAME";
|
||||
pub const U_EVENT_INTERFACE: &str = "INTERFACE";
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_pcipath_from_dev_tree_path_legacy() {
|
||||
let (root, path) = pcipath_from_dev_tree_path("02/01").unwrap();
|
||||
assert_eq!(root, "00");
|
||||
assert_eq!(path.len(), 2);
|
||||
assert_eq!(path[0].slot(), 0x02);
|
||||
assert_eq!(path[1].slot(), 0x01);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pcipath_from_dev_tree_path_nested_ovmf() {
|
||||
let (root, path) = pcipath_from_dev_tree_path("02/00/01").unwrap();
|
||||
assert_eq!(root, "00");
|
||||
assert_eq!(path.len(), 3);
|
||||
assert_eq!(path[0].slot(), 0x02);
|
||||
assert_eq!(path[1].slot(), 0x00);
|
||||
assert_eq!(path[2].slot(), 0x01);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pcipath_from_dev_tree_path_numa_pxb() {
|
||||
let (root, path) = pcipath_from_dev_tree_path("20/00/02").unwrap();
|
||||
assert_eq!(root, "20");
|
||||
assert_eq!(path.len(), 2);
|
||||
assert_eq!(path[0].slot(), 0x00);
|
||||
assert_eq!(path[1].slot(), 0x02);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user