AMD-V on Intel VT-d

This commit is contained in:
Masato Imai
2025-07-14 09:38:19 +00:00
parent f67b0b7477
commit 6e4850a738
2 changed files with 72 additions and 50 deletions

View File

@ -7,6 +7,8 @@ use x86::vmx::vmcs;
use x86_64::structures::paging::{OffsetPageTable, Translate}; use x86_64::structures::paging::{OffsetPageTable, Translate};
use x86_64::{PhysAddr, VirtAddr}; use x86_64::{PhysAddr, VirtAddr};
use crate::info;
use super::vcpu::VCpu; use super::vcpu::VCpu;
type MsrIndex = u32; type MsrIndex = u32;
@ -132,7 +134,7 @@ impl ShadowMsr {
// Lock bit (0) | Enable VMX inside SMX (1) | Enable VMX outside SMX (2) // Lock bit (0) | Enable VMX inside SMX (1) | Enable VMX outside SMX (2)
Self::set_ret_val(vcpu, 0x5) Self::set_ret_val(vcpu, 0x5)
} }
0x48 => Self::set_ret_val(vcpu, 0), // IA32_SPEC_CTRL 0x48 => Self::set_ret_val(vcpu, 0), // IA32_SPEC_CTRL
0x122 => Self::set_ret_val(vcpu, 0), // IA32_TSX_CTRL 0x122 => Self::set_ret_val(vcpu, 0), // IA32_TSX_CTRL
0x560 => Self::set_ret_val(vcpu, 0), // IA32_RTIT_OUTPUT_BASE 0x560 => Self::set_ret_val(vcpu, 0), // IA32_RTIT_OUTPUT_BASE
0x561 => Self::set_ret_val(vcpu, 0), // IA32_RTIT_OUTPUT_MASK_PTRS 0x561 => Self::set_ret_val(vcpu, 0), // IA32_RTIT_OUTPUT_MASK_PTRS
@ -158,15 +160,15 @@ impl ShadowMsr {
x86::msr::IA32_LSTAR => 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_CSTAR => Self::shadow_read(vcpu, msr_kind),
x86::msr::IA32_FMASK => Self::shadow_read(vcpu, msr_kind), x86::msr::IA32_FMASK => Self::shadow_read(vcpu, msr_kind),
x86::msr::SYSENTER_CS_MSR => { x86::msr::SYSENTER_CS_MSR => Self::set_ret_val(vcpu, unsafe {
Self::set_ret_val(vcpu, unsafe { vmread(vmcs::guest::IA32_SYSENTER_CS).unwrap() }) vmread(vmcs::guest::IA32_SYSENTER_CS).unwrap()
} }),
x86::msr::SYSENTER_ESP_MSR => { x86::msr::SYSENTER_ESP_MSR => Self::set_ret_val(vcpu, unsafe {
Self::set_ret_val(vcpu, unsafe { vmread(vmcs::guest::IA32_SYSENTER_ESP).unwrap() }) vmread(vmcs::guest::IA32_SYSENTER_ESP).unwrap()
} }),
x86::msr::SYSENTER_EIP_MSR => { x86::msr::SYSENTER_EIP_MSR => Self::set_ret_val(vcpu, unsafe {
Self::set_ret_val(vcpu, unsafe { vmread(vmcs::guest::IA32_SYSENTER_EIP).unwrap() }) 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),
@ -179,10 +181,10 @@ impl ShadowMsr {
0xc0010117 => Self::set_ret_val(vcpu, 0), // MSR_VM_HSAVE_PA 0xc0010117 => Self::set_ret_val(vcpu, 0), // MSR_VM_HSAVE_PA
0x277 => Self::set_ret_val(vcpu, 0x0007040600070406), 0x277 => Self::set_ret_val(vcpu, 0x0007040600070406),
0xc0000103 => Self::shadow_read(vcpu, msr_kind), // TSC_AUX 0xc0000103 => Self::shadow_read(vcpu, msr_kind), // TSC_AUX
0xd90 => Self::set_ret_val(vcpu, 0), // MSR_C1_PMON_EVNT_SEL0 0xd90 => Self::set_ret_val(vcpu, 0), // MSR_C1_PMON_EVNT_SEL0
0xe1 => Self::set_ret_val(vcpu, 0), // IA32_UMWAIT_CONTROL 0xe1 => Self::set_ret_val(vcpu, 0), // IA32_UMWAIT_CONTROL
0x1c4 => Self::set_ret_val(vcpu, 0), // Unknown MSR 0x1c4 => Self::set_ret_val(vcpu, 0), // Unknown MSR
0x1c5 => 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);
} }
@ -218,11 +220,17 @@ impl ShadowMsr {
x86::msr::SYSENTER_ESP_MSR => unsafe { x86::msr::SYSENTER_ESP_MSR => unsafe {
vmwrite(vmcs::guest::IA32_SYSENTER_ESP, value).unwrap() vmwrite(vmcs::guest::IA32_SYSENTER_ESP, value).unwrap()
}, },
x86::msr::IA32_EFER => unsafe { vmwrite(vmcs::guest::IA32_EFER_FULL, value).unwrap() }, x86::msr::IA32_EFER => {
info!("Setting IA32_EFER: {:#x}", value);
if value == 0xd01 || value == 0x100 {
unsafe { vmwrite(vmcs::guest::IA32_EFER_FULL, value).unwrap() }
}
}
x86::msr::IA32_FS_BASE => unsafe { vmwrite(vmcs::guest::FS_BASE, value).unwrap() }, 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() }, x86::msr::IA32_GS_BASE => unsafe { vmwrite(vmcs::guest::GS_BASE, value).unwrap() },
0x1b => Self::shadow_write(vcpu, msr_kind), 0x1b => Self::shadow_write(vcpu, msr_kind),
0xc0010007 => Self::shadow_write(vcpu, msr_kind), 0xc0010007 => Self::shadow_write(vcpu, msr_kind),
0xc0010117 => Self::shadow_write(vcpu, msr_kind),
_ => { _ => {
panic!("Unhandled WRMSR: {:#x}", msr_kind); panic!("Unhandled WRMSR: {:#x}", msr_kind);

View File

@ -369,6 +369,7 @@ impl VCpu {
.unwrap(); .unwrap();
self.guest_msr.set(0x1b, 0).unwrap(); self.guest_msr.set(0x1b, 0).unwrap();
self.guest_msr.set(0xc0010007, 0).unwrap(); self.guest_msr.set(0xc0010007, 0).unwrap();
self.guest_msr.set(0xc0010117, 0).unwrap();
vmwrite( vmwrite(
vmcs::control::VMEXIT_MSR_LOAD_ADDR_FULL, vmcs::control::VMEXIT_MSR_LOAD_ADDR_FULL,
@ -1061,44 +1062,57 @@ impl VCpu {
33 => { 33 => {
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 =
vmread(vmcs::ro::VM_INSTRUCTION_ERROR).unwrap_or(0) unsafe { vmread(vmcs::ro::VM_INSTRUCTION_ERROR).unwrap_or(0) };
};
info!(" VM-instruction error: {}", vm_instruction_error); info!(" VM-instruction error: {}", vm_instruction_error);
// Dump guest state for debugging // Dump guest state for debugging
unsafe { unsafe {
info!(" Guest state dump:"); info!(" Guest state dump:");
info!(" CS: selector={:#x}, base={:#x}, limit={:#x}, rights={:#x}", info!(
vmread(vmcs::guest::CS_SELECTOR).unwrap(), " CS: selector={:#x}, base={:#x}, limit={:#x}, rights={:#x}",
vmread(vmcs::guest::CS_BASE).unwrap(), vmread(vmcs::guest::CS_SELECTOR).unwrap(),
vmread(vmcs::guest::CS_LIMIT).unwrap(), vmread(vmcs::guest::CS_BASE).unwrap(),
vmread(vmcs::guest::CS_ACCESS_RIGHTS).unwrap()); vmread(vmcs::guest::CS_LIMIT).unwrap(),
info!(" SS: selector={:#x}, base={:#x}, limit={:#x}, rights={:#x}", vmread(vmcs::guest::CS_ACCESS_RIGHTS).unwrap()
vmread(vmcs::guest::SS_SELECTOR).unwrap(), );
vmread(vmcs::guest::SS_BASE).unwrap(), info!(
vmread(vmcs::guest::SS_LIMIT).unwrap(), " SS: selector={:#x}, base={:#x}, limit={:#x}, rights={:#x}",
vmread(vmcs::guest::SS_ACCESS_RIGHTS).unwrap()); vmread(vmcs::guest::SS_SELECTOR).unwrap(),
info!(" DS: selector={:#x}, base={:#x}, limit={:#x}, rights={:#x}", vmread(vmcs::guest::SS_BASE).unwrap(),
vmread(vmcs::guest::DS_SELECTOR).unwrap(), vmread(vmcs::guest::SS_LIMIT).unwrap(),
vmread(vmcs::guest::DS_BASE).unwrap(), vmread(vmcs::guest::SS_ACCESS_RIGHTS).unwrap()
vmread(vmcs::guest::DS_LIMIT).unwrap(), );
vmread(vmcs::guest::DS_ACCESS_RIGHTS).unwrap()); info!(
info!(" ES: selector={:#x}, base={:#x}, limit={:#x}, rights={:#x}", " DS: selector={:#x}, base={:#x}, limit={:#x}, rights={:#x}",
vmread(vmcs::guest::ES_SELECTOR).unwrap(), vmread(vmcs::guest::DS_SELECTOR).unwrap(),
vmread(vmcs::guest::ES_BASE).unwrap(), vmread(vmcs::guest::DS_BASE).unwrap(),
vmread(vmcs::guest::ES_LIMIT).unwrap(), vmread(vmcs::guest::DS_LIMIT).unwrap(),
vmread(vmcs::guest::ES_ACCESS_RIGHTS).unwrap()); vmread(vmcs::guest::DS_ACCESS_RIGHTS).unwrap()
info!(" RIP={:#x}, RSP={:#x}, RFLAGS={:#x}", );
vmread(vmcs::guest::RIP).unwrap(), info!(
vmread(vmcs::guest::RSP).unwrap(), " ES: selector={:#x}, base={:#x}, limit={:#x}, rights={:#x}",
vmread(vmcs::guest::RFLAGS).unwrap()); vmread(vmcs::guest::ES_SELECTOR).unwrap(),
info!(" CR0={:#x}, CR3={:#x}, CR4={:#x}", vmread(vmcs::guest::ES_BASE).unwrap(),
vmread(vmcs::guest::CR0).unwrap(), vmread(vmcs::guest::ES_LIMIT).unwrap(),
vmread(vmcs::guest::CR3).unwrap(), vmread(vmcs::guest::ES_ACCESS_RIGHTS).unwrap()
vmread(vmcs::guest::CR4).unwrap()); );
info!(" EFER={:#x}", info!(
vmread(vmcs::guest::IA32_EFER_FULL).unwrap()); " RIP={:#x}, RSP={:#x}, RFLAGS={:#x}",
vmread(vmcs::guest::RIP).unwrap(),
vmread(vmcs::guest::RSP).unwrap(),
vmread(vmcs::guest::RFLAGS).unwrap()
);
info!(
" CR0={:#x}, CR3={:#x}, CR4={:#x}",
vmread(vmcs::guest::CR0).unwrap(),
vmread(vmcs::guest::CR3).unwrap(),
vmread(vmcs::guest::CR4).unwrap()
);
info!(
" EFER={:#x}",
vmread(vmcs::guest::IA32_EFER_FULL).unwrap()
);
} }
panic!("VM-entry failure due to invalid guest state"); panic!("VM-entry failure due to invalid guest state");
} }