use crate::{
cputure::GuestRegisters, vmexit::{ExitType, exception::EventInjection}, x86::msr
};
pub enum MsrAccessType {
Read,
Write,
}
pub fn handle_msr_access(
guest_registers: &mut GuestRegisters,
access_type: MsrAccessType,
) -> ExitType {
log::trace!("Handling MSR VM exit...");
const MSR_MASK_LOW: u64 = u32::MAX as u64;
const MSR_RANGE_LOW_END: u64 = 0x00001FFF;
const MSR_RANGE_HIGH_START: u64 = 0xC0000000;
const MSR_RANGE_HIGH_END: u64 = 0xC0001FFF;
const HYPERV_MSR_START: u64 = 0x40000000;
const HYPERV_MSR_END: u64 = 0x4000FFFF;
let msr_id = guest_registers.rcx;
if (msr_id <= MSR_RANGE_LOW_END)
|| ((msr_id >= MSR_RANGE_HIGH_START) && (msr_id <= MSR_RANGE_HIGH_END))
|| (msr_id >= HYPERV_MSR_START) && (msr_id <= HYPERV_MSR_END)
{
log::trace!("Valid MSR access attempted: {:#x}", msr_id);
match access_type {
MsrAccessType::Read => {
let msr_value = msr::rdmsr(msr_id as _);
guest_registers.rdx = msr_value >> 32;
guest_registers.rax = msr_value & MSR_MASK_LOW;
}
MsrAccessType::Write => {
let msr_value = (guest_registers.rdx << 32) | (guest_registers.rax & MSR_MASK_LOW);
unsafe { msr::wrmsr(msr_id as _, msr_value) };
}
}
} else {
log::info!("Invalid MSR access attempted: {:#x}", msr_id);
EventInjection::vmentry_inject_gp(0);
return ExitType::Continue;
}
log::trace!("MSR VMEXIT handled successfully.");
ExitType::IncrementRIP
}