diff --git a/src/vmm/cpuid.rs b/src/vmm/cpuid.rs index 1d1584c..9226abd 100644 --- a/src/vmm/cpuid.rs +++ b/src/vmm/cpuid.rs @@ -6,7 +6,7 @@ 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"miHypervisor"; + let vendor: &[u8; 12] = b"AuthenticAMD"; let brand_string: &[u8; 48] = b"mii Hypervisor CPU on Intel VT-x \0"; let vendor = unsafe { core::mem::transmute::<&[u8; 12], &[u32; 3]>(vendor) }; diff --git a/src/vmm/msr.rs b/src/vmm/msr.rs index 0216139..79be6db 100644 --- a/src/vmm/msr.rs +++ b/src/vmm/msr.rs @@ -133,6 +133,13 @@ impl ShadowMsr { } x86::msr::IA32_KERNEL_GSBASE => Self::shadow_read(vcpu, msr_kind), 0x1b => Self::shadow_read(vcpu, msr_kind), + 0x8b => Self::set_ret_val(vcpu, 0x8701021), + 0xc0011029 => Self::set_ret_val(vcpu, 0x3000310e08202), + 0xc0010000 => Self::set_ret_val(vcpu, 0x130076), + 0xc0010001 => Self::set_ret_val(vcpu, 0), + 0xc0010002 => Self::set_ret_val(vcpu, 0), + 0xc0010003 => Self::set_ret_val(vcpu, 0), + 0xc0010007 => Self::set_ret_val(vcpu, 0), _ => { panic!("Unhandled RDMSR: {:#x}", msr_kind); } @@ -172,6 +179,7 @@ impl ShadowMsr { x86::msr::IA32_FS_BASE => unsafe { vmwrite(vmcs::guest::FS_BASE, value).unwrap() }, x86::msr::IA32_GS_BASE => unsafe { vmwrite(vmcs::guest::GS_BASE, value).unwrap() }, 0x1b => Self::shadow_write(vcpu, msr_kind), + 0xc0010007 => Self::shadow_write(vcpu, msr_kind), _ => { panic!("Unhandled WRMSR: {:#x}", msr_kind); diff --git a/src/vmm/vcpu.rs b/src/vmm/vcpu.rs index aae4626..3172a0a 100644 --- a/src/vmm/vcpu.rs +++ b/src/vmm/vcpu.rs @@ -50,7 +50,8 @@ use super::{ const SIZE_2MIB: u64 = 2 * 1024 * 1024; -static EPT_FRAME_ALLOCATOR: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); +static EPT_FRAME_ALLOCATOR: AtomicPtr = + AtomicPtr::new(core::ptr::null_mut()); #[repr(C)] pub struct VCpu { @@ -193,7 +194,7 @@ impl VCpu { mapper: &OffsetPageTable<'static>, ) { EPT_FRAME_ALLOCATOR.store(frame_allocator as *mut _, Ordering::Release); - + self.vmxon.activate_vmxon().unwrap(); let revision_id = unsafe { rdmsr(x86::msr::IA32_VMX_BASIC) } as u32; @@ -241,7 +242,7 @@ impl VCpu { let cmdline_start = linux::LAYOUT_CMDLINE as u64; let cmdline_end = cmdline_start + cmdline_max_size as u64; - + let cmdline_bytes = b"console=ttyS0 earlyprintk=serial nokaslr\0"; self.load_image(cmdline_bytes, cmdline_start as usize); @@ -272,21 +273,23 @@ impl VCpu { pub fn load_image(&mut self, image: &[u8], addr: usize) { info!("Loading image at {:#x}, size: {} bytes", addr, image.len()); - + let start_page = addr & !0xFFF; let end_page = ((addr + image.len() - 1) & !0xFFF) + 0x1000; - + unsafe { let frame_allocator_ptr = EPT_FRAME_ALLOCATOR.load(Ordering::Acquire); if !frame_allocator_ptr.is_null() { let frame_allocator = &mut *(frame_allocator_ptr as *mut BootInfoFrameAllocator); - + let mut current_page = start_page; while current_page < end_page { if self.ept.get_phys_addr(current_page as u64).is_none() { if let Some(frame) = frame_allocator.allocate_frame() { let hpa = frame.start_address().as_u64(); - self.ept.map_4k(current_page as u64, hpa, frame_allocator).unwrap(); + self.ept + .map_4k(current_page as u64, hpa, frame_allocator) + .unwrap(); } else { panic!("Failed to allocate frame for image at {:#x}", current_page); } @@ -295,7 +298,7 @@ impl VCpu { } } } - + for (i, &byte) in image.iter().enumerate() { let gpa = addr + i; self.ept.set(gpa as u64, byte).unwrap(); @@ -305,8 +308,10 @@ impl VCpu { pub fn setup_guest_memory(&mut self, frame_allocator: &mut BootInfoFrameAllocator) -> u64 { let guest_memory_size = 2 * 1024 * 1024 * 1024; - info!("Setting up guest memory with on-demand allocation (reported size: {}MB)", - guest_memory_size / (1024 * 1024)); + info!( + "Setting up guest memory with on-demand allocation (reported size: {}MB)", + guest_memory_size / (1024 * 1024) + ); self.load_kernel(linux::BZIMAGE, guest_memory_size); @@ -354,6 +359,7 @@ impl VCpu { .set(x86::msr::MSR_C5_PMON_BOX_CTRL, 0) .unwrap(); self.guest_msr.set(0x1b, 0).unwrap(); + self.guest_msr.set(0xc0010007, 0).unwrap(); vmwrite( vmcs::control::VMEXIT_MSR_LOAD_ADDR_FULL, @@ -981,7 +987,10 @@ impl VCpu { fn handle_ept_violation(&mut self, gpa: u64) { if gpa >= 2 * 1024 * 1024 * 1024 { - panic!("EPT Violation: Guest tried to access memory beyond 2GB at {:#x}", gpa); + panic!( + "EPT Violation: Guest tried to access memory beyond 2GB at {:#x}", + gpa + ); } unsafe { @@ -989,19 +998,22 @@ impl VCpu { if frame_allocator_ptr.is_null() { panic!("EPT Violation: Frame allocator not initialized!"); } - + let frame_allocator = &mut *(frame_allocator_ptr as *mut BootInfoFrameAllocator); - + match frame_allocator.allocate_frame() { Some(frame) => { let hpa = frame.start_address().as_u64(); - + if let Err(e) = self.ept.map_4k(gpa, hpa, frame_allocator) { panic!("Failed to map page at GPA {:#x}: {}", gpa, e); } } None => { - panic!("EPT Violation: Out of memory! Cannot allocate frame for GPA {:#x}", gpa); + panic!( + "EPT Violation: Out of memory! Cannot allocate frame for GPA {:#x}", + gpa + ); } } } @@ -1153,29 +1165,51 @@ impl VCpu { 0x01 => match instruction_bytes[2] { 0xCA => { unsafe { - let rflags = vmread(vmcs::guest::RFLAGS).unwrap(); - vmwrite(vmcs::guest::RFLAGS, rflags & !(1 << 18)).unwrap(); + let rflags = + vmread(vmcs::guest::RFLAGS).unwrap(); + vmwrite( + vmcs::guest::RFLAGS, + rflags & !(1 << 18), + ) + .unwrap(); } self.step_next_inst().unwrap(); } 0xCB => { unsafe { - let rflags = vmread(vmcs::guest::RFLAGS).unwrap(); - vmwrite(vmcs::guest::RFLAGS, rflags | (1 << 18)).unwrap(); + let rflags = + vmread(vmcs::guest::RFLAGS).unwrap(); + vmwrite( + vmcs::guest::RFLAGS, + rflags | (1 << 18), + ) + .unwrap(); } self.step_next_inst().unwrap(); } _ => { + info!( + "VMExit: Exception {} at RIP {:#x} with instruction bytes: {:?}", + vector, rip, &instruction_bytes + ); self.inject_exception(vector, error_code).unwrap(); } }, _ => { + info!( + "VMExit: Exception {} at RIP {:#x} with instruction bytes: {:?}", + vector, rip, &instruction_bytes + ); self.inject_exception(vector, error_code).unwrap(); } } } } _ => { + info!( + "VMExit: Exception {} at RIP {:#x} with instruction bytes: {:?}", + vector, rip, &instruction_bytes + ); self.inject_exception(vector, error_code).unwrap(); } } @@ -1215,7 +1249,7 @@ impl VCpu { let translation_valid = (exit_qualification & 0x100) != 0; let page_addr = guest_address & !0xFFF; - + self.handle_ept_violation(page_addr); } _ => {