From ac21f3662476f709f7095d80d8aa6ccd3a168dac Mon Sep 17 00:00:00 2001 From: Masato Imai Date: Tue, 5 Aug 2025 13:28:59 +0000 Subject: [PATCH] vmcs ctrls --- .../src/vmm/x86_64/intel/controls.rs | 114 +++++++++++++++++- nel_os_kernel/src/vmm/x86_64/intel/mod.rs | 4 + 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/nel_os_kernel/src/vmm/x86_64/intel/controls.rs b/nel_os_kernel/src/vmm/x86_64/intel/controls.rs index 2df8e7f..061dc18 100644 --- a/nel_os_kernel/src/vmm/x86_64/intel/controls.rs +++ b/nel_os_kernel/src/vmm/x86_64/intel/controls.rs @@ -1,4 +1,116 @@ +use crate::vmm::x86_64::{ + common, + intel::{vmcs, vmwrite}, +}; + pub fn setup_exec_controls() -> Result<(), &'static str> { - // TODO + let basic_msr = common::read_msr(0x480); + let mut raw_pin_exec_ctrl = u32::from(vmcs::controls::PinBasedVmExecutionControls::read()?); + + let reserved_bits = if basic_msr & (1 << 55) != 0 { + common::read_msr(0x48d) + } else { + common::read_msr(0x481) + }; + raw_pin_exec_ctrl |= (reserved_bits & 0xFFFFFFFF) as u32; + raw_pin_exec_ctrl &= (reserved_bits >> 32) as u32; + + let mut pin_exec_ctrl = vmcs::controls::PinBasedVmExecutionControls::from(raw_pin_exec_ctrl); + pin_exec_ctrl.set_external_interrupt_exiting(false); + + pin_exec_ctrl.write(); + + let mut raw_primary_exec_ctrl = + u32::from(vmcs::controls::PrimaryProcessorBasedVmExecutionControls::read()?); + + let reserved_bits = if basic_msr & (1 << 55) != 0 { + common::read_msr(0x48e) + } else { + common::read_msr(0x482) + }; + raw_primary_exec_ctrl |= (reserved_bits & 0xFFFFFFFF) as u32; + raw_primary_exec_ctrl &= (reserved_bits >> 32) as u32; + + let mut primary_exec_ctrl = + vmcs::controls::PrimaryProcessorBasedVmExecutionControls::from(raw_primary_exec_ctrl); + primary_exec_ctrl.set_hlt(true); + primary_exec_ctrl.set_activate_secondary_controls(true); + primary_exec_ctrl.set_use_tpr_shadow(false); + primary_exec_ctrl.set_use_msr_bitmap(false); + primary_exec_ctrl.set_unconditional_io(false); + primary_exec_ctrl.set_use_io_bitmap(false); // TODO: true + + primary_exec_ctrl.write(); + + let mut raw_secondary_exec_ctrl = + u32::from(vmcs::controls::SecondaryProcessorBasedVmExecutionControls::read()?); + + let reserved_bits = if basic_msr & (1 << 55) != 0 { + common::read_msr(0x48b) + } else { + 0 + }; + raw_secondary_exec_ctrl |= (reserved_bits & 0xFFFFFFFF) as u32; + raw_secondary_exec_ctrl &= (reserved_bits >> 32) as u32; + + let mut secondary_exec_ctrl = + vmcs::controls::SecondaryProcessorBasedVmExecutionControls::from(raw_secondary_exec_ctrl); + secondary_exec_ctrl.set_ept(false); // TODO: true + secondary_exec_ctrl.set_unrestricted_guest(false); //TODO: true + secondary_exec_ctrl.set_virtualize_apic_accesses(false); // TODO: true + + secondary_exec_ctrl.write(); + + vmwrite(0x6000, u64::MAX)?; + vmwrite(0x6002, u64::MAX)?; + + Ok(()) +} + +pub fn setup_entry_controls() -> Result<(), &'static str> { + let baisc_msr = common::read_msr(0x480); + + let mut raw_entry_ctrl = u32::from(vmcs::controls::EntryControls::read()?); + let reserved_bits = if baisc_msr & (1 << 55) != 0 { + common::read_msr(0x490) + } else { + common::read_msr(0x484) + }; + raw_entry_ctrl |= (reserved_bits & 0xFFFFFFFF) as u32; + raw_entry_ctrl &= (reserved_bits >> 32) as u32; + + let mut entry_ctrl = vmcs::controls::EntryControls::from(raw_entry_ctrl); + entry_ctrl.set_ia32e_mode_guest(false); + entry_ctrl.set_load_ia32_efer(true); + entry_ctrl.set_load_ia32_pat(true); + + entry_ctrl.write(); + + Ok(()) +} + +pub fn setup_exit_controls() -> Result<(), &'static str> { + let basic_msr = common::read_msr(0x480); + + let mut raw_exit_ctrl = u32::from(vmcs::controls::PrimaryExitControls::read()?); + let reserved_bits = if basic_msr & (1 << 55) != 0 { + common::read_msr(0x48f) + } else { + common::read_msr(0x483) + }; + raw_exit_ctrl |= (reserved_bits & 0xFFFFFFFF) as u32; + raw_exit_ctrl &= (reserved_bits >> 32) as u32; + + let mut exit_ctrl = vmcs::controls::PrimaryExitControls::from(raw_exit_ctrl); + exit_ctrl.set_host_addr_space_size(true); + exit_ctrl.set_save_ia32_efer(true); + exit_ctrl.set_save_ia32_pat(true); + exit_ctrl.set_load_ia32_efer(true); + exit_ctrl.set_load_ia32_pat(true); + + exit_ctrl.write(); + + vmwrite(0x4004, 1u64 << 6)?; // EXCEPTION_BITMAP + Ok(()) } diff --git a/nel_os_kernel/src/vmm/x86_64/intel/mod.rs b/nel_os_kernel/src/vmm/x86_64/intel/mod.rs index e63f755..0965e03 100644 --- a/nel_os_kernel/src/vmm/x86_64/intel/mod.rs +++ b/nel_os_kernel/src/vmm/x86_64/intel/mod.rs @@ -23,8 +23,12 @@ pub struct IntelVCpu { impl IntelVCpu { fn activate(&mut self) -> Result<(), &'static str> { + let revision_id = common::read_msr(0x480) as u32; + self.vmcs.write_revision_id(revision_id); self.vmcs.reset(); controls::setup_exec_controls()?; + controls::setup_entry_controls()?; + controls::setup_exit_controls()?; Ok(()) }