mirror of
https://github.com/mii443/nel_os.git
synced 2025-08-22 16:15:38 +00:00
add CR
This commit is contained in:
22
Cargo.lock
generated
22
Cargo.lock
generated
@ -25,18 +25,18 @@ checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
|
||||
|
||||
[[package]]
|
||||
name = "bitfield"
|
||||
version = "0.19.0"
|
||||
version = "0.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "786e53b0c071573a28956cec19a92653e42de34c683e2f6e86c197a349fba318"
|
||||
checksum = "db1bcd90f88eabbf0cadbfb87a45bceeaebcd3b4bc9e43da379cd2ef0162590d"
|
||||
dependencies = [
|
||||
"bitfield-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitfield-macros"
|
||||
version = "0.19.0"
|
||||
version = "0.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07805405d3f1f3a55aab895718b488821d40458f9188059909091ae0935c344a"
|
||||
checksum = "3787a07661997bfc05dd3431e379c0188573f78857080cf682e1393ab8e4d64c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -51,9 +51,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.0"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
|
||||
[[package]]
|
||||
name = "bootloader"
|
||||
@ -260,7 +260,7 @@ version = "11.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -298,9 +298,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.100"
|
||||
version = "2.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
|
||||
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -376,7 +376,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c101112411baafbb4bf8d33e4c4a80ab5b02d74d2612331c61e8192fc9710491"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"rustversion",
|
||||
"volatile 0.4.6",
|
||||
]
|
||||
@ -388,7 +388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"rustversion",
|
||||
"volatile 0.4.6",
|
||||
]
|
||||
|
@ -57,7 +57,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
|
||||
}
|
||||
|
||||
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))]
|
||||
vcpu.vm_loop();
|
||||
|
@ -1,17 +1,14 @@
|
||||
use raw_cpuid::cpuid;
|
||||
|
||||
use crate::info;
|
||||
|
||||
use super::{vcpu::VCpu, vmcs::VmxLeaf};
|
||||
|
||||
pub fn handle_cpuid_exit(vcpu: &mut VCpu) {
|
||||
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) };
|
||||
match VmxLeaf::from(regs.rax) {
|
||||
VmxLeaf::EXTENDED_FEATURE => match regs.rcx {
|
||||
0 => {
|
||||
info!("CPUID extended feature");
|
||||
let mut ebx = ExtFeatureEbx0::default();
|
||||
ebx.smep = true;
|
||||
ebx.invpcid = false;
|
||||
@ -32,7 +29,6 @@ pub fn handle_cpuid_exit(vcpu: &mut VCpu) {
|
||||
}
|
||||
},
|
||||
VmxLeaf::EXTENDED_PROCESSOR_SIGNATURE => {
|
||||
info!("CPUID extended processor signature");
|
||||
let signature = cpuid!(0x80000001, 0);
|
||||
regs.rax = 0x00000000;
|
||||
regs.rbx = 0x00000000;
|
||||
@ -40,21 +36,18 @@ pub fn handle_cpuid_exit(vcpu: &mut VCpu) {
|
||||
regs.rdx = signature.edx as u64;
|
||||
}
|
||||
VmxLeaf::EXTENDED_FUNCTION => {
|
||||
info!("CPUID extended function");
|
||||
regs.rax = 0x80000000 + 1;
|
||||
regs.rbx = 0x00000000;
|
||||
regs.rcx = 0x00000000;
|
||||
regs.rdx = 0x00000000;
|
||||
}
|
||||
VmxLeaf::MAXIMUM_INPUT => {
|
||||
info!("CPUID max input");
|
||||
regs.rax = 0x20;
|
||||
regs.rbx = vendor[0] as u64;
|
||||
regs.rcx = vendor[1] as u64;
|
||||
regs.rdx = vendor[2] as u64;
|
||||
regs.rcx = vendor[2] as u64;
|
||||
regs.rdx = vendor[1] as u64;
|
||||
}
|
||||
VmxLeaf::VERSION_AND_FEATURE_INFO => {
|
||||
info!("CPUID version and feature info");
|
||||
let ecx = FeatureInfoEcx {
|
||||
sse3: false,
|
||||
pclmulqdq: false,
|
||||
@ -130,7 +123,6 @@ pub fn handle_cpuid_exit(vcpu: &mut VCpu) {
|
||||
regs.rdx = edx.to_u32() as u64;
|
||||
}
|
||||
_ => {
|
||||
info!("Unhandled CPUID leaf: {:#x}", regs.rax);
|
||||
invalid(vcpu);
|
||||
}
|
||||
};
|
||||
|
160
src/vmm/cr.rs
Normal file
160
src/vmm/cr.rs
Normal 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() },
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
pub mod asm;
|
||||
pub mod cpuid;
|
||||
pub mod cr;
|
||||
pub mod ept;
|
||||
pub mod error;
|
||||
pub mod linux;
|
||||
pub mod msr;
|
||||
pub mod qual;
|
||||
pub mod register;
|
||||
pub mod support;
|
||||
pub mod vcpu;
|
||||
|
@ -44,7 +44,7 @@ pub enum MsrError {
|
||||
|
||||
impl ShadowMsr {
|
||||
pub fn new() -> Self {
|
||||
let ents = vec![SavedMsr::default(); MAX_NUM_ENTS];
|
||||
let ents = vec![];
|
||||
|
||||
ShadowMsr { ents }
|
||||
}
|
||||
@ -108,7 +108,7 @@ impl ShadowMsr {
|
||||
.set(msr_kind, Self::concat(regs.rdx, regs.rax))
|
||||
.unwrap();
|
||||
} else {
|
||||
panic!("MSR not found");
|
||||
panic!("MSR not found: {:#x}", msr_kind);
|
||||
}
|
||||
}
|
||||
|
||||
|
127
src/vmm/qual.rs
Normal file
127
src/vmm/qual.rs
Normal 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);
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
use rand::{Rng, SeedableRng};
|
||||
use core::u64;
|
||||
|
||||
use x86::{
|
||||
bits64::vmx::{vmread, vmwrite},
|
||||
controlregs::{cr0, cr3, cr4, Cr0},
|
||||
@ -12,7 +13,8 @@ use crate::{
|
||||
info,
|
||||
memory::BootInfoFrameAllocator,
|
||||
vmm::{
|
||||
cpuid, msr,
|
||||
cpuid, cr, msr,
|
||||
qual::QualCr,
|
||||
vmcs::{
|
||||
DescriptorType, EntryControls, Granularity, PrimaryExitControls,
|
||||
PrimaryProcessorBasedVmExecutionControls, SecondaryProcessorBasedVmExecutionControls,
|
||||
@ -41,6 +43,7 @@ pub struct VCpu {
|
||||
pub eptp: EPTP,
|
||||
pub host_msr: ShadowMsr,
|
||||
pub guest_msr: ShadowMsr,
|
||||
pub ia32e_enabled: bool,
|
||||
}
|
||||
|
||||
const TEMP_STACK_SIZE: usize = 4096;
|
||||
@ -64,10 +67,15 @@ impl VCpu {
|
||||
eptp,
|
||||
host_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();
|
||||
|
||||
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_guest_state().unwrap();
|
||||
self.setup_guest_memory(frame_allocator);
|
||||
self.register_msrs(&mapper);
|
||||
}
|
||||
|
||||
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) {
|
||||
let mut pages = 100;
|
||||
let mut gpa = 0;
|
||||
@ -188,15 +170,13 @@ impl VCpu {
|
||||
}
|
||||
info!("Guest memory setup complete");
|
||||
|
||||
self.test_guest_memory();
|
||||
|
||||
self.load_kernel(linux::BZIMAGE);
|
||||
|
||||
let eptp = EPTP::new(&self.ept.root_table);
|
||||
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 {
|
||||
// tsc_aux, star, lstar, cstar, fmask, kernel_gs_base.
|
||||
self.host_msr
|
||||
@ -306,7 +286,7 @@ impl VCpu {
|
||||
|
||||
primary_exec_ctrl.0 |= (reserved_bits & 0xFFFFFFFF) 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_use_tpr_shadow(true);
|
||||
primary_exec_ctrl.set_use_msr_bitmap(false);
|
||||
@ -330,6 +310,11 @@ impl VCpu {
|
||||
|
||||
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(())
|
||||
}
|
||||
|
||||
@ -558,7 +543,11 @@ impl VCpu {
|
||||
|
||||
vmwrite(vmcs::guest::RIP, linux::LAYOUT_KERNEL_BASE 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(())
|
||||
@ -643,6 +632,7 @@ impl VCpu {
|
||||
info!("HLT instruction executed");
|
||||
}
|
||||
VmxExitReason::CPUID => {
|
||||
info!("CPUID instruction executed");
|
||||
cpuid::handle_cpuid_exit(self);
|
||||
self.step_next_inst().unwrap();
|
||||
}
|
||||
@ -656,6 +646,13 @@ impl VCpu {
|
||||
msr::ShadowMsr::handle_wrmsr_vmexit(self);
|
||||
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());
|
||||
}
|
||||
|
Reference in New Issue
Block a user