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 <liuwe@microsoft.com>
This commit is contained in:
Wei Liu
2024-07-11 22:03:28 +00:00
committed by Bo Chen
parent cfaa192eb4
commit 18340d9761
+24 -16
View File
@@ -1529,16 +1529,11 @@ struct MshvEmulatorContext<'a> {
impl<'a> MshvEmulatorContext<'a> { impl<'a> MshvEmulatorContext<'a> {
// Do the actual gva -> gpa translation // Do the actual gva -> gpa translation
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
fn translate(&self, gva: u64) -> Result<u64, PlatformError> { fn translate(&self, gva: u64, flags: u32) -> Result<u64, PlatformError> {
if self.map.0 == gva { if self.map.0 == gva {
return Ok(self.map.1); 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 let (gpa, result_code) = self
.vcpu .vcpu
.translate_gva(gva, flags.into()) .translate_gva(gva, flags.into())
@@ -1549,15 +1544,14 @@ impl<'a> MshvEmulatorContext<'a> {
_ => Err(PlatformError::TranslateVirtualAddress(anyhow!(result_code))), _ => Err(PlatformError::TranslateVirtualAddress(anyhow!(result_code))),
} }
} }
}
#[cfg(target_arch = "x86_64")] fn read_memory_flags(
/// Platform emulation for Hyper-V &self,
impl<'a> PlatformEmulator for MshvEmulatorContext<'a> { gva: u64,
type CpuState = EmulatorCpuState; data: &mut [u8],
flags: u32,
fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError> { ) -> Result<(), PlatformError> {
let gpa = self.translate(gva)?; let gpa = self.translate(gva, flags)?;
debug!( debug!(
"mshv emulator: memory read {} bytes from [{:#x} -> {:#x}]", "mshv emulator: memory read {} bytes from [{:#x} -> {:#x}]",
data.len(), data.len(),
@@ -1575,9 +1569,19 @@ impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
Ok(()) 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> { 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!( debug!(
"mshv emulator: memory write {} bytes at [{:#x} -> {:#x}]", "mshv emulator: memory write {} bytes at [{:#x} -> {:#x}]",
data.len(), data.len(),
@@ -1644,7 +1648,11 @@ impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
let rip = let rip =
self.cpu_state(self.vcpu.vp_index as usize)? self.cpu_state(self.vcpu.vp_index as usize)?
.linearize(Register::CS, ip, false)?; .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,
)
} }
} }