mirror of
https://github.com/mii443/nel_os.git
synced 2025-12-03 03:08:25 +00:00
add VMCS
This commit is contained in:
55
src/main.rs
55
src/main.rs
@@ -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...");
|
||||
|
||||
|
||||
@@ -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
36
src/vmm/vcpu.rs
Normal 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
31
src/vmm/vmcs.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user