From 18340d976188d3783a41dbc41cfc8723cabf0251 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Thu, 11 Jul 2024 22:03:28 +0000 Subject: [PATCH] hypervisor: mshv: fine-grained control over translation flags The assertion that only code emulation requires GVA to GPA translation is wrong. Allow the caller of `translate` to pass in permission flags directly. Provide a new method `read_memory_flags` so that we can add the EXECUTE permission flag where necessary. Signed-off-by: Wei Liu --- hypervisor/src/mshv/mod.rs | 40 +++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 3f878500f..a9469f93e 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -1529,16 +1529,11 @@ struct MshvEmulatorContext<'a> { impl<'a> MshvEmulatorContext<'a> { // Do the actual gva -> gpa translation #[allow(non_upper_case_globals)] - fn translate(&self, gva: u64) -> Result { + fn translate(&self, gva: u64, flags: u32) -> Result { if self.map.0 == gva { return Ok(self.map.1); } - // We can only get into here when executing guest code. Check for R and X permissions. In - // the future if we have other use cases, we may want to allow the caller to specify the - // flags. - let flags = HV_TRANSLATE_GVA_VALIDATE_READ | HV_TRANSLATE_GVA_VALIDATE_EXECUTE; - let (gpa, result_code) = self .vcpu .translate_gva(gva, flags.into()) @@ -1549,15 +1544,14 @@ impl<'a> MshvEmulatorContext<'a> { _ => Err(PlatformError::TranslateVirtualAddress(anyhow!(result_code))), } } -} -#[cfg(target_arch = "x86_64")] -/// Platform emulation for Hyper-V -impl<'a> PlatformEmulator for MshvEmulatorContext<'a> { - type CpuState = EmulatorCpuState; - - fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError> { - let gpa = self.translate(gva)?; + fn read_memory_flags( + &self, + gva: u64, + data: &mut [u8], + flags: u32, + ) -> Result<(), PlatformError> { + let gpa = self.translate(gva, flags)?; debug!( "mshv emulator: memory read {} bytes from [{:#x} -> {:#x}]", data.len(), @@ -1575,9 +1569,19 @@ impl<'a> PlatformEmulator for MshvEmulatorContext<'a> { Ok(()) } +} + +#[cfg(target_arch = "x86_64")] +/// Platform emulation for Hyper-V +impl<'a> PlatformEmulator for MshvEmulatorContext<'a> { + type CpuState = EmulatorCpuState; + + fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError> { + self.read_memory_flags(gva, data, HV_TRANSLATE_GVA_VALIDATE_READ) + } fn write_memory(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError> { - let gpa = self.translate(gva)?; + let gpa = self.translate(gva, HV_TRANSLATE_GVA_VALIDATE_WRITE)?; debug!( "mshv emulator: memory write {} bytes at [{:#x} -> {:#x}]", data.len(), @@ -1644,7 +1648,11 @@ impl<'a> PlatformEmulator for MshvEmulatorContext<'a> { let rip = self.cpu_state(self.vcpu.vp_index as usize)? .linearize(Register::CS, ip, false)?; - self.read_memory(rip, instruction_bytes) + self.read_memory_flags( + rip, + instruction_bytes, + HV_TRANSLATE_GVA_VALIDATE_READ | HV_TRANSLATE_GVA_VALIDATE_EXECUTE, + ) } }