diff --git a/src/main.rs b/src/main.rs index fba5fb3..7363fcb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,7 +56,6 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { let mut vcpu = VCpu::new(phys_mem_offset.as_u64(), &mut frame_allocator); vcpu.activate(); - vcpu.reset_vmcs().unwrap(); info!("vmlaunch..."); diff --git a/src/vmm/vcpu.rs b/src/vmm/vcpu.rs index d679d90..b777f64 100644 --- a/src/vmm/vcpu.rs +++ b/src/vmm/vcpu.rs @@ -1,8 +1,11 @@ use x86::{msr::rdmsr, vmx::VmFail}; -use crate::memory::BootInfoFrameAllocator; +use crate::{info, memory::BootInfoFrameAllocator}; -use super::{vmcs::Vmcs, vmxon::Vmxon}; +use super::{ + vmcs::{PinBasedVmExecutionControls, Vmcs}, + vmxon::Vmxon, +}; pub struct VCpu { pub vmxon: Vmxon, @@ -28,6 +31,39 @@ impl VCpu { let revision_id = unsafe { rdmsr(x86::msr::IA32_VMX_BASIC) } as u32; self.vmcs .write_revision_id(revision_id, self.phys_mem_offset); + self.reset_vmcs().unwrap(); + self.setup_exec_ctrls().unwrap(); + } + + pub fn setup_exec_ctrls(&mut self) -> Result<(), VmFail> { + let basic_msr = unsafe { rdmsr(x86::msr::IA32_VMX_BASIC) }; + let mut pin_exec_ctrl = PinBasedVmExecutionControls::read(); + + let reserved_bits = if basic_msr & (1 << 55) != 0 { + unsafe { rdmsr(x86::msr::IA32_VMX_TRUE_PINBASED_CTLS) } + } else { + unsafe { rdmsr(x86::msr::IA32_VMX_PINBASED_CTLS) } + }; + + pin_exec_ctrl.0 |= (reserved_bits & 0xFFFFFFFF) as u32; + pin_exec_ctrl.0 &= (reserved_bits >> 32) as u32; + + pin_exec_ctrl.write(); + + let mut primary_exec_ctrl = PinBasedVmExecutionControls::read(); + + let reserved_bits = if basic_msr & (1 << 55) != 0 { + unsafe { rdmsr(x86::msr::IA32_VMX_TRUE_PROCBASED_CTLS) } + } else { + unsafe { rdmsr(x86::msr::IA32_VMX_PROCBASED_CTLS) } + }; + + primary_exec_ctrl.0 |= (reserved_bits & 0xFFFFFFFF) as u32; + primary_exec_ctrl.0 &= (reserved_bits >> 32) as u32; + + primary_exec_ctrl.write(); + + Ok(()) } pub fn reset_vmcs(&mut self) -> Result<(), VmFail> { diff --git a/src/vmm/vmcs.rs b/src/vmm/vmcs.rs index 935fd58..5c20e2d 100644 --- a/src/vmm/vmcs.rs +++ b/src/vmm/vmcs.rs @@ -171,6 +171,57 @@ impl PinBasedVmExecutionControls { } } +/* + + _reserved1: u2, + interrupt_window: bool, + tsc_offsetting: bool, + _reserved2: u3, + hlt: bool, + _reserved3: u1, + invlpg: bool, + mwait: bool, + rdpmc: bool, + rdtsc: bool, + _reserved4: u2, + cr3load: bool, + cr3store: bool, + activate_teritary_controls: bool, + _reserved: u1, + cr8load: bool, + cr8store: bool, + use_tpr_shadow: bool, + nmi_window: bool, + mov_dr: bool, + unconditional_io: bool, + use_io_bitmap: bool, + _reserved5: u1, + monitor_trap: bool, + use_msr_bitmap: bool, + monitor: bool, + pause: bool, + activate_secondary_controls: bool, +*/ + +pub struct PrimaryProcessorBasedVmExecutionControls(pub u32); + +impl PrimaryProcessorBasedVmExecutionControls { + pub fn read() -> Self { + let err = VmcsControl32::PRIMARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS.read(); + if err.is_err() { + panic!("Failed to read Primary Processor Based VM Execution Controls"); + } + let err = err.unwrap(); + PrimaryProcessorBasedVmExecutionControls(err) + } + + pub fn write(&self) { + VmcsControl32::PRIMARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS + .write(self.0) + .expect("Failed to write Primary Processor Based VM Execution Controls"); + } +} + pub enum VmcsControl32 { PIN_BASED_VM_EXECUTION_CONTROLS = 0x00004000, PRIMARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS = 0x00004002,