This commit is contained in:
Masato Imai
2025-04-21 08:11:53 +00:00
parent b8c097946c
commit 96f5c9e7d7
4 changed files with 74 additions and 50 deletions

View File

@@ -16,14 +16,10 @@ use nel_os::{
println,
vmm::{
support::{has_intel_cpu, has_vmx_support},
vmxon::Vmxon,
vcpu::VCpu,
},
};
use x86::bits64::rflags;
use x86_64::{
registers::{control::Cr0Flags, segmentation::Segment},
VirtAddr,
};
use x86_64::VirtAddr;
#[cfg(not(test))]
#[panic_handler]
@@ -57,50 +53,9 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
panic!("VMX not supported");
}
let mut vmxon = Vmxon::new(&mut frame_allocator);
vmxon.init(phys_mem_offset.as_u64());
vmxon.activate_vmxon().unwrap();
info!("Checking vmlaunch requirements...");
{
let mut success = true;
let cr0 = x86_64::registers::control::Cr0::read();
if cr0.contains(Cr0Flags::PROTECTED_MODE_ENABLE) {
info!("Protected mode is enabled");
} else {
info!("Protected mode is not enabled");
success = false;
}
let rflags = rflags::read();
if rflags.contains(rflags::RFlags::FLAGS_VM) {
info!("VM flag is enabled");
success = false;
} else {
info!("VM flag is not enabled");
}
let ia32_efer = unsafe { x86::msr::rdmsr(x86::msr::IA32_EFER) };
if (ia32_efer & 1 << 10) != 0 {
info!("IA32_EFER.LMA is enabled");
let cs = x86_64::registers::segmentation::CS::get_reg().0;
if cs & 0x1 == 0 {
info!("CS.L is enabled");
} else {
info!("CS.L is not enabled");
success = false;
}
} else {
info!("IA32_EFER.LMA is not enabled");
}
if success {
info!("vmlaunch requirements are met");
} else {
panic!("vmlaunch requirements are not met");
}
}
let mut vcpu = VCpu::new(phys_mem_offset.as_u64(), &mut frame_allocator);
vcpu.activate();
vcpu.reset_vmcs().unwrap();
info!("vmlaunch...");

View File

@@ -1,3 +1,5 @@
pub mod error;
pub mod support;
pub mod vcpu;
pub mod vmcs;
pub mod vmxon;

36
src/vmm/vcpu.rs Normal file
View File

@@ -0,0 +1,36 @@
use x86::{msr::rdmsr, vmx::VmFail};
use crate::memory::BootInfoFrameAllocator;
use super::{vmcs::Vmcs, vmxon::Vmxon};
pub struct VCpu {
pub vmxon: Vmxon,
pub vmcs: Vmcs,
pub phys_mem_offset: u64,
}
impl VCpu {
pub fn new(phys_mem_offset: u64, frame_allocator: &mut BootInfoFrameAllocator) -> Self {
let mut vmxon = Vmxon::new(frame_allocator);
vmxon.init(phys_mem_offset);
let vmcs = Vmcs::new(frame_allocator);
VCpu {
vmxon,
vmcs,
phys_mem_offset,
}
}
pub fn activate(&mut self) {
self.vmxon.activate_vmxon().unwrap();
let revision_id = unsafe { rdmsr(x86::msr::IA32_VMX_BASIC) } as u32;
self.vmcs
.write_revision_id(revision_id, self.phys_mem_offset);
}
pub fn reset_vmcs(&mut self) -> Result<(), VmFail> {
self.vmcs.reset()
}
}

31
src/vmm/vmcs.rs Normal file
View File

@@ -0,0 +1,31 @@
use x86::{bits64::vmx, vmx::VmFail};
use x86_64::structures::paging::{FrameAllocator, PhysFrame};
use crate::memory::BootInfoFrameAllocator;
pub struct Vmcs {
pub frame: PhysFrame,
}
impl Vmcs {
pub fn new(frame_allocator: &mut BootInfoFrameAllocator) -> Self {
let frame = frame_allocator.allocate_frame().unwrap();
Self { frame }
}
pub fn reset(&mut self) -> Result<(), VmFail> {
let vmcs_addr = self.frame.start_address().as_u64();
unsafe {
vmx::vmclear(vmcs_addr)?;
vmx::vmptrld(vmcs_addr)
}
}
pub fn write_revision_id(&mut self, revision_id: u32, phys_mem_offset: u64) {
let vmcs_addr = self.frame.start_address().as_u64() + phys_mem_offset;
unsafe {
core::ptr::write_volatile(vmcs_addr as *mut u32, revision_id);
}
}
}