This commit is contained in:
Masato Imai
2025-05-17 03:31:47 +00:00
parent 71cfacfd1d
commit 37a367a736
9 changed files with 338 additions and 60 deletions

22
Cargo.lock generated
View File

@ -25,18 +25,18 @@ checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
[[package]] [[package]]
name = "bitfield" name = "bitfield"
version = "0.19.0" version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "786e53b0c071573a28956cec19a92653e42de34c683e2f6e86c197a349fba318" checksum = "db1bcd90f88eabbf0cadbfb87a45bceeaebcd3b4bc9e43da379cd2ef0162590d"
dependencies = [ dependencies = [
"bitfield-macros", "bitfield-macros",
] ]
[[package]] [[package]]
name = "bitfield-macros" name = "bitfield-macros"
version = "0.19.0" version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07805405d3f1f3a55aab895718b488821d40458f9188059909091ae0935c344a" checksum = "3787a07661997bfc05dd3431e379c0188573f78857080cf682e1393ab8e4d64c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -51,9 +51,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.9.0" version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
[[package]] [[package]]
name = "bootloader" name = "bootloader"
@ -260,7 +260,7 @@ version = "11.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146"
dependencies = [ dependencies = [
"bitflags 2.9.0", "bitflags 2.9.1",
] ]
[[package]] [[package]]
@ -298,9 +298,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.100" version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -376,7 +376,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c101112411baafbb4bf8d33e4c4a80ab5b02d74d2612331c61e8192fc9710491" checksum = "c101112411baafbb4bf8d33e4c4a80ab5b02d74d2612331c61e8192fc9710491"
dependencies = [ dependencies = [
"bit_field", "bit_field",
"bitflags 2.9.0", "bitflags 2.9.1",
"rustversion", "rustversion",
"volatile 0.4.6", "volatile 0.4.6",
] ]
@ -388,7 +388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae" checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae"
dependencies = [ dependencies = [
"bit_field", "bit_field",
"bitflags 2.9.0", "bitflags 2.9.1",
"rustversion", "rustversion",
"volatile 0.4.6", "volatile 0.4.6",
] ]

BIN
bzImage

Binary file not shown.

View File

@ -57,7 +57,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
} }
let mut vcpu = VCpu::new(phys_mem_offset.as_u64(), &mut frame_allocator); let mut vcpu = VCpu::new(phys_mem_offset.as_u64(), &mut frame_allocator);
vcpu.activate(&mut frame_allocator); vcpu.activate(&mut frame_allocator, &mapper);
#[cfg(not(test))] #[cfg(not(test))]
vcpu.vm_loop(); vcpu.vm_loop();

View File

@ -1,17 +1,14 @@
use raw_cpuid::cpuid; use raw_cpuid::cpuid;
use crate::info;
use super::{vcpu::VCpu, vmcs::VmxLeaf}; use super::{vcpu::VCpu, vmcs::VmxLeaf};
pub fn handle_cpuid_exit(vcpu: &mut VCpu) { pub fn handle_cpuid_exit(vcpu: &mut VCpu) {
let regs = &mut vcpu.guest_registers; let regs = &mut vcpu.guest_registers;
let vendor: &[u8; 12] = b"miimiimiimii"; let vendor: &[u8; 12] = b"miHypervisor";
let vendor = unsafe { core::mem::transmute::<&[u8; 12], &[u32; 3]>(vendor) }; let vendor = unsafe { core::mem::transmute::<&[u8; 12], &[u32; 3]>(vendor) };
match VmxLeaf::from(regs.rax) { match VmxLeaf::from(regs.rax) {
VmxLeaf::EXTENDED_FEATURE => match regs.rcx { VmxLeaf::EXTENDED_FEATURE => match regs.rcx {
0 => { 0 => {
info!("CPUID extended feature");
let mut ebx = ExtFeatureEbx0::default(); let mut ebx = ExtFeatureEbx0::default();
ebx.smep = true; ebx.smep = true;
ebx.invpcid = false; ebx.invpcid = false;
@ -32,7 +29,6 @@ pub fn handle_cpuid_exit(vcpu: &mut VCpu) {
} }
}, },
VmxLeaf::EXTENDED_PROCESSOR_SIGNATURE => { VmxLeaf::EXTENDED_PROCESSOR_SIGNATURE => {
info!("CPUID extended processor signature");
let signature = cpuid!(0x80000001, 0); let signature = cpuid!(0x80000001, 0);
regs.rax = 0x00000000; regs.rax = 0x00000000;
regs.rbx = 0x00000000; regs.rbx = 0x00000000;
@ -40,21 +36,18 @@ pub fn handle_cpuid_exit(vcpu: &mut VCpu) {
regs.rdx = signature.edx as u64; regs.rdx = signature.edx as u64;
} }
VmxLeaf::EXTENDED_FUNCTION => { VmxLeaf::EXTENDED_FUNCTION => {
info!("CPUID extended function");
regs.rax = 0x80000000 + 1; regs.rax = 0x80000000 + 1;
regs.rbx = 0x00000000; regs.rbx = 0x00000000;
regs.rcx = 0x00000000; regs.rcx = 0x00000000;
regs.rdx = 0x00000000; regs.rdx = 0x00000000;
} }
VmxLeaf::MAXIMUM_INPUT => { VmxLeaf::MAXIMUM_INPUT => {
info!("CPUID max input");
regs.rax = 0x20; regs.rax = 0x20;
regs.rbx = vendor[0] as u64; regs.rbx = vendor[0] as u64;
regs.rcx = vendor[1] as u64; regs.rcx = vendor[2] as u64;
regs.rdx = vendor[2] as u64; regs.rdx = vendor[1] as u64;
} }
VmxLeaf::VERSION_AND_FEATURE_INFO => { VmxLeaf::VERSION_AND_FEATURE_INFO => {
info!("CPUID version and feature info");
let ecx = FeatureInfoEcx { let ecx = FeatureInfoEcx {
sse3: false, sse3: false,
pclmulqdq: false, pclmulqdq: false,
@ -130,7 +123,6 @@ pub fn handle_cpuid_exit(vcpu: &mut VCpu) {
regs.rdx = edx.to_u32() as u64; regs.rdx = edx.to_u32() as u64;
} }
_ => { _ => {
info!("Unhandled CPUID leaf: {:#x}", regs.rax);
invalid(vcpu); invalid(vcpu);
} }
}; };

160
src/vmm/cr.rs Normal file
View File

@ -0,0 +1,160 @@
use core::convert::TryFrom;
use x86::{
bits64::vmx::{vmread, vmwrite},
msr::rdmsr,
vmx::vmcs,
};
use crate::info;
use super::{
qual::{AccessType, QualCr, Register},
vcpu::VCpu,
};
pub fn handle_cr_access(vcpu: &mut VCpu, qual: &QualCr) {
match AccessType::try_from(qual.access_type().unwrap()).unwrap() {
AccessType::MovTo => match qual.index() {
0 | 4 => {
passthrough_write(vcpu, qual);
update_ia32e(vcpu);
}
_ => panic!("Unsupported CR index: {}", qual.index()),
},
AccessType::MovFrom => passthrough_read(vcpu, qual),
_ => {
panic!("Unsupported CR access type: {:?}", qual.access_type());
}
}
}
fn passthrough_read(vcpu: &mut VCpu, qual: &QualCr) {
let value = match qual.index() {
3 => unsafe { vmread(x86::vmx::vmcs::guest::CR3).unwrap() },
_ => panic!("Unsupported CR index: {}", qual.index()),
};
set_value(vcpu, qual, value);
}
fn passthrough_write(vcpu: &mut VCpu, qual: &QualCr) {
let value = get_value(vcpu, qual);
match qual.index() {
0 => unsafe {
vmwrite(vmcs::guest::CR0, adjust_cr0(value)).unwrap();
vmwrite(vmcs::control::CR0_READ_SHADOW, value).unwrap();
},
4 => unsafe {
vmwrite(vmcs::guest::CR4, adjust_cr4(value)).unwrap();
vmwrite(vmcs::control::CR4_READ_SHADOW, value).unwrap();
},
_ => {
panic!("Unsupported CR index: {}", qual.index());
}
}
}
pub fn update_ia32e(vcpu: &mut VCpu) {
let cr0 = unsafe { vmread(x86::vmx::vmcs::guest::CR0).unwrap() };
let cr4 = unsafe { vmread(x86::vmx::vmcs::guest::CR4).unwrap() };
let ia32e_enabled = (cr0 & 1 << 31) != 0 && (cr4 & 1 << 5) != 0;
vcpu.ia32e_enabled = ia32e_enabled;
let mut entry_ctrl = super::vmcs::EntryControls::read();
entry_ctrl.set_ia32e_mode_guest(ia32e_enabled);
entry_ctrl.write();
let mut efer = unsafe { vmread(x86::vmx::vmcs::guest::IA32_EFER_FULL).unwrap() };
let lma = (vcpu.ia32e_enabled as u64) << 10;
if lma != 0 {
efer |= lma;
} else {
efer &= !lma;
}
let lme = if cr0 & (1 << 31) != 0 {
efer & (1 << 10)
} else {
efer & !(1 << 8)
};
if lme != 0 {
efer |= lme;
} else {
efer &= lme;
}
unsafe { vmwrite(x86::vmx::vmcs::guest::IA32_EFER_FULL, efer).unwrap() };
}
pub fn adjust_cr0(value: u64) -> u64 {
let mut result = value;
let cr0_fixed0 = unsafe { rdmsr(x86::msr::IA32_VMX_CR0_FIXED0) };
let cr0_fixed1 = unsafe { rdmsr(x86::msr::IA32_VMX_CR0_FIXED1) };
result |= cr0_fixed0;
result &= cr0_fixed1;
result
}
pub fn adjust_cr4(value: u64) -> u64 {
let mut result = value;
let cr4_fixed0 = unsafe { rdmsr(x86::msr::IA32_VMX_CR4_FIXED0) };
let cr4_fixed1 = unsafe { rdmsr(x86::msr::IA32_VMX_CR4_FIXED1) };
result |= cr4_fixed0;
result &= cr4_fixed1;
result
}
fn set_value(vcpu: &mut VCpu, qual: &QualCr, value: u64) {
let guest_regs = &mut vcpu.guest_registers;
match qual.register().unwrap() {
Register::Rax => guest_regs.rax = value,
Register::Rcx => guest_regs.rcx = value,
Register::Rdx => guest_regs.rdx = value,
Register::Rbx => guest_regs.rbx = value,
Register::Rbp => guest_regs.rbp = value,
Register::Rsi => guest_regs.rsi = value,
Register::Rdi => guest_regs.rdi = value,
Register::R8 => guest_regs.r8 = value,
Register::R9 => guest_regs.r9 = value,
Register::R10 => guest_regs.r10 = value,
Register::R11 => guest_regs.r11 = value,
Register::R12 => guest_regs.r12 = value,
Register::R13 => guest_regs.r13 = value,
Register::R14 => guest_regs.r14 = value,
Register::R15 => guest_regs.r15 = value,
Register::Rsp => unsafe { vmwrite(x86::vmx::vmcs::guest::RSP, value).unwrap() },
}
}
fn get_value(vcpu: &mut VCpu, qual: &QualCr) -> u64 {
let guest_regs = &mut vcpu.guest_registers;
match qual.register().unwrap() {
Register::Rax => guest_regs.rax,
Register::Rcx => guest_regs.rcx,
Register::Rdx => guest_regs.rdx,
Register::Rbx => guest_regs.rbx,
Register::Rbp => guest_regs.rbp,
Register::Rsi => guest_regs.rsi,
Register::Rdi => guest_regs.rdi,
Register::R8 => guest_regs.r8,
Register::R9 => guest_regs.r9,
Register::R10 => guest_regs.r10,
Register::R11 => guest_regs.r11,
Register::R12 => guest_regs.r12,
Register::R13 => guest_regs.r13,
Register::R14 => guest_regs.r14,
Register::R15 => guest_regs.r15,
Register::Rsp => unsafe { vmread(x86::vmx::vmcs::guest::RSP).unwrap() },
}
}

View File

@ -1,9 +1,11 @@
pub mod asm; pub mod asm;
pub mod cpuid; pub mod cpuid;
pub mod cr;
pub mod ept; pub mod ept;
pub mod error; pub mod error;
pub mod linux; pub mod linux;
pub mod msr; pub mod msr;
pub mod qual;
pub mod register; pub mod register;
pub mod support; pub mod support;
pub mod vcpu; pub mod vcpu;

View File

@ -44,7 +44,7 @@ pub enum MsrError {
impl ShadowMsr { impl ShadowMsr {
pub fn new() -> Self { pub fn new() -> Self {
let ents = vec![SavedMsr::default(); MAX_NUM_ENTS]; let ents = vec![];
ShadowMsr { ents } ShadowMsr { ents }
} }
@ -108,7 +108,7 @@ impl ShadowMsr {
.set(msr_kind, Self::concat(regs.rdx, regs.rax)) .set(msr_kind, Self::concat(regs.rdx, regs.rax))
.unwrap(); .unwrap();
} else { } else {
panic!("MSR not found"); panic!("MSR not found: {:#x}", msr_kind);
} }
} }

127
src/vmm/qual.rs Normal file
View File

@ -0,0 +1,127 @@
use bitfield::bitfield;
use core::convert::TryFrom;
use core::fmt::Debug;
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AccessType {
MovTo = 0,
MovFrom = 1,
Clts = 2,
Lmsw = 3,
}
impl TryFrom<u8> for AccessType {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(AccessType::MovTo),
1 => Ok(AccessType::MovFrom),
2 => Ok(AccessType::Clts),
3 => Ok(AccessType::Lmsw),
_ => Err("Invalid AccessType value"),
}
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LmswOperandType {
Reg = 0,
Mem = 1,
}
impl TryFrom<u8> for LmswOperandType {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(LmswOperandType::Reg),
1 => Ok(LmswOperandType::Mem),
_ => Err("Invalid LmswOperandType value"),
}
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Register {
Rax = 0,
Rcx = 1,
Rdx = 2,
Rbx = 3,
Rsp = 4,
Rbp = 5,
Rsi = 6,
Rdi = 7,
R8 = 8,
R9 = 9,
R10 = 10,
R11 = 11,
R12 = 12,
R13 = 13,
R14 = 14,
R15 = 15,
}
impl TryFrom<u8> for Register {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Register::Rax),
1 => Ok(Register::Rcx),
2 => Ok(Register::Rdx),
3 => Ok(Register::Rbx),
4 => Ok(Register::Rsp),
5 => Ok(Register::Rbp),
6 => Ok(Register::Rsi),
7 => Ok(Register::Rdi),
8 => Ok(Register::R8),
9 => Ok(Register::R9),
10 => Ok(Register::R10),
11 => Ok(Register::R11),
12 => Ok(Register::R12),
13 => Ok(Register::R13),
14 => Ok(Register::R14),
15 => Ok(Register::R15),
_ => Err("Invalid Register value"),
}
}
}
bitfield! {
#[derive(Clone, Copy)]
pub struct QualCr(u64);
impl Debug;
pub u8, index, set_index: 3, 0;
u8, access_type_raw, set_access_type_raw: 5, 4;
u8, lmsw_operand_type_raw, set_lmsw_operand_type_raw: 6, 6;
u8, register_raw, set_register_raw: 11, 8;
u16, lmsw_source, set_lmsw_source: 31, 16;
}
impl QualCr {
pub fn access_type(&self) -> Result<AccessType, &'static str> {
AccessType::try_from(self.access_type_raw())
}
pub fn set_access_type(&mut self, val: AccessType) {
self.set_access_type_raw(val as u8);
}
pub fn lmsw_operand_type(&self) -> Result<LmswOperandType, &'static str> {
LmswOperandType::try_from(self.lmsw_operand_type_raw())
}
pub fn set_lmsw_operand_type(&mut self, val: LmswOperandType) {
self.set_lmsw_operand_type_raw(val as u8);
}
pub fn register(&self) -> Result<Register, &'static str> {
Register::try_from(self.register_raw())
}
pub fn set_register(&mut self, val: Register) {
self.set_register_raw(val as u8);
}
}

View File

@ -1,4 +1,5 @@
use rand::{Rng, SeedableRng}; use core::u64;
use x86::{ use x86::{
bits64::vmx::{vmread, vmwrite}, bits64::vmx::{vmread, vmwrite},
controlregs::{cr0, cr3, cr4, Cr0}, controlregs::{cr0, cr3, cr4, Cr0},
@ -12,7 +13,8 @@ use crate::{
info, info,
memory::BootInfoFrameAllocator, memory::BootInfoFrameAllocator,
vmm::{ vmm::{
cpuid, msr, cpuid, cr, msr,
qual::QualCr,
vmcs::{ vmcs::{
DescriptorType, EntryControls, Granularity, PrimaryExitControls, DescriptorType, EntryControls, Granularity, PrimaryExitControls,
PrimaryProcessorBasedVmExecutionControls, SecondaryProcessorBasedVmExecutionControls, PrimaryProcessorBasedVmExecutionControls, SecondaryProcessorBasedVmExecutionControls,
@ -41,6 +43,7 @@ pub struct VCpu {
pub eptp: EPTP, pub eptp: EPTP,
pub host_msr: ShadowMsr, pub host_msr: ShadowMsr,
pub guest_msr: ShadowMsr, pub guest_msr: ShadowMsr,
pub ia32e_enabled: bool,
} }
const TEMP_STACK_SIZE: usize = 4096; const TEMP_STACK_SIZE: usize = 4096;
@ -64,10 +67,15 @@ impl VCpu {
eptp, eptp,
host_msr: ShadowMsr::new(), host_msr: ShadowMsr::new(),
guest_msr: ShadowMsr::new(), guest_msr: ShadowMsr::new(),
ia32e_enabled: false,
} }
} }
pub fn activate(&mut self, frame_allocator: &mut BootInfoFrameAllocator) { pub fn activate(
&mut self,
frame_allocator: &mut BootInfoFrameAllocator,
mapper: &OffsetPageTable<'static>,
) {
self.vmxon.activate_vmxon().unwrap(); self.vmxon.activate_vmxon().unwrap();
let revision_id = unsafe { rdmsr(x86::msr::IA32_VMX_BASIC) } as u32; let revision_id = unsafe { rdmsr(x86::msr::IA32_VMX_BASIC) } as u32;
@ -80,6 +88,7 @@ impl VCpu {
self.setup_host_state().unwrap(); self.setup_host_state().unwrap();
self.setup_guest_state().unwrap(); self.setup_guest_state().unwrap();
self.setup_guest_memory(frame_allocator); self.setup_guest_memory(frame_allocator);
self.register_msrs(&mapper);
} }
pub fn load_kernel(&mut self, kernel: &[u8]) { pub fn load_kernel(&mut self, kernel: &[u8]) {
@ -144,33 +153,6 @@ impl VCpu {
} }
} }
pub fn test_guest_memory(&mut self) {
for x in 1..=1024 {
let mut gpa = 0;
let start = 100 * 1024 * (x - 1);
let mut random_data = [0u8; 100 * 1024];
let mut rng = rand::rngs::SmallRng::from_seed([0u8; 16]);
for byte in random_data.iter_mut() {
*byte = rng.gen();
}
self.load_image(&random_data, start);
while gpa < 100 * 1024 {
let value = self.ept.get((gpa + start) as u64).unwrap();
if value != random_data[gpa] {
panic!("Guest memory test failed at {:#x}", gpa);
}
gpa += 1;
}
}
let start = 100 * 1024 * 0;
let end = 100 * 1024 * 1024;
self.ept.set_range(start as u64, end as u64, 0).unwrap();
}
pub fn setup_guest_memory(&mut self, frame_allocator: &mut BootInfoFrameAllocator) { pub fn setup_guest_memory(&mut self, frame_allocator: &mut BootInfoFrameAllocator) {
let mut pages = 100; let mut pages = 100;
let mut gpa = 0; let mut gpa = 0;
@ -188,15 +170,13 @@ impl VCpu {
} }
info!("Guest memory setup complete"); info!("Guest memory setup complete");
self.test_guest_memory();
self.load_kernel(linux::BZIMAGE); self.load_kernel(linux::BZIMAGE);
let eptp = EPTP::new(&self.ept.root_table); let eptp = EPTP::new(&self.ept.root_table);
unsafe { vmwrite(vmcs::control::EPTP_FULL, eptp.0).unwrap() }; unsafe { vmwrite(vmcs::control::EPTP_FULL, eptp.0).unwrap() };
} }
pub fn register_msrs(&mut self, mapper: OffsetPageTable<'static>) { pub fn register_msrs(&mut self, mapper: &OffsetPageTable<'static>) {
unsafe { unsafe {
// tsc_aux, star, lstar, cstar, fmask, kernel_gs_base. // tsc_aux, star, lstar, cstar, fmask, kernel_gs_base.
self.host_msr self.host_msr
@ -306,7 +286,7 @@ impl VCpu {
primary_exec_ctrl.0 |= (reserved_bits & 0xFFFFFFFF) as u32; primary_exec_ctrl.0 |= (reserved_bits & 0xFFFFFFFF) as u32;
primary_exec_ctrl.0 &= (reserved_bits >> 32) as u32; primary_exec_ctrl.0 &= (reserved_bits >> 32) as u32;
primary_exec_ctrl.set_hlt(false); primary_exec_ctrl.set_hlt(true);
primary_exec_ctrl.set_activate_secondary_controls(true); primary_exec_ctrl.set_activate_secondary_controls(true);
primary_exec_ctrl.set_use_tpr_shadow(true); primary_exec_ctrl.set_use_tpr_shadow(true);
primary_exec_ctrl.set_use_msr_bitmap(false); primary_exec_ctrl.set_use_msr_bitmap(false);
@ -330,6 +310,11 @@ impl VCpu {
secondary_exec_ctrl.write(); secondary_exec_ctrl.write();
unsafe {
vmwrite(vmcs::control::CR0_GUEST_HOST_MASK, u64::MAX).unwrap();
vmwrite(vmcs::control::CR4_GUEST_HOST_MASK, u64::MAX).unwrap();
}
Ok(()) Ok(())
} }
@ -558,7 +543,11 @@ impl VCpu {
vmwrite(vmcs::guest::RIP, linux::LAYOUT_KERNEL_BASE as u64)?; vmwrite(vmcs::guest::RIP, linux::LAYOUT_KERNEL_BASE as u64)?;
self.guest_registers.rsi = linux::LAYOUT_BOOTPARAM as u64; self.guest_registers.rsi = linux::LAYOUT_BOOTPARAM as u64;
info!("Guest RIP: {:#x}", linux::LAYOUT_KERNEL_BASE as u64);
let cr0 = vmread(vmcs::guest::CR0)?;
let cr4 = vmread(vmcs::guest::CR4)?;
vmwrite(vmcs::control::CR0_READ_SHADOW, cr0)?;
vmwrite(vmcs::control::CR4_READ_SHADOW, cr4)?;
} }
Ok(()) Ok(())
@ -643,6 +632,7 @@ impl VCpu {
info!("HLT instruction executed"); info!("HLT instruction executed");
} }
VmxExitReason::CPUID => { VmxExitReason::CPUID => {
info!("CPUID instruction executed");
cpuid::handle_cpuid_exit(self); cpuid::handle_cpuid_exit(self);
self.step_next_inst().unwrap(); self.step_next_inst().unwrap();
} }
@ -656,6 +646,13 @@ impl VCpu {
msr::ShadowMsr::handle_wrmsr_vmexit(self); msr::ShadowMsr::handle_wrmsr_vmexit(self);
self.step_next_inst().unwrap(); self.step_next_inst().unwrap();
} }
VmxExitReason::CONTROL_REGISTER_ACCESSES => {
info!("Control register access");
let qual = unsafe { vmread(vmcs::ro::EXIT_QUALIFICATION).unwrap() };
let qual = QualCr(qual);
cr::handle_cr_access(self, &qual);
self.step_next_inst().unwrap();
}
_ => { _ => {
panic!("VMExit reason: {:?}", info.get_reason()); panic!("VMExit reason: {:?}", info.get_reason());
} }