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 raw_cpuid::cpuid;
|
||||||
|
|
||||||
use super::{vcpu::VCpu, vmcs::VmxLeaf};
|
use super::{vcpu::VCpu, vmcs::VmxLeaf};
|
||||||
@ -95,6 +94,9 @@ pub fn handle_cpuid_exit(vcpu: &mut VCpu) {
|
|||||||
regs.rax = 0x00000000;
|
regs.rax = 0x00000000;
|
||||||
regs.rbx = 0x00000000;
|
regs.rbx = 0x00000000;
|
||||||
regs.rcx = signature.ecx as u64;
|
regs.rcx = signature.ecx as u64;
|
||||||
|
if vcpu.emulate_amd {
|
||||||
|
regs.rcx |= 1 << 2; // SVM
|
||||||
|
}
|
||||||
regs.rdx = signature.edx as u64;
|
regs.rdx = signature.edx as u64;
|
||||||
}
|
}
|
||||||
VmxLeaf::EXTENDED_FUNCTION => {
|
VmxLeaf::EXTENDED_FUNCTION => {
|
||||||
|
@ -7,7 +7,6 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
|
||||||
use x86::current::vmx::{vmread, vmwrite};
|
use x86::current::vmx::{vmread, vmwrite};
|
||||||
use x86::vmx::vmcs;
|
use x86::vmx::vmcs;
|
||||||
|
|
||||||
@ -31,7 +30,7 @@ pub struct OpcodeEmulator {
|
|||||||
pub saved_rsp: Option<u64>,
|
pub saved_rsp: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum VmcallControl {
|
pub enum VmcallControl {
|
||||||
ReturnTo32Bit,
|
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 {
|
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();
|
let replace_len = replace.len();
|
||||||
if replace_len > 16 {
|
if replace_len > 16 {
|
||||||
return false;
|
return false;
|
||||||
@ -152,8 +155,6 @@ fn replace_opcode(vcpu: &mut VCpu, instruction_bytes: [u8; 16], replace: &[u8])
|
|||||||
let mut original_opcode = [0u8; 16];
|
let mut original_opcode = [0u8; 16];
|
||||||
original_opcode[..replace_len].copy_from_slice(&instruction_bytes[..replace_len]);
|
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.original_opcode = Some(original_opcode);
|
||||||
vcpu.opcode_emulator.replaced_address = Some(guest_phys_addr);
|
vcpu.opcode_emulator.replaced_address = Some(guest_phys_addr);
|
||||||
vcpu.opcode_emulator.replaced_size = Some(replace_len as u64);
|
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);
|
let user_ss_selector = vcpu.opcode_emulator.saved_ss_selector.unwrap_or(0x2b);
|
||||||
|
|
||||||
// Read current values for logging
|
// Read current values for logging
|
||||||
let current_cs_val = vmread(vmcs::guest::CS_SELECTOR).unwrap();
|
let _current_cs_val = vmread(vmcs::guest::CS_SELECTOR).unwrap();
|
||||||
let current_cs_base = vmread(vmcs::guest::CS_BASE).unwrap();
|
let _current_cs_base = vmread(vmcs::guest::CS_BASE).unwrap();
|
||||||
let current_cs_limit = vmread(vmcs::guest::CS_LIMIT).unwrap();
|
let _current_cs_limit = vmread(vmcs::guest::CS_LIMIT).unwrap();
|
||||||
let current_cs_rights = vmread(vmcs::guest::CS_ACCESS_RIGHTS).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_val = vmread(vmcs::guest::SS_SELECTOR).unwrap();
|
||||||
let current_ss_base = vmread(vmcs::guest::SS_BASE).unwrap();
|
let _current_ss_base = vmread(vmcs::guest::SS_BASE).unwrap();
|
||||||
let current_ss_limit = vmread(vmcs::guest::SS_LIMIT).unwrap();
|
let _current_ss_limit = vmread(vmcs::guest::SS_LIMIT).unwrap();
|
||||||
let current_ss_rights = vmread(vmcs::guest::SS_ACCESS_RIGHTS).unwrap();
|
let _current_ss_rights = vmread(vmcs::guest::SS_ACCESS_RIGHTS).unwrap();
|
||||||
|
|
||||||
// Set CS for 32-bit compatibility mode
|
// Set CS for 32-bit compatibility mode
|
||||||
vmwrite(vmcs::guest::CS_SELECTOR, user_cs_selector as u64).unwrap();
|
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_selector = vcpu.opcode_emulator.saved_gs_selector.unwrap_or(0);
|
||||||
let gs_base = vcpu.opcode_emulator.saved_gs_base.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_val = vmread(vmcs::guest::GS_SELECTOR).unwrap();
|
||||||
let current_gs_base = vmread(vmcs::guest::GS_BASE).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_SELECTOR, gs_selector as u64).unwrap();
|
||||||
vmwrite(vmcs::guest::GS_BASE, gs_base).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() };
|
let current_gs_base = unsafe { vmread(vmcs::guest::GS_BASE).unwrap() };
|
||||||
|
|
||||||
// Read all current segment values for logging
|
// Read all current segment values for logging
|
||||||
let current_cs_base = unsafe { vmread(vmcs::guest::CS_BASE).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_limit = unsafe { vmread(vmcs::guest::CS_LIMIT).unwrap() };
|
||||||
let current_cs_rights = unsafe { vmread(vmcs::guest::CS_ACCESS_RIGHTS).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_base = unsafe { vmread(vmcs::guest::SS_BASE).unwrap() };
|
||||||
let current_ss_limit = unsafe { vmread(vmcs::guest::SS_LIMIT).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_ss_rights = unsafe { vmread(vmcs::guest::SS_ACCESS_RIGHTS).unwrap() };
|
||||||
let current_gs_limit = unsafe { vmread(vmcs::guest::GS_LIMIT).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_gs_rights = unsafe { vmread(vmcs::guest::GS_ACCESS_RIGHTS).unwrap() };
|
||||||
|
|
||||||
vcpu.opcode_emulator.saved_cs_selector = Some(current_cs);
|
vcpu.opcode_emulator.saved_cs_selector = Some(current_cs);
|
||||||
vcpu.opcode_emulator.saved_ss_selector = Some(current_ss);
|
vcpu.opcode_emulator.saved_ss_selector = Some(current_ss);
|
||||||
|
@ -6,7 +6,7 @@ use x86_64::{
|
|||||||
PhysAddr,
|
PhysAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{info, memory};
|
use crate::memory;
|
||||||
|
|
||||||
pub struct EPT {
|
pub struct EPT {
|
||||||
pub root_table: PhysFrame,
|
pub root_table: PhysFrame,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use bitfield::bitfield;
|
use bitfield::bitfield;
|
||||||
|
|
||||||
use crate::{error, info};
|
use crate::error;
|
||||||
|
|
||||||
use super::vcpu::VCpu;
|
use super::vcpu::VCpu;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
use x86_64::PhysAddr;
|
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
pub struct InveptDesc {
|
pub struct InveptDesc {
|
||||||
|
@ -125,6 +125,28 @@ impl ShadowMsr {
|
|||||||
x86::msr::IA32_EFER => Self::set_ret_val(vcpu, unsafe {
|
x86::msr::IA32_EFER => Self::set_ret_val(vcpu, unsafe {
|
||||||
vmread(vmcs::guest::IA32_EFER_FULL).unwrap()
|
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 => {
|
x86::msr::IA32_FS_BASE => {
|
||||||
Self::set_ret_val(vcpu, unsafe { vmread(vmcs::guest::FS_BASE).unwrap() })
|
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() })
|
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_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),
|
0x1b => Self::shadow_read(vcpu, msr_kind),
|
||||||
0x8b => Self::set_ret_val(vcpu, 0x8701021),
|
0x8b => Self::set_ret_val(vcpu, 0x8701021),
|
||||||
0xc0011029 => Self::set_ret_val(vcpu, 0x3000310e08202),
|
0xc0011029 => Self::set_ret_val(vcpu, 0x3000310e08202),
|
||||||
@ -140,6 +175,14 @@ impl ShadowMsr {
|
|||||||
0xc0010002 => Self::set_ret_val(vcpu, 0),
|
0xc0010002 => Self::set_ret_val(vcpu, 0),
|
||||||
0xc0010003 => Self::set_ret_val(vcpu, 0),
|
0xc0010003 => Self::set_ret_val(vcpu, 0),
|
||||||
0xc0010007 => 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);
|
panic!("Unhandled RDMSR: {:#x}", msr_kind);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ use super::{
|
|||||||
vmxon::Vmxon,
|
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;
|
const GUEST_MEMORY_SIZE: u64 = 2 * 1024 * 1024 * 1024;
|
||||||
|
|
||||||
static EPT_FRAME_ALLOCATOR: AtomicPtr<BootInfoFrameAllocator> =
|
static EPT_FRAME_ALLOCATOR: AtomicPtr<BootInfoFrameAllocator> =
|
||||||
@ -252,7 +252,7 @@ impl VCpu {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let cmdline_start = linux::LAYOUT_CMDLINE as u64;
|
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";
|
let cmdline_bytes = b"console=ttyS0 earlyprintk=serial nokaslr\0";
|
||||||
self.load_image(cmdline_bytes, cmdline_start as usize);
|
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!(
|
info!(
|
||||||
"Setting up guest memory with on-demand allocation (reported size: {}MB)",
|
"Setting up guest memory with on-demand allocation (reported size: {}MB)",
|
||||||
GUEST_MEMORY_SIZE / (1024 * 1024)
|
GUEST_MEMORY_SIZE / (1024 * 1024)
|
||||||
@ -1062,7 +1062,6 @@ impl VCpu {
|
|||||||
info!(" Reason: VM-entry failure due to invalid guest state");
|
info!(" Reason: VM-entry failure due to invalid guest state");
|
||||||
// Read VM-instruction error for more details
|
// Read VM-instruction error for more details
|
||||||
let vm_instruction_error = unsafe {
|
let vm_instruction_error = unsafe {
|
||||||
use x86::msr::rdmsr;
|
|
||||||
vmread(vmcs::ro::VM_INSTRUCTION_ERROR).unwrap_or(0)
|
vmread(vmcs::ro::VM_INSTRUCTION_ERROR).unwrap_or(0)
|
||||||
};
|
};
|
||||||
info!(" VM-instruction error: {}", vm_instruction_error);
|
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
|
// Try reading directly as physical address if translation fails
|
||||||
if rip < 0x100000000 {
|
if rip < 0x100000000 {
|
||||||
for i in 0..16 {
|
for i in 0..16 {
|
||||||
@ -1254,13 +1253,13 @@ impl VCpu {
|
|||||||
unsafe { vmread(vmcs::ro::GUEST_PHYSICAL_ADDR_FULL).unwrap() };
|
unsafe { vmread(vmcs::ro::GUEST_PHYSICAL_ADDR_FULL).unwrap() };
|
||||||
let exit_qualification =
|
let exit_qualification =
|
||||||
unsafe { vmread(vmcs::ro::EXIT_QUALIFICATION).unwrap() };
|
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 _read_access = (exit_qualification & 0x1) != 0;
|
||||||
let write_access = (exit_qualification & 0x2) != 0;
|
let _write_access = (exit_qualification & 0x2) != 0;
|
||||||
let execute_access = (exit_qualification & 0x4) != 0;
|
let _execute_access = (exit_qualification & 0x4) != 0;
|
||||||
let gpa_valid = (exit_qualification & 0x80) != 0;
|
let _gpa_valid = (exit_qualification & 0x80) != 0;
|
||||||
let translation_valid = (exit_qualification & 0x100) != 0;
|
let _translation_valid = (exit_qualification & 0x100) != 0;
|
||||||
|
|
||||||
let page_addr = guest_address & !0xFFF;
|
let page_addr = guest_address & !0xFFF;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user