diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 303a9bf30..161eb0f59 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -2011,4 +2011,38 @@ impl vm::Vm for MshvVm { )) }) } + + #[cfg(feature = "sev_snp")] + fn gain_page_access(&self, gpa: u64, size: u32) -> vm::Result<()> { + if !self.sev_snp_enabled { + return Ok(()); + } + + let start_gpfn: u64 = gpa >> PAGE_SHIFT; + let end_gpfn: u64 = (gpa + size as u64 - 1) >> PAGE_SHIFT; + + let gpas: Vec = (start_gpfn..=end_gpfn).map(|x| x << PAGE_SHIFT).collect(); + + if !gpas.is_empty() { + let mut gpa_list = vec_with_array_field::(gpas.len()); + gpa_list[0].gpa_list_size = gpas.len() as u64; + gpa_list[0].host_access = HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE; + gpa_list[0].acquire = 1; + gpa_list[0].flags = 0; + + // SAFETY: gpa_list initialized with gpas.len() and now it is being turned into + // gpas_slice with gpas.len() again. It is guaranteed to be large enough to hold + // everything from gpas. + unsafe { + let gpas_slice: &mut [u64] = gpa_list[0].gpa_list.as_mut_slice(gpas.len()); + gpas_slice.copy_from_slice(gpas.as_slice()); + } + + self.fd + .modify_gpa_host_access(&gpa_list[0]) + .map_err(|e| vm::HypervisorVmError::ModifyGpaHostAccess(e.into()))?; + } + + Ok(()) + } } diff --git a/hypervisor/src/vm.rs b/hypervisor/src/vm.rs index 68906bdb0..19563d0be 100644 --- a/hypervisor/src/vm.rs +++ b/hypervisor/src/vm.rs @@ -235,6 +235,12 @@ pub enum HypervisorVmError { /// #[error("Failed to set VM property: {0}")] SetVmProperty(#[source] anyhow::Error), + /// + /// Modify GPA host access error + /// + #[cfg(feature = "sev_snp")] + #[error("Failed to modify GPA host access: {0}")] + ModifyGpaHostAccess(#[source] anyhow::Error), } /// /// Result type for returning from a function @@ -404,6 +410,11 @@ pub trait Vm: Send + Sync + Any { fn resume(&self) -> Result<()> { Ok(()) } + + #[cfg(feature = "sev_snp")] + fn gain_page_access(&self, _gpa: u64, _size: u32) -> Result<()> { + Ok(()) + } } pub trait VmOps: Send + Sync {