mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
tests: Add integration test for Generic Initiator
Add test_guest_numa_generic_initiator to validate ACPI Generic
Initiator Affinity (SRAT Type 5) support for VFIO device.
The test verifies the following :
- Guest VM boots with a VFIO device associated with a {cpu,
memort}-less NUMA node
- Guest Kernel correctly detects Generic Initiator through
ACPI tables SRAT, SLIT
- NUMA topology in the guest includes the device-only node
with correct distances
Invoked via :
./scripts/dev_cli.sh tests --integration -- --hypervisor kvm \
--test-filter test_guest_numa_generic_initiator
The test requires a real VFIO device bound to vfio-pci driver and
skips gracefully if hardware is unavailable.
Signed-off-by: Saravanan D <saravanand@crusoe.ai>
This commit is contained in:
committed by
Rob Bradford
parent
df67c3690e
commit
18768e9bf8
@@ -11063,6 +11063,120 @@ mod vfio {
|
|||||||
|
|
||||||
handle_child_output(r, &output);
|
handle_child_output(r, &output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_guest_numa_generic_initiator() {
|
||||||
|
// Skip test if VFIO device is not available or not ready
|
||||||
|
if !std::path::Path::new(NVIDIA_VFIO_DEVICE).exists() {
|
||||||
|
println!("SKIPPED: VFIO device {} not found", NVIDIA_VFIO_DEVICE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if device is bound to vfio-pci driver
|
||||||
|
let driver_path = format!("{}/driver", NVIDIA_VFIO_DEVICE);
|
||||||
|
if let Ok(driver) = std::fs::read_link(&driver_path) {
|
||||||
|
let driver_name = driver.file_name().unwrap_or_default().to_string_lossy();
|
||||||
|
if driver_name != "vfio-pci" {
|
||||||
|
println!(
|
||||||
|
"SKIPPED: VFIO device {} bound to {}, not vfio-pci",
|
||||||
|
NVIDIA_VFIO_DEVICE, driver_name
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!(
|
||||||
|
"SKIPPED: VFIO device {} not bound to any driver",
|
||||||
|
NVIDIA_VFIO_DEVICE
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let disk_config = UbuntuDiskConfig::new(JAMMY_VFIO_IMAGE_NAME.to_string());
|
||||||
|
let guest = Guest::new(Box::new(disk_config));
|
||||||
|
let api_socket = temp_api_path(&guest.tmp_dir);
|
||||||
|
|
||||||
|
// x86_64: Direct kernel boot
|
||||||
|
let mut child = GuestCommand::new(&guest)
|
||||||
|
.args(["--cpus", "boot=4"])
|
||||||
|
.args(["--memory", "size=0"])
|
||||||
|
.args(["--memory-zone", "id=mem0,size=1G", "id=mem1,size=1G"])
|
||||||
|
.args([
|
||||||
|
"--numa",
|
||||||
|
"guest_numa_id=0,cpus=[0-1],distances=[1@20,2@25],memory_zones=mem0",
|
||||||
|
"guest_numa_id=1,cpus=[2-3],distances=[0@20,2@30],memory_zones=mem1",
|
||||||
|
"guest_numa_id=2,device_id=vfio0,distances=[0@25,1@30]",
|
||||||
|
])
|
||||||
|
.args([
|
||||||
|
"--device",
|
||||||
|
&format!("id=vfio0,path={},iommu=on", NVIDIA_VFIO_DEVICE),
|
||||||
|
])
|
||||||
|
.args(["--kernel", fw_path(FwType::RustHypervisorFirmware).as_str()])
|
||||||
|
.args(["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
|
||||||
|
.args(["--api-socket", &api_socket])
|
||||||
|
.capture_output()
|
||||||
|
.default_disks()
|
||||||
|
.default_net()
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let r = std::panic::catch_unwind(|| {
|
||||||
|
guest.wait_vm_boot().unwrap();
|
||||||
|
|
||||||
|
// Verify NUMA topology is correct
|
||||||
|
guest.check_numa_common(
|
||||||
|
Some(&[960_000, 960_000]),
|
||||||
|
Some(&[&[0, 1], &[2, 3]]),
|
||||||
|
Some(&["10 20 25", "20 10 30", "25 30 10"]),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify Generic Initiator support is present
|
||||||
|
// Linux kernel sets has_generic_initiator when it parses Type 5 SRAT entries
|
||||||
|
let has_gi = guest
|
||||||
|
.ssh_command(
|
||||||
|
"cat /sys/devices/system/node/has_generic_initiator 2>/dev/null || echo 0",
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.trim()
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
has_gi, "2",
|
||||||
|
"Generic Initiator support should be detected by kernel"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify SRAT table contains Generic Initiator entry (Type 5)
|
||||||
|
// We'll check that /sys/firmware/acpi/tables/SRAT exists and contains our entry
|
||||||
|
let srat_check = guest
|
||||||
|
.ssh_command(
|
||||||
|
"[ -f /sys/firmware/acpi/tables/SRAT ] && echo 'exists' || echo 'missing'",
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.trim()
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
srat_check, "exists",
|
||||||
|
"SRAT table should exist in guest firmware"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Use hexdump to verify Type 5 entry is present
|
||||||
|
// Type 5 (0x05) should appear in the SRAT table
|
||||||
|
let srat_has_type5 = guest
|
||||||
|
.ssh_command("sudo hexdump -C /sys/firmware/acpi/tables/SRAT | grep -q '05 20' && echo 'found' || echo 'not_found'")
|
||||||
|
.unwrap()
|
||||||
|
.trim()
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
srat_has_type5, "found",
|
||||||
|
"SRAT table should contain Generic Initiator Affinity Structure (Type 5, Length 0x20/32)"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
kill_child(&mut child);
|
||||||
|
let output = child.wait_with_output().unwrap();
|
||||||
|
|
||||||
|
handle_child_output(r, &output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod live_migration {
|
mod live_migration {
|
||||||
|
|||||||
Reference in New Issue
Block a user