From 13ef424bf1826f2360b965e12e50dc5fd4a82986 Mon Sep 17 00:00:00 2001 From: Muminul Islam Date: Wed, 4 Oct 2023 18:07:45 -0700 Subject: [PATCH] vmm: Add IGVM to the config/commandline This patch adds igvm to the Vm config and params as well as the command line argument to pass igvm file to load into guest memory. The file must maintain the IGVM format. The CLI option is featured guarded by igvm feature gate. The IGVM(Independent Guest Virtual Machine) file format is designed to encapsulate all information required to launch a virtual machine on any given virtualization stack, with support for different isolation technologies such as AMD SEV-SNP and Intel TDX. At a conceptual level, this file format is a set of commands created by the tool that generated the file, used by the loader to construct the initial guest state. The file format also contains measurement information that the underlying platform will use to confirm that the file was loaded correctly and signed by the appropriate authorities. The IGVM file is generated by the tool: https://github.com/microsoft/igvm-tooling The IGVM file is parsed by the following crates: https://github.com/microsoft/igvm Signed-off-by: Muminul Islam --- Cargo.toml | 3 ++- fuzz/Cargo.toml | 3 +++ fuzz/fuzz_targets/linux_loader_cmdline.rs | 2 ++ src/main.rs | 9 ++++++++- vmm/Cargo.toml | 1 + vmm/src/config.rs | 17 ++++++++++++++++- vmm/src/lib.rs | 2 ++ vmm/src/vm_config.rs | 3 +++ 8 files changed, 37 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 07ac1bc19..e0cafcdb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,10 +71,11 @@ default = ["kvm", "io_uring"] dbus_api = ["zbus", "vmm/dbus_api"] dhat-heap = ["dhat"] # For heap profiling guest_debug = ["vmm/guest_debug"] +igvm = ["vmm/igvm", "mshv"] io_uring = ["vmm/io_uring"] kvm = ["vmm/kvm"] mshv = ["vmm/mshv"] -sev_snp = ["vmm/sev_snp", "mshv"] +sev_snp = ["igvm", "vmm/sev_snp", "mshv"] tdx = ["vmm/tdx"] tracing = ["vmm/tracing", "tracer/tracing"] diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 2c557abce..f5d27e1a3 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -8,6 +8,9 @@ edition = "2021" [package.metadata] cargo-fuzz = true +[features] +igvm = [] + [dependencies] block = { path = "../block" } devices = { path = "../devices" } diff --git a/fuzz/fuzz_targets/linux_loader_cmdline.rs b/fuzz/fuzz_targets/linux_loader_cmdline.rs index 82a1bd76d..747adf6f4 100644 --- a/fuzz/fuzz_targets/linux_loader_cmdline.rs +++ b/fuzz/fuzz_targets/linux_loader_cmdline.rs @@ -23,6 +23,8 @@ fuzz_target!(|bytes| { kernel: None, cmdline: Some(String::from_utf8_lossy(&bytes).to_string()), initramfs: None, + #[cfg(feature = "igvm")] + igvm: None, }; let kernel_cmdline = match vmm::vm::Vm::generate_cmdline(&payload_config) { Ok(cmdline) => cmdline, diff --git a/src/main.rs b/src/main.rs index 426d154c9..2edd116a4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -443,7 +443,14 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String .num_args(0) .group("vmm-config"), ); - + #[cfg(feature = "igvm")] + let app = app.arg( + Arg::new("igvm") + .long("igvm") + .help("Path to IGVM file to load.") + .num_args(1) + .group("vm-config"), + ); app.arg( Arg::new("version") .short('V') diff --git a/vmm/Cargo.toml b/vmm/Cargo.toml index 7ea86867a..313c6c226 100644 --- a/vmm/Cargo.toml +++ b/vmm/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" default = [] dbus_api = ["blocking", "futures", "zbus"] guest_debug = ["kvm", "gdbstub", "gdbstub_arch"] +igvm = [] io_uring = ["block/io_uring"] kvm = ["hypervisor/kvm", "vfio-ioctls/kvm", "vm-device/kvm", "pci/kvm"] mshv = ["hypervisor/mshv", "vfio-ioctls/mshv", "vm-device/mshv", "pci/mshv"] diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 17c906481..7ed48e0dd 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -398,6 +398,8 @@ pub struct VmParams<'a> { pub gdb: bool, pub platform: Option<&'a str>, pub tpm: Option<&'a str>, + #[cfg(feature = "igvm")] + pub igvm: Option<&'a str>, } impl<'a> VmParams<'a> { @@ -451,6 +453,8 @@ impl<'a> VmParams<'a> { #[cfg(feature = "guest_debug")] let gdb = args.contains_id("gdb"); let tpm: Option<&str> = args.get_one::("tpm").map(|x| x as &str); + #[cfg(feature = "igvm")] + let igvm = args.get_one::("igvm").map(|x| x as &str); VmParams { cpus, memory, @@ -480,6 +484,8 @@ impl<'a> VmParams<'a> { gdb, platform, tpm, + #[cfg(feature = "igvm")] + igvm, } } } @@ -2283,12 +2289,21 @@ impl VmConfig { numa = Some(numa_config_list); } - let payload = if vm_params.kernel.is_some() || vm_params.firmware.is_some() { + #[cfg(not(feature = "igvm"))] + let payload_present = vm_params.kernel.is_some() || vm_params.firmware.is_some(); + + #[cfg(feature = "igvm")] + let payload_present = + vm_params.kernel.is_some() || vm_params.firmware.is_some() || vm_params.igvm.is_some(); + + let payload = if payload_present { Some(PayloadConfig { kernel: vm_params.kernel.map(PathBuf::from), initramfs: vm_params.initramfs.map(PathBuf::from), cmdline: vm_params.cmdline.map(|s| s.to_string()), firmware: vm_params.firmware.map(PathBuf::from), + #[cfg(feature = "igvm")] + igvm: vm_params.igvm.map(PathBuf::from), }) } else { None diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 9f55c048c..1076f5611 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -302,6 +302,8 @@ pub fn feature_list() -> Vec { "dhat-heap".to_string(), #[cfg(feature = "guest_debug")] "guest_debug".to_string(), + #[cfg(feature = "igvm")] + "igvm".to_string(), #[cfg(feature = "io_uring")] "io_uring".to_string(), #[cfg(feature = "kvm")] diff --git a/vmm/src/vm_config.rs b/vmm/src/vm_config.rs index dc028d890..100a4898c 100644 --- a/vmm/src/vm_config.rs +++ b/vmm/src/vm_config.rs @@ -556,6 +556,9 @@ pub struct PayloadConfig { pub cmdline: Option, #[serde(default)] pub initramfs: Option, + #[cfg(feature = "igvm")] + #[serde(default)] + pub igvm: Option, } pub fn default_serial() -> ConsoleConfig {