mirror of
https://github.com/mii443/nel_os.git
synced 2025-08-22 16:15:38 +00:00
MSR
This commit is contained in:
@ -1,4 +1,3 @@
|
||||
use crate::info;
|
||||
use raw_cpuid::cpuid;
|
||||
|
||||
use super::{vcpu::VCpu, vmcs::VmxLeaf};
|
||||
@ -95,6 +94,9 @@ pub fn handle_cpuid_exit(vcpu: &mut VCpu) {
|
||||
regs.rax = 0x00000000;
|
||||
regs.rbx = 0x00000000;
|
||||
regs.rcx = signature.ecx as u64;
|
||||
if vcpu.emulate_amd {
|
||||
regs.rcx |= 1 << 2; // SVM
|
||||
}
|
||||
regs.rdx = signature.edx as u64;
|
||||
}
|
||||
VmxLeaf::EXTENDED_FUNCTION => {
|
||||
|
@ -7,7 +7,6 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
use x86::current::vmx::{vmread, vmwrite};
|
||||
use x86::vmx::vmcs;
|
||||
|
||||
@ -31,7 +30,7 @@ pub struct OpcodeEmulator {
|
||||
pub saved_rsp: Option<u64>,
|
||||
}
|
||||
|
||||
enum VmcallControl {
|
||||
pub enum VmcallControl {
|
||||
ReturnTo32Bit,
|
||||
}
|
||||
|
||||
@ -144,6 +143,10 @@ fn restore_replaced_opcode(vcpu: &mut VCpu) -> bool {
|
||||
}
|
||||
|
||||
fn replace_opcode(vcpu: &mut VCpu, instruction_bytes: [u8; 16], replace: &[u8]) -> bool {
|
||||
let rip = unsafe { vmread(vmcs::guest::RIP).unwrap() };
|
||||
|
||||
let guest_phys_addr = vcpu.translate_guest_address(rip).unwrap();
|
||||
info!("Replacing opcode at address: {:#x}", guest_phys_addr);
|
||||
let replace_len = replace.len();
|
||||
if replace_len > 16 {
|
||||
return false;
|
||||
@ -152,8 +155,6 @@ fn replace_opcode(vcpu: &mut VCpu, instruction_bytes: [u8; 16], replace: &[u8])
|
||||
let mut original_opcode = [0u8; 16];
|
||||
original_opcode[..replace_len].copy_from_slice(&instruction_bytes[..replace_len]);
|
||||
|
||||
let rip = unsafe { vmread(vmcs::guest::RIP).unwrap() };
|
||||
let guest_phys_addr = vcpu.translate_guest_address(rip).unwrap();
|
||||
vcpu.opcode_emulator.original_opcode = Some(original_opcode);
|
||||
vcpu.opcode_emulator.replaced_address = Some(guest_phys_addr);
|
||||
vcpu.opcode_emulator.replaced_size = Some(replace_len as u64);
|
||||
@ -199,14 +200,14 @@ fn return_to_32_bit(vcpu: &mut VCpu) -> bool {
|
||||
let user_ss_selector = vcpu.opcode_emulator.saved_ss_selector.unwrap_or(0x2b);
|
||||
|
||||
// Read current values for logging
|
||||
let current_cs_val = vmread(vmcs::guest::CS_SELECTOR).unwrap();
|
||||
let current_cs_base = vmread(vmcs::guest::CS_BASE).unwrap();
|
||||
let current_cs_limit = vmread(vmcs::guest::CS_LIMIT).unwrap();
|
||||
let current_cs_rights = vmread(vmcs::guest::CS_ACCESS_RIGHTS).unwrap();
|
||||
let current_ss_val = vmread(vmcs::guest::SS_SELECTOR).unwrap();
|
||||
let current_ss_base = vmread(vmcs::guest::SS_BASE).unwrap();
|
||||
let current_ss_limit = vmread(vmcs::guest::SS_LIMIT).unwrap();
|
||||
let current_ss_rights = vmread(vmcs::guest::SS_ACCESS_RIGHTS).unwrap();
|
||||
let _current_cs_val = vmread(vmcs::guest::CS_SELECTOR).unwrap();
|
||||
let _current_cs_base = vmread(vmcs::guest::CS_BASE).unwrap();
|
||||
let _current_cs_limit = vmread(vmcs::guest::CS_LIMIT).unwrap();
|
||||
let _current_cs_rights = vmread(vmcs::guest::CS_ACCESS_RIGHTS).unwrap();
|
||||
let _current_ss_val = vmread(vmcs::guest::SS_SELECTOR).unwrap();
|
||||
let _current_ss_base = vmread(vmcs::guest::SS_BASE).unwrap();
|
||||
let _current_ss_limit = vmread(vmcs::guest::SS_LIMIT).unwrap();
|
||||
let _current_ss_rights = vmread(vmcs::guest::SS_ACCESS_RIGHTS).unwrap();
|
||||
|
||||
// Set CS for 32-bit compatibility mode
|
||||
vmwrite(vmcs::guest::CS_SELECTOR, user_cs_selector as u64).unwrap();
|
||||
@ -255,8 +256,8 @@ fn return_to_32_bit(vcpu: &mut VCpu) -> bool {
|
||||
let gs_selector = vcpu.opcode_emulator.saved_gs_selector.unwrap_or(0);
|
||||
let gs_base = vcpu.opcode_emulator.saved_gs_base.unwrap_or(0);
|
||||
|
||||
let current_gs_val = vmread(vmcs::guest::GS_SELECTOR).unwrap();
|
||||
let current_gs_base = vmread(vmcs::guest::GS_BASE).unwrap();
|
||||
let _current_gs_val = vmread(vmcs::guest::GS_SELECTOR).unwrap();
|
||||
let _current_gs_base = vmread(vmcs::guest::GS_BASE).unwrap();
|
||||
|
||||
vmwrite(vmcs::guest::GS_SELECTOR, gs_selector as u64).unwrap();
|
||||
vmwrite(vmcs::guest::GS_BASE, gs_base).unwrap();
|
||||
@ -337,14 +338,14 @@ fn emulate_syscall(vcpu: &mut VCpu, instruction_bytes: [u8; 16]) -> bool {
|
||||
let current_gs_base = unsafe { vmread(vmcs::guest::GS_BASE).unwrap() };
|
||||
|
||||
// Read all current segment values for logging
|
||||
let current_cs_base = unsafe { vmread(vmcs::guest::CS_BASE).unwrap() };
|
||||
let current_cs_limit = unsafe { vmread(vmcs::guest::CS_LIMIT).unwrap() };
|
||||
let current_cs_rights = unsafe { vmread(vmcs::guest::CS_ACCESS_RIGHTS).unwrap() };
|
||||
let current_ss_base = unsafe { vmread(vmcs::guest::SS_BASE).unwrap() };
|
||||
let current_ss_limit = unsafe { vmread(vmcs::guest::SS_LIMIT).unwrap() };
|
||||
let current_ss_rights = unsafe { vmread(vmcs::guest::SS_ACCESS_RIGHTS).unwrap() };
|
||||
let current_gs_limit = unsafe { vmread(vmcs::guest::GS_LIMIT).unwrap() };
|
||||
let current_gs_rights = unsafe { vmread(vmcs::guest::GS_ACCESS_RIGHTS).unwrap() };
|
||||
let _current_cs_base = unsafe { vmread(vmcs::guest::CS_BASE).unwrap() };
|
||||
let _current_cs_limit = unsafe { vmread(vmcs::guest::CS_LIMIT).unwrap() };
|
||||
let _current_cs_rights = unsafe { vmread(vmcs::guest::CS_ACCESS_RIGHTS).unwrap() };
|
||||
let _current_ss_base = unsafe { vmread(vmcs::guest::SS_BASE).unwrap() };
|
||||
let _current_ss_limit = unsafe { vmread(vmcs::guest::SS_LIMIT).unwrap() };
|
||||
let _current_ss_rights = unsafe { vmread(vmcs::guest::SS_ACCESS_RIGHTS).unwrap() };
|
||||
let _current_gs_limit = unsafe { vmread(vmcs::guest::GS_LIMIT).unwrap() };
|
||||
let _current_gs_rights = unsafe { vmread(vmcs::guest::GS_ACCESS_RIGHTS).unwrap() };
|
||||
|
||||
vcpu.opcode_emulator.saved_cs_selector = Some(current_cs);
|
||||
vcpu.opcode_emulator.saved_ss_selector = Some(current_ss);
|
||||
|
@ -6,7 +6,7 @@ use x86_64::{
|
||||
PhysAddr,
|
||||
};
|
||||
|
||||
use crate::{info, memory};
|
||||
use crate::memory;
|
||||
|
||||
pub struct EPT {
|
||||
pub root_table: PhysFrame,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use bitfield::bitfield;
|
||||
|
||||
use crate::{error, info};
|
||||
use crate::error;
|
||||
|
||||
use super::vcpu::VCpu;
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
use core::arch::asm;
|
||||
use x86_64::PhysAddr;
|
||||
|
||||
#[repr(C, packed)]
|
||||
pub struct InveptDesc {
|
||||
|
@ -125,6 +125,28 @@ impl ShadowMsr {
|
||||
x86::msr::IA32_EFER => Self::set_ret_val(vcpu, unsafe {
|
||||
vmread(vmcs::guest::IA32_EFER_FULL).unwrap()
|
||||
}),
|
||||
x86::msr::IA32_TIME_STAMP_COUNTER => {
|
||||
Self::set_ret_val(vcpu, unsafe { x86::time::rdtsc() })
|
||||
}
|
||||
x86::msr::IA32_FEATURE_CONTROL => {
|
||||
// Lock bit (0) | Enable VMX inside SMX (1) | Enable VMX outside SMX (2)
|
||||
Self::set_ret_val(vcpu, 0x5)
|
||||
}
|
||||
0x48 => Self::set_ret_val(vcpu, 0), // IA32_SPEC_CTRL
|
||||
0x122 => Self::set_ret_val(vcpu, 0), // IA32_TSX_CTRL
|
||||
0x560 => Self::set_ret_val(vcpu, 0), // IA32_RTIT_OUTPUT_BASE
|
||||
0x561 => Self::set_ret_val(vcpu, 0), // IA32_RTIT_OUTPUT_MASK_PTRS
|
||||
0x570 => Self::set_ret_val(vcpu, 0), // IA32_RTIT_CTL
|
||||
0x571 => Self::set_ret_val(vcpu, 0), // IA32_RTIT_STATUS
|
||||
0x572 => Self::set_ret_val(vcpu, 0), // IA32_CR3_MATCH
|
||||
0x580 => Self::set_ret_val(vcpu, 0), // IA32_ADDR0_START
|
||||
0x581 => Self::set_ret_val(vcpu, 0), // IA32_ADDR0_END
|
||||
0x582 => Self::set_ret_val(vcpu, 0), // IA32_ADDR1_START
|
||||
0x583 => Self::set_ret_val(vcpu, 0), // IA32_ADDR1_END
|
||||
0x584 => Self::set_ret_val(vcpu, 0), // IA32_ADDR2_START
|
||||
0x585 => Self::set_ret_val(vcpu, 0), // IA32_ADDR2_END
|
||||
0x586 => Self::set_ret_val(vcpu, 0), // IA32_ADDR3_START
|
||||
0x587 => Self::set_ret_val(vcpu, 0), // IA32_ADDR3_END
|
||||
x86::msr::IA32_FS_BASE => {
|
||||
Self::set_ret_val(vcpu, unsafe { vmread(vmcs::guest::FS_BASE).unwrap() })
|
||||
}
|
||||
@ -132,6 +154,19 @@ impl ShadowMsr {
|
||||
Self::set_ret_val(vcpu, unsafe { vmread(vmcs::guest::GS_BASE).unwrap() })
|
||||
}
|
||||
x86::msr::IA32_KERNEL_GSBASE => Self::shadow_read(vcpu, msr_kind),
|
||||
x86::msr::IA32_STAR => Self::shadow_read(vcpu, msr_kind),
|
||||
x86::msr::IA32_LSTAR => Self::shadow_read(vcpu, msr_kind),
|
||||
x86::msr::IA32_CSTAR => Self::shadow_read(vcpu, msr_kind),
|
||||
x86::msr::IA32_FMASK => Self::shadow_read(vcpu, msr_kind),
|
||||
x86::msr::SYSENTER_CS_MSR => {
|
||||
Self::set_ret_val(vcpu, unsafe { vmread(vmcs::guest::IA32_SYSENTER_CS).unwrap() })
|
||||
}
|
||||
x86::msr::SYSENTER_ESP_MSR => {
|
||||
Self::set_ret_val(vcpu, unsafe { vmread(vmcs::guest::IA32_SYSENTER_ESP).unwrap() })
|
||||
}
|
||||
x86::msr::SYSENTER_EIP_MSR => {
|
||||
Self::set_ret_val(vcpu, unsafe { vmread(vmcs::guest::IA32_SYSENTER_EIP).unwrap() })
|
||||
}
|
||||
0x1b => Self::shadow_read(vcpu, msr_kind),
|
||||
0x8b => Self::set_ret_val(vcpu, 0x8701021),
|
||||
0xc0011029 => Self::set_ret_val(vcpu, 0x3000310e08202),
|
||||
@ -140,6 +175,14 @@ impl ShadowMsr {
|
||||
0xc0010002 => Self::set_ret_val(vcpu, 0),
|
||||
0xc0010003 => Self::set_ret_val(vcpu, 0),
|
||||
0xc0010007 => Self::set_ret_val(vcpu, 0),
|
||||
0xc0010114 => Self::set_ret_val(vcpu, 0),
|
||||
0xc0010117 => Self::set_ret_val(vcpu, 0), // MSR_VM_HSAVE_PA
|
||||
0x277 => Self::set_ret_val(vcpu, 0x0007040600070406),
|
||||
0xc0000103 => Self::shadow_read(vcpu, msr_kind), // TSC_AUX
|
||||
0xd90 => Self::set_ret_val(vcpu, 0), // MSR_C1_PMON_EVNT_SEL0
|
||||
0xe1 => Self::set_ret_val(vcpu, 0), // IA32_UMWAIT_CONTROL
|
||||
0x1c4 => Self::set_ret_val(vcpu, 0), // Unknown MSR
|
||||
0x1c5 => Self::set_ret_val(vcpu, 0), // Unknown MSR
|
||||
_ => {
|
||||
panic!("Unhandled RDMSR: {:#x}", msr_kind);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ use super::{
|
||||
vmxon::Vmxon,
|
||||
};
|
||||
|
||||
const SIZE_2MIB: u64 = 2 * 1024 * 1024;
|
||||
const _SIZE_2MIB: u64 = 2 * 1024 * 1024;
|
||||
const GUEST_MEMORY_SIZE: u64 = 2 * 1024 * 1024 * 1024;
|
||||
|
||||
static EPT_FRAME_ALLOCATOR: AtomicPtr<BootInfoFrameAllocator> =
|
||||
@ -252,7 +252,7 @@ impl VCpu {
|
||||
};
|
||||
|
||||
let cmdline_start = linux::LAYOUT_CMDLINE as u64;
|
||||
let cmdline_end = cmdline_start + cmdline_max_size 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);
|
||||
@ -316,7 +316,7 @@ impl VCpu {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_guest_memory(&mut self, frame_allocator: &mut BootInfoFrameAllocator) -> u64 {
|
||||
pub fn setup_guest_memory(&mut self, _frame_allocator: &mut BootInfoFrameAllocator) -> u64 {
|
||||
info!(
|
||||
"Setting up guest memory with on-demand allocation (reported size: {}MB)",
|
||||
GUEST_MEMORY_SIZE / (1024 * 1024)
|
||||
@ -1062,7 +1062,6 @@ impl VCpu {
|
||||
info!(" Reason: VM-entry failure due to invalid guest state");
|
||||
// Read VM-instruction error for more details
|
||||
let vm_instruction_error = unsafe {
|
||||
use x86::msr::rdmsr;
|
||||
vmread(vmcs::ro::VM_INSTRUCTION_ERROR).unwrap_or(0)
|
||||
};
|
||||
info!(" VM-instruction error: {}", vm_instruction_error);
|
||||
@ -1203,7 +1202,7 @@ impl VCpu {
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
Err(_e) => {
|
||||
// Try reading directly as physical address if translation fails
|
||||
if rip < 0x100000000 {
|
||||
for i in 0..16 {
|
||||
@ -1254,13 +1253,13 @@ impl VCpu {
|
||||
unsafe { vmread(vmcs::ro::GUEST_PHYSICAL_ADDR_FULL).unwrap() };
|
||||
let exit_qualification =
|
||||
unsafe { vmread(vmcs::ro::EXIT_QUALIFICATION).unwrap() };
|
||||
let guest_rip = unsafe { vmread(vmcs::guest::RIP).unwrap() };
|
||||
let _guest_rip = unsafe { vmread(vmcs::guest::RIP).unwrap() };
|
||||
|
||||
let read_access = (exit_qualification & 0x1) != 0;
|
||||
let write_access = (exit_qualification & 0x2) != 0;
|
||||
let execute_access = (exit_qualification & 0x4) != 0;
|
||||
let gpa_valid = (exit_qualification & 0x80) != 0;
|
||||
let translation_valid = (exit_qualification & 0x100) != 0;
|
||||
let _read_access = (exit_qualification & 0x1) != 0;
|
||||
let _write_access = (exit_qualification & 0x2) != 0;
|
||||
let _execute_access = (exit_qualification & 0x4) != 0;
|
||||
let _gpa_valid = (exit_qualification & 0x80) != 0;
|
||||
let _translation_valid = (exit_qualification & 0x100) != 0;
|
||||
|
||||
let page_addr = guest_address & !0xFFF;
|
||||
|
||||
|
Reference in New Issue
Block a user