diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index db18c6416..8cf43de4e 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -675,6 +675,25 @@ impl vm::Vm for KvmVm { Ok(()) } + #[cfg(all(feature = "sev_snp", target_arch = "x86_64"))] + fn complete_isolated_import( + &self, + snp_id_block: igvm_defs::IGVM_VHS_SNP_ID_BLOCK, + host_data: [u8; 32], + id_block_enabled: u8, + ) -> vm::Result<()> { + self.sev_fd + .as_ref() + .unwrap() + .launch_finish( + &self.fd, + host_data, + id_block_enabled, + snp_id_block.author_key_enabled, + ) + .map_err(|e| vm::HypervisorVmError::CompleteIsolatedImport(e.into())) + } + #[cfg(target_arch = "x86_64")] /// /// Sets the address of the one-page region in the VM's address space. diff --git a/hypervisor/src/kvm/x86_64/sev.rs b/hypervisor/src/kvm/x86_64/sev.rs index a2aebdd19..6249468fe 100644 --- a/hypervisor/src/kvm/x86_64/sev.rs +++ b/hypervisor/src/kvm/x86_64/sev.rs @@ -11,7 +11,7 @@ use std::path::Path; use igvm_defs::SnpPolicy; use kvm_bindings::kvm_sev_cmd; use kvm_ioctls::VmFd; -use log::{error, info}; +use log::{debug, error, info}; use vmm_sys_util::errno; pub(crate) type Result = std::result::Result; @@ -20,6 +20,7 @@ pub(crate) type Result = std::result::Result; const KVM_SEV_INIT2: u32 = 22; const KVM_SEV_SNP_LAUNCH_START: u32 = 100; const KVM_SEV_SNP_LAUNCH_UPDATE: u32 = 101; +const KVM_SEV_SNP_LAUNCH_FINISH: u32 = 102; // SNP_LAUNCH_UPDATE page types — linux/arch/x86/include/uapi/asm/sev-guest.h pub const SNP_PAGE_TYPE_VMSA: u32 = 2; @@ -80,6 +81,21 @@ pub(crate) struct KvmSevSnpLaunchUpdate { pub pad2: [u64; 4], } +#[repr(C, packed)] +#[derive(Debug, Copy, Clone, Default)] +pub(crate) struct KvmSevSnpLaunchFinish { + pub id_block_uaddr: u64, + pub id_auth_uaddr: u64, + pub id_block_en: u8, + pub auth_key_en: u8, + pub vcek_disabled: u8, + pub host_data: [u8; 32], + pub pad0: [u8; 3], + // must be zero https://elixir.bootlin.com/linux/v6.11/source/arch/x86/kvm/svm/sev.c#L2506 + pub flags: u16, + pub pad1: [u64; 4], +} + impl SevFd { pub(crate) fn new(sev_path: impl AsRef) -> Result { let file = OpenOptions::new() @@ -157,4 +173,28 @@ impl SevFd { }; sev_op(vm, &mut sev_cmd, "KVM_SEV_SNP_LAUNCH_UPDATE") } + + pub(crate) fn launch_finish( + &self, + vm: &VmFd, + host_data: [u8; 32], + id_block_en: u8, + auth_key_en: u8, + ) -> Result<()> { + let mut finish = KvmSevSnpLaunchFinish { + host_data, + id_block_en, + auth_key_en, + ..Default::default() + }; + let mut sev_cmd = kvm_sev_cmd { + id: KVM_SEV_SNP_LAUNCH_FINISH, + data: &mut finish as *mut KvmSevSnpLaunchFinish as _, + sev_fd: self.fd.as_raw_fd() as _, + ..Default::default() + }; + let flags = finish.flags; + debug!("Calling KVM_SEV_SNP_LAUNCH_FINISH, flags: {flags}"); + sev_op(vm, &mut sev_cmd, "KVM_SEV_SNP_LAUNCH_FINISH") + } } diff --git a/vmm/src/seccomp_filters.rs b/vmm/src/seccomp_filters.rs index 748e3b3b6..bc17cde4e 100644 --- a/vmm/src/seccomp_filters.rs +++ b/vmm/src/seccomp_filters.rs @@ -113,6 +113,7 @@ mod kvm { pub const KVM_SET_NESTED_STATE: u64 = 1082175167; pub const KVM_SEV_SNP_LAUNCH_START: u64 = 0x4018_aeb4; pub const KVM_SEV_SNP_LAUNCH_UPDATE: u64 = 0x8018_aeb5; + pub const KVM_SEV_SNP_LAUNCH_FINISH: u64 = 0x4008_aeb7; } mod iommufd { @@ -271,6 +272,7 @@ fn create_vmm_ioctl_seccomp_rule_common_kvm() -> Result, Backen and![Cond::new(1, ArgLen::Dword, Eq, KVM_SET_NESTED_STATE)?], and![Cond::new(1, ArgLen::Dword, Eq, KVM_SEV_SNP_LAUNCH_START)?], and![Cond::new(1, ArgLen::Dword, Eq, KVM_SEV_SNP_LAUNCH_UPDATE)?], + and![Cond::new(1, ArgLen::Dword, Eq, KVM_SEV_SNP_LAUNCH_FINISH)?], ]) }