mirror of
https://github.com/mii443/nel_os.git
synced 2025-12-03 03:08:25 +00:00
add VMCS guest state
This commit is contained in:
123
src/vmm/vcpu.rs
123
src/vmm/vcpu.rs
@@ -9,7 +9,11 @@ use x86::{
|
|||||||
|
|
||||||
use core::arch::naked_asm;
|
use core::arch::naked_asm;
|
||||||
|
|
||||||
use crate::{info, memory::BootInfoFrameAllocator};
|
use crate::{
|
||||||
|
info,
|
||||||
|
memory::BootInfoFrameAllocator,
|
||||||
|
vmm::vmcs::{DescriptorType, Granularity, SegmentRights},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
vmcs::{PinBasedVmExecutionControls, Vmcs},
|
vmcs::{PinBasedVmExecutionControls, Vmcs},
|
||||||
@@ -43,9 +47,11 @@ impl VCpu {
|
|||||||
self.reset_vmcs().unwrap();
|
self.reset_vmcs().unwrap();
|
||||||
self.setup_exec_ctrls().unwrap();
|
self.setup_exec_ctrls().unwrap();
|
||||||
self.setup_host_state().unwrap();
|
self.setup_host_state().unwrap();
|
||||||
|
self.setup_guest_state().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_exec_ctrls(&mut self) -> Result<(), VmFail> {
|
pub fn setup_exec_ctrls(&mut self) -> Result<(), VmFail> {
|
||||||
|
info!("Setting up execution controls");
|
||||||
let basic_msr = unsafe { rdmsr(x86::msr::IA32_VMX_BASIC) };
|
let basic_msr = unsafe { rdmsr(x86::msr::IA32_VMX_BASIC) };
|
||||||
let mut pin_exec_ctrl = PinBasedVmExecutionControls::read();
|
let mut pin_exec_ctrl = PinBasedVmExecutionControls::read();
|
||||||
|
|
||||||
@@ -77,6 +83,7 @@ impl VCpu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_host_state(&mut self) -> Result<(), VmFail> {
|
pub fn setup_host_state(&mut self) -> Result<(), VmFail> {
|
||||||
|
info!("Setting up host state");
|
||||||
unsafe {
|
unsafe {
|
||||||
vmwrite(vmcs::host::CR0, cr0().bits() as u64)?;
|
vmwrite(vmcs::host::CR0, cr0().bits() as u64)?;
|
||||||
vmwrite(vmcs::host::CR3, cr3())?;
|
vmwrite(vmcs::host::CR3, cr3())?;
|
||||||
@@ -126,10 +133,124 @@ impl VCpu {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn setup_guest_state(&mut self) -> Result<(), VmFail> {
|
||||||
|
info!("Setting up guest state");
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
vmwrite(vmcs::guest::CR0, cr0().bits() as u64)?;
|
||||||
|
vmwrite(vmcs::guest::CR3, cr3())?;
|
||||||
|
vmwrite(vmcs::guest::CR4, cr4().bits() as u64)?;
|
||||||
|
|
||||||
|
vmwrite(vmcs::guest::CS_BASE, 0)?;
|
||||||
|
vmwrite(vmcs::guest::SS_BASE, 0)?;
|
||||||
|
vmwrite(vmcs::guest::DS_BASE, 0)?;
|
||||||
|
vmwrite(vmcs::guest::ES_BASE, 0)?;
|
||||||
|
vmwrite(vmcs::guest::FS_BASE, 0)?;
|
||||||
|
vmwrite(vmcs::guest::GS_BASE, 0)?;
|
||||||
|
vmwrite(vmcs::guest::TR_BASE, 0)?;
|
||||||
|
vmwrite(vmcs::guest::GDTR_BASE, 0)?;
|
||||||
|
vmwrite(vmcs::guest::IDTR_BASE, 0)?;
|
||||||
|
vmwrite(vmcs::guest::LDTR_BASE, 0xDEAD00)?;
|
||||||
|
|
||||||
|
vmwrite(vmcs::guest::CS_LIMIT, u32::MAX as u64)?;
|
||||||
|
vmwrite(vmcs::guest::SS_LIMIT, u32::MAX as u64)?;
|
||||||
|
vmwrite(vmcs::guest::DS_LIMIT, u32::MAX as u64)?;
|
||||||
|
vmwrite(vmcs::guest::ES_LIMIT, u32::MAX as u64)?;
|
||||||
|
vmwrite(vmcs::guest::FS_LIMIT, u32::MAX as u64)?;
|
||||||
|
vmwrite(vmcs::guest::GS_LIMIT, u32::MAX as u64)?;
|
||||||
|
vmwrite(vmcs::guest::TR_LIMIT, u32::MAX as u64)?;
|
||||||
|
vmwrite(vmcs::guest::GDTR_LIMIT, u32::MAX as u64)?;
|
||||||
|
vmwrite(vmcs::guest::IDTR_LIMIT, u32::MAX as u64)?;
|
||||||
|
vmwrite(vmcs::guest::LDTR_LIMIT, u32::MAX as u64)?;
|
||||||
|
|
||||||
|
vmwrite(
|
||||||
|
vmcs::guest::CS_SELECTOR,
|
||||||
|
x86::segmentation::cs().bits() as u64,
|
||||||
|
)?;
|
||||||
|
vmwrite(vmcs::guest::SS_SELECTOR, 0)?;
|
||||||
|
vmwrite(vmcs::guest::DS_SELECTOR, 0)?;
|
||||||
|
vmwrite(vmcs::guest::ES_SELECTOR, 0)?;
|
||||||
|
vmwrite(vmcs::guest::FS_SELECTOR, 0)?;
|
||||||
|
vmwrite(vmcs::guest::GS_SELECTOR, 0)?;
|
||||||
|
vmwrite(vmcs::guest::TR_SELECTOR, 0)?;
|
||||||
|
vmwrite(vmcs::guest::LDTR_SELECTOR, 0)?;
|
||||||
|
|
||||||
|
let cs_rights = {
|
||||||
|
let mut rights = SegmentRights(0);
|
||||||
|
rights.set_rw(true);
|
||||||
|
rights.set_dc(false);
|
||||||
|
rights.set_executable(true);
|
||||||
|
rights.set_desc_type_raw(DescriptorType::Code as u8);
|
||||||
|
rights.set_dpl(0);
|
||||||
|
rights.set_granularity_raw(Granularity::KByte as u8);
|
||||||
|
rights.set_long(true);
|
||||||
|
rights.set_db(false);
|
||||||
|
rights
|
||||||
|
};
|
||||||
|
vmwrite(vmcs::guest::CS_ACCESS_RIGHTS, cs_rights.0 as u64)?;
|
||||||
|
|
||||||
|
let ds_rights = {
|
||||||
|
let mut rights = SegmentRights(0);
|
||||||
|
rights.set_rw(true);
|
||||||
|
rights.set_dc(false);
|
||||||
|
rights.set_executable(false);
|
||||||
|
rights.set_desc_type_raw(DescriptorType::Code as u8);
|
||||||
|
rights.set_dpl(0);
|
||||||
|
rights.set_granularity_raw(Granularity::KByte as u8);
|
||||||
|
rights.set_long(false);
|
||||||
|
rights.set_db(true);
|
||||||
|
rights
|
||||||
|
};
|
||||||
|
vmwrite(vmcs::guest::DS_ACCESS_RIGHTS, ds_rights.0 as u64)?;
|
||||||
|
|
||||||
|
let tr_rights = {
|
||||||
|
let mut rights = SegmentRights(0);
|
||||||
|
rights.set_rw(true);
|
||||||
|
rights.set_dc(false);
|
||||||
|
rights.set_executable(true);
|
||||||
|
rights.set_desc_type_raw(DescriptorType::System as u8);
|
||||||
|
rights.set_dpl(0);
|
||||||
|
rights.set_granularity_raw(Granularity::Byte as u8);
|
||||||
|
rights.set_long(false);
|
||||||
|
rights.set_db(false);
|
||||||
|
rights
|
||||||
|
};
|
||||||
|
vmwrite(vmcs::guest::TR_ACCESS_RIGHTS, tr_rights.0 as u64)?;
|
||||||
|
|
||||||
|
let ldtr_rights = {
|
||||||
|
let mut rights = SegmentRights(0);
|
||||||
|
rights.set_accessed(false);
|
||||||
|
rights.set_rw(true);
|
||||||
|
rights.set_dc(false);
|
||||||
|
rights.set_executable(false);
|
||||||
|
rights.set_desc_type_raw(DescriptorType::System as u8);
|
||||||
|
rights.set_dpl(0);
|
||||||
|
rights.set_granularity_raw(Granularity::Byte as u8);
|
||||||
|
rights.set_long(false);
|
||||||
|
rights.set_db(false);
|
||||||
|
rights
|
||||||
|
};
|
||||||
|
vmwrite(vmcs::guest::LDTR_ACCESS_RIGHTS, ldtr_rights.0 as u64)?;
|
||||||
|
|
||||||
|
vmwrite(vmcs::guest::RIP, Self::guest as u64)?;
|
||||||
|
vmwrite(vmcs::guest::IA32_EFER_FULL, rdmsr(IA32_EFER))?;
|
||||||
|
vmwrite(vmcs::guest::RFLAGS, 0x2)?;
|
||||||
|
vmwrite(vmcs::guest::LINK_PTR_FULL, u64::MAX)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn reset_vmcs(&mut self) -> Result<(), VmFail> {
|
pub fn reset_vmcs(&mut self) -> Result<(), VmFail> {
|
||||||
|
info!("Resetting VMCS");
|
||||||
self.vmcs.reset()
|
self.vmcs.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
unsafe extern "C" fn guest() -> ! {
|
||||||
|
naked_asm!("hlt");
|
||||||
|
}
|
||||||
|
|
||||||
fn vmexit_handler(&mut self) -> ! {
|
fn vmexit_handler(&mut self) -> ! {
|
||||||
info!("VMExit occurred");
|
info!("VMExit occurred");
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
use bitfield::BitMut;
|
use bitfield::{bitfield, BitMut};
|
||||||
use x86::{bits64::vmx, vmx::VmFail};
|
use x86::{bits64::vmx, vmx::VmFail};
|
||||||
use x86_64::structures::paging::{FrameAllocator, PhysFrame};
|
use x86_64::structures::paging::{FrameAllocator, PhysFrame};
|
||||||
|
|
||||||
@@ -171,38 +171,6 @@ 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);
|
pub struct PrimaryProcessorBasedVmExecutionControls(pub u32);
|
||||||
|
|
||||||
impl PrimaryProcessorBasedVmExecutionControls {
|
impl PrimaryProcessorBasedVmExecutionControls {
|
||||||
@@ -222,6 +190,34 @@ impl PrimaryProcessorBasedVmExecutionControls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum DescriptorType {
|
||||||
|
System = 0,
|
||||||
|
Code = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Granularity {
|
||||||
|
Byte = 0,
|
||||||
|
KByte = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
bitfield! {
|
||||||
|
pub struct SegmentRights(u32);
|
||||||
|
impl Debug;
|
||||||
|
|
||||||
|
pub accessed, set_accessed: 0;
|
||||||
|
pub rw, set_rw: 1;
|
||||||
|
pub dc, set_dc: 2;
|
||||||
|
pub executable, set_executable: 3;
|
||||||
|
pub u8, desc_type_raw, set_desc_type_raw: 4, 4;
|
||||||
|
pub u8, dpl, set_dpl: 6, 5;
|
||||||
|
pub present, set_present: 7;
|
||||||
|
pub avl, set_avl: 12;
|
||||||
|
pub long, set_long: 13;
|
||||||
|
pub u1, db, set_db: 14;
|
||||||
|
pub u8, granularity_raw, set_granularity_raw: 15, 15;
|
||||||
|
pub unusable, set_unusable: 16;
|
||||||
|
}
|
||||||
|
|
||||||
pub enum VmcsControl32 {
|
pub enum VmcsControl32 {
|
||||||
PIN_BASED_VM_EXECUTION_CONTROLS = 0x00004000,
|
PIN_BASED_VM_EXECUTION_CONTROLS = 0x00004000,
|
||||||
PRIMARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS = 0x00004002,
|
PRIMARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS = 0x00004002,
|
||||||
|
|||||||
Reference in New Issue
Block a user