From 1757d83db38a74db5bfba4f658ab14a25b51fb3f Mon Sep 17 00:00:00 2001 From: Muminul Islam Date: Fri, 18 Oct 2024 17:10:59 -0700 Subject: [PATCH] hypervisor: Keep GHCB mapped address for each VCPU on MSHV For confidential VM on MSHV, GHCB page is the communication method between guest and host. All the CVM exits, VMM needs to read and write to the GHCB page. MSHV provides an option to remap the page to the root partition. This way VMM could directly read and write to the page and skip extra IOCTL and hypercall. This improvement makes the IO 10% faster. Signed-off-by: Muminul Islam --- hypervisor/src/mshv/mod.rs | 46 ++++++++++++++++++++++++++++++++++++++ hypervisor/src/vm.rs | 6 +++++ 2 files changed, 52 insertions(+) diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 7584dda14..c163b17cf 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -395,6 +395,20 @@ impl hypervisor::Hypervisor for MshvHypervisor { } } +#[cfg(feature = "sev_snp")] +struct Ghcb(*mut svm_ghcb_base); + +#[cfg(feature = "sev_snp")] +// SAFETY: struct is based on GHCB page in the hypervisor, +// safe to Send across threads +unsafe impl Send for Ghcb {} + +#[cfg(feature = "sev_snp")] +// SAFETY: struct is based on GHCB page in the hypervisor, +// safe to Sync across threads as this is only required for Vcpu trait +// functionally not used anyway +unsafe impl Sync for Ghcb {} + /// Vcpu struct for Microsoft Hypervisor pub struct MshvVcpu { fd: VcpuFd, @@ -405,6 +419,8 @@ pub struct MshvVcpu { msrs: Vec, vm_ops: Option>, vm_fd: Arc, + #[cfg(feature = "sev_snp")] + ghcb: Option, } /// Implementation of Vcpu trait for Microsoft Hypervisor @@ -1649,6 +1665,34 @@ impl vm::Vm for MshvVm { .fd .create_vcpu(id) .map_err(|e| vm::HypervisorVmError::CreateVcpu(e.into()))?; + + /* Map the GHCB page to the VMM(root) address space + * The map is available after the vcpu creation. This address is mapped + * to the overlay ghcb page of the Microsoft Hypervisor, don't have + * to worry about the scenario when a guest changes the GHCB mapping. + */ + #[cfg(feature = "sev_snp")] + let ghcb = if self.sev_snp_enabled { + // SAFETY: Safe to call as VCPU has this map already available upon creation + let addr = unsafe { + libc::mmap( + std::ptr::null_mut(), + HV_PAGE_SIZE, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_SHARED, + vcpu_fd.as_raw_fd(), + MSHV_VP_MMAP_OFFSET_GHCB as i64 * libc::sysconf(libc::_SC_PAGE_SIZE), + ) + }; + if addr == libc::MAP_FAILED { + // No point of continuing, without this mmap VMGEXIT will fail anyway + // Return error + return Err(vm::HypervisorVmError::MmapToRoot); + } + Some(Ghcb(addr as *mut svm_ghcb_base)) + } else { + None + }; let vcpu = MshvVcpu { fd: vcpu_fd, vp_index: id, @@ -1658,6 +1702,8 @@ impl vm::Vm for MshvVm { msrs: self.msrs.clone(), vm_ops, vm_fd: self.fd.clone(), + #[cfg(feature = "sev_snp")] + ghcb, }; Ok(Arc::new(vcpu)) } diff --git a/hypervisor/src/vm.rs b/hypervisor/src/vm.rs index 2d45a8d9e..b6f11c9ff 100644 --- a/hypervisor/src/vm.rs +++ b/hypervisor/src/vm.rs @@ -251,6 +251,12 @@ pub enum HypervisorVmError { #[cfg(feature = "sev_snp")] #[error("Failed to modify GPA host access: {0}")] ModifyGpaHostAccess(#[source] anyhow::Error), + /// + /// Failed to mmap + /// + #[cfg(feature = "sev_snp")] + #[error("Failed to mmap:")] + MmapToRoot, } /// /// Result type for returning from a function