tests: enable KVM SEV-SNP confidential VM integration tests

Bring the confidential VM (CVM) integration tests up on the KVM SEV-SNP
backend in addition to MSHV. On KVM the IGVM is an Oak stage0 firmware
image and the guest kernel is supplied separately: stage0 reads the
kernel, cmdline and E820 over fw_cfg. The test harness selects this
model when a guest kernel is present at /igvm_files/bzImage, mirroring
how the stage0 IGVM is discovered; MSHV keeps using the monolithic IGVM
with the kernel baked in.

  - test_infra: stage0 + direct-kernel + fw_cfg boot wiring (both the
    command line and the HTTP/D-Bus API path) plus an on_kvm_sev_snp()
    helper for tests to branch on.
  - tests: the CVM tests that don't work on the KVM SEV-SNP path yet are
    gated with #[cfg(not(feature = "kvm"))] inside the common_cvm module.
    The MSHV build enables mshv,igvm,sev_snp (no kvm feature) while the
    KVM build enables kvm,igvm,sev_snp,fw_cfg, so the cfg compiles these
    tests into the MSHV binary only and drops them on KVM; both
    hypervisors run the single common_cvm nextest profile. They all still
    run on MSHV:
      * test_pci_multiple_segments - stage0 places all 64-bit BARs in a
        single global window, so a BAR allocated in a different
        per-segment window is relocated cross-window and wedges boot.
      * test_dmi_uuid / test_dmi_oem_strings /
        test_dmi_system_and_chassis - SMBIOS is not delivered to SEV-SNP
        guests on the KVM stage0 boot path, so the guest's DMI tables
        read empty. VMM follow-up.
      * test_vdpa_block - needs host vdpa_sim_blk setup, and vDPA DMA
        into SEV-SNP-encrypted memory is unsupported (the guest hangs).

Assisted-by: Claude:Opus-4.8
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
This commit is contained in:
Ruben Hakobyan
2026-06-08 08:30:22 -07:00
committed by Rob Bradford
parent b1d33ec9aa
commit 2fc37a3235
6 changed files with 80 additions and 5 deletions

View File

@@ -1411,6 +1411,14 @@ impl Guest {
"cmdline": self.kernel_cmdline.as_deref().unwrap(),
"host_data": generate_host_data(),
});
// On the KVM direct-kernel path the kernel is supplied separately
// and read by stage0 over fw_cfg (see on_kvm_sev_snp).
if let Some(kernel) = sev_snp_direct_kernel() {
body["payload"]["kernel"] = serde_json::json!(kernel.to_str().unwrap());
body["payload"]["fw_cfg_config"] = serde_json::json!({
"initramfs": false,
});
}
} else {
body["payload"] = serde_json::json!({
"kernel": self.kernel_path.as_deref().unwrap(),
@@ -2027,6 +2035,19 @@ impl<'a> GuestCommand<'a> {
"--igvm",
igvm.to_str().expect("IGVM path is not valid UTF-8"),
]);
// On the KVM direct-kernel path the kernel is supplied separately
// (see on_kvm_sev_snp); pass it plus the guest cmdline so
// console/serial tests route output as in a regular direct boot.
if let Some(kernel) = sev_snp_direct_kernel() {
self.command.args([
"--kernel",
kernel.to_str().expect("kernel path is not valid UTF-8"),
]);
if let Some(cmdline) = &self.guest.kernel_cmdline {
self.command.args(["--cmdline", cmdline]);
}
self.command.args(["--fw-cfg-config", "initramfs=off"]);
}
self.command
.args(["--host-data", generate_host_data().as_str()]);
self.command.args([
@@ -2542,6 +2563,16 @@ impl Display for GuestVmType {
}
}
fn sev_snp_direct_kernel() -> Option<PathBuf> {
let kernel_path = PathBuf::from("/igvm_files/bzImage");
kernel_path.exists().then_some(kernel_path)
}
// True on the KVM SEV-SNP direct-kernel path.
pub fn on_kvm_sev_snp() -> bool {
sev_snp_direct_kernel().is_some()
}
// Get the direct igvm boot file path based on the console type
fn direct_igvm_boot_path(console: Option<&str>) -> Option<PathBuf> {
// get the default hvc0 igvm file if console string is not passed