diff --git a/Cargo.lock b/Cargo.lock index 29c4df65a..7cd4d8e2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -624,7 +624,7 @@ dependencies = [ [[package]] name = "mshv-bindings" version = "0.1.0" -source = "git+https://github.com/cloud-hypervisor/mshv?branch=master#547b86e74096a51ca7b9ec6737f5ec1baf5bbdea" +source = "git+https://github.com/cloud-hypervisor/mshv?branch=master#e1e078b51fb049b38e5db32cacd44569c0ea5a1f" dependencies = [ "libc", "serde", @@ -636,7 +636,7 @@ dependencies = [ [[package]] name = "mshv-ioctls" version = "0.1.0" -source = "git+https://github.com/cloud-hypervisor/mshv?branch=master#547b86e74096a51ca7b9ec6737f5ec1baf5bbdea" +source = "git+https://github.com/cloud-hypervisor/mshv?branch=master#e1e078b51fb049b38e5db32cacd44569c0ea5a1f" dependencies = [ "libc", "mshv-bindings", diff --git a/hypervisor/src/arch/emulator/mod.rs b/hypervisor/src/arch/emulator/mod.rs index 6fb4551ff..ce2d3bd37 100644 --- a/hypervisor/src/arch/emulator/mod.rs +++ b/hypervisor/src/arch/emulator/mod.rs @@ -47,8 +47,8 @@ pub enum PlatformError { #[error("Set CPU state failure: {0}")] SetCpuStateFailure(#[source] anyhow::Error), - #[error("Unmapped virtual address: {0}")] - UnmappedGVA(#[source] anyhow::Error), + #[error("Translate virtual address: {0}")] + TranslateGVA(#[source] anyhow::Error), #[error("Unsupported CPU Mode: {0}")] UnsupportedCpuMode(#[source] anyhow::Error), diff --git a/hypervisor/src/cpu.rs b/hypervisor/src/cpu.rs index b30cad3c6..3bf22ed57 100644 --- a/hypervisor/src/cpu.rs +++ b/hypervisor/src/cpu.rs @@ -23,6 +23,8 @@ use crate::CpuState; use crate::MpState; #[cfg(target_arch = "x86_64")] use crate::Xsave; +#[cfg(feature = "mshv")] +use mshv_bindings::*; use thiserror::Error; #[derive(Error, Debug)] @@ -198,6 +200,11 @@ pub enum HypervisorCpuError { /// #[error("Failed to set system register: {0}")] SetSysRegister(#[source] anyhow::Error), + /// + /// GVA translation error + /// + #[error("Failed to translate GVA: {0}")] + TranslateGVA(#[source] anyhow::Error), } #[derive(Debug)] @@ -398,4 +405,9 @@ pub trait Vcpu: Send + Sync { /// Triggers the running of the current virtual CPU returning an exit reason. /// fn run(&self) -> std::result::Result; + #[cfg(all(feature = "mshv", target_arch = "x86_64"))] + /// + /// Translate guest virtual address to guest physical address + /// + fn translate_gva(&self, gva: u64, flags: u64) -> Result<(u64, hv_translate_gva_result)>; } diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 3a6a4b22c..346177cd9 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -528,6 +528,18 @@ impl cpu::Vcpu for MshvVcpu { xsave, }) } + #[cfg(target_arch = "x86_64")] + /// + /// Translate guest virtual address to guest physical address + /// + fn translate_gva(&self, gva: u64, flags: u64) -> cpu::Result<(u64, hv_translate_gva_result)> { + let r = self + .fd + .translate_gva(gva, flags) + .map_err(|e| cpu::HypervisorCpuError::TranslateGVA(e.into()))?; + + Ok(r) + } } struct MshvEmulatorContext<'a> { @@ -537,14 +549,25 @@ struct MshvEmulatorContext<'a> { impl<'a> MshvEmulatorContext<'a> { // Do the actual gva -> gpa translation + #[allow(non_upper_case_globals)] fn translate(&self, gva: u64) -> Result { if self.map.0 == gva { return Ok(self.map.1); } - // TODO Check if we could fallback to e.g. an hypercall for doing - // the translation for us. - todo!() + // TODO: More fine-grained control for the flags + let flags = HV_TRANSLATE_GVA_VALIDATE_READ | HV_TRANSLATE_GVA_VALIDATE_WRITE; + + let r = self + .vcpu + .translate_gva(gva, flags.into()) + .map_err(|e| PlatformError::TranslateGVA(anyhow!(e)))?; + + let result_code = unsafe { r.1.__bindgen_anon_1.result_code }; + match result_code { + hv_translate_gva_result_code_HvTranslateGvaSuccess => Ok(r.0), + _ => Err(PlatformError::TranslateGVA(anyhow!(result_code))), + } } }