diff --git a/src/context.rs b/src/context.rs index dc65d35..6873c81 100644 --- a/src/context.rs +++ b/src/context.rs @@ -161,7 +161,7 @@ impl LinuxContext { /// The initialized context of the instance's first process. /// It is used to initialize the vCPU context for the shim kernel which enters /// under Intel's long mode. - pub fn construct_guest64(rip: u64, cr3: u64, cr4: Cr4Flags) -> Self { + pub fn construct_guest64(rip: u64, cr3: u64, cr4: Cr4Flags, linux: &LinuxContext) -> Self { Self { rsp: 0, rip, @@ -238,8 +238,8 @@ impl LinuxContext { ia32_sysenter_esp: 0, ia32_sysenter_eip: 0, kernel_gsbase: 0, - pat: 0, - mtrr_def_type: 0, + pat: linux.pat, // Reuse PAT value provided by Linux. + mtrr_def_type: linux.mtrr_def_type, // Reuse MTRR value provided by Linux. } } diff --git a/src/vmx/vcpu.rs b/src/vmx/vcpu.rs index 441e4b8..f7f8a37 100644 --- a/src/vmx/vcpu.rs +++ b/src/vmx/vcpu.rs @@ -27,8 +27,8 @@ use super::definitions::VmxExitReason; use super::read_vmcs_revision_id; use super::structs::{EptpList, IOBitmap, MsrBitmap, VmxRegion}; use super::vmcs::{ - self, VmcsControl32, VmcsControl64, VmcsControlNW, VmcsGuest16, VmcsGuest32, VmcsGuest64, - VmcsGuestNW, VmcsHost16, VmcsHost32, VmcsHost64, VmcsHostNW, exit_qualification, + self, VmcsControl16, VmcsControl32, VmcsControl64, VmcsControlNW, VmcsGuest16, VmcsGuest32, + VmcsGuest64, VmcsGuestNW, VmcsHost16, VmcsHost32, VmcsHost64, VmcsHostNW, exit_qualification, interrupt_exit_info, }; use crate::LinuxContext; @@ -476,6 +476,7 @@ impl VmxVcpu { } self.setup_vmcs_control(ept_root, is_guest)?; + self.set_vpid(self.id as u16 + 1)?; self.unbind_from_current_processor()?; Ok(()) } @@ -699,6 +700,9 @@ impl VmxVcpu { } } + // Enable VPID to speed up `VMFUNC` operation. + val |= CpuCtrl2::ENABLE_VPID; + vmcs::set_control( VmcsControl32::SECONDARY_PROCBASED_EXEC_CONTROLS, Msr::IA32_VMX_PROCBASED_CTLS2, @@ -770,6 +774,14 @@ impl VmxVcpu { Ok(()) } + fn set_vpid(&mut self, vpid: u16) -> AxResult { + if vpid == 0 || vpid > 0xfffe { + return ax_err!(InvalidInput); + } + VmcsControl16::VPID.write(vpid)?; + Ok(()) + } + fn load_vmcs_guest(&self, linux: &mut LinuxContext) -> AxResult { linux.rip = VmcsGuestNW::RIP.read()? as _; linux.rsp = VmcsGuestNW::RSP.read()? as _;