diff --git a/arch/src/x86_64/regs.rs b/arch/src/x86_64/regs.rs index 6df184200..52fd2b530 100644 --- a/arch/src/x86_64/regs.rs +++ b/arch/src/x86_64/regs.rs @@ -10,7 +10,8 @@ use crate::layout::{BOOT_GDT_START, BOOT_IDT_START, PVH_INFO_START}; use crate::GuestMemoryMmap; use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt}; use hypervisor::arch::x86::regs::CR0_PE; -use hypervisor::x86_64::{FpuState, SpecialRegisters, StandardRegisters}; +use hypervisor::arch::x86::StandardRegisters; +use hypervisor::x86_64::{FpuState, SpecialRegisters}; use std::sync::Arc; use std::{mem, result}; use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError}; diff --git a/hypervisor/src/arch/x86/emulator/mod.rs b/hypervisor/src/arch/x86/emulator/mod.rs index 51bc08679..50fc02544 100644 --- a/hypervisor/src/arch/x86/emulator/mod.rs +++ b/hypervisor/src/arch/x86/emulator/mod.rs @@ -7,8 +7,10 @@ use crate::arch::emulator::{EmulationError, EmulationResult, PlatformEmulator, PlatformError}; use crate::arch::x86::emulator::instructions::*; use crate::arch::x86::regs::{CR0_PE, EFER_LMA}; -use crate::arch::x86::{segment_type_expand_down, segment_type_ro, Exception, SegmentRegisterOps}; -use crate::x86_64::{SegmentRegister, SpecialRegisters, StandardRegisters}; +use crate::arch::x86::{ + segment_type_expand_down, segment_type_ro, Exception, SegmentRegisterOps, StandardRegisters, +}; +use crate::x86_64::{SegmentRegister, SpecialRegisters}; use anyhow::Context; use iced_x86::*; diff --git a/hypervisor/src/arch/x86/mod.rs b/hypervisor/src/arch/x86/mod.rs index 087ba7676..25214166b 100644 --- a/hypervisor/src/arch/x86/mod.rs +++ b/hypervisor/src/arch/x86/mod.rs @@ -129,3 +129,26 @@ macro_rules! msr_data { } }; } + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))] +pub struct StandardRegisters { + pub rax: u64, + pub rbx: u64, + pub rcx: u64, + pub rdx: u64, + pub rsi: u64, + pub rdi: u64, + pub rsp: u64, + pub rbp: u64, + pub r8: u64, + pub r9: u64, + pub r10: u64, + pub r11: u64, + pub r12: u64, + pub r13: u64, + pub r14: u64, + pub r15: u64, + pub rip: u64, + pub rflags: u64, +} diff --git a/hypervisor/src/cpu.rs b/hypervisor/src/cpu.rs index 5e22bce0c..dfce39074 100644 --- a/hypervisor/src/cpu.rs +++ b/hypervisor/src/cpu.rs @@ -12,6 +12,8 @@ use crate::aarch64::VcpuInit; #[cfg(target_arch = "aarch64")] use crate::aarch64::{RegList, Register, StandardRegisters}; +#[cfg(target_arch = "x86_64")] +use crate::arch::x86::StandardRegisters; #[cfg(feature = "tdx")] use crate::kvm::{TdxExitDetails, TdxExitStatus}; #[cfg(all(feature = "mshv", target_arch = "x86_64"))] @@ -21,9 +23,7 @@ use crate::x86_64::Xsave; #[cfg(target_arch = "x86_64")] use crate::x86_64::{CpuId, LapicState}; #[cfg(target_arch = "x86_64")] -use crate::x86_64::{ - ExtendedControlRegisters, FpuState, MsrEntries, SpecialRegisters, StandardRegisters, VcpuEvents, -}; +use crate::x86_64::{ExtendedControlRegisters, FpuState, MsrEntries, SpecialRegisters, VcpuEvents}; use crate::CpuState; #[cfg(target_arch = "aarch64")] use crate::DeviceAttr; diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index ef0f8a8e8..5acdeba90 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -46,7 +46,7 @@ use vmm_sys_util::eventfd::EventFd; #[cfg(target_arch = "x86_64")] pub mod x86_64; #[cfg(target_arch = "x86_64")] -use crate::arch::x86::NUM_IOAPIC_PINS; +use crate::arch::x86::{StandardRegisters, NUM_IOAPIC_PINS}; #[cfg(target_arch = "x86_64")] use crate::ClockData; use crate::{ @@ -61,7 +61,7 @@ use kvm_bindings::{ KVM_CAP_SPLIT_IRQCHIP, KVM_GUESTDBG_ENABLE, KVM_GUESTDBG_SINGLESTEP, KVM_GUESTDBG_USE_HW_BP, }; #[cfg(target_arch = "x86_64")] -use x86_64::{check_required_kvm_extensions, FpuState, SpecialRegisters, StandardRegisters}; +use x86_64::{check_required_kvm_extensions, FpuState, SpecialRegisters}; #[cfg(target_arch = "x86_64")] pub use x86_64::{ CpuId, CpuIdEntry, ExtendedControlRegisters, LapicState, MsrEntries, VcpuKvmState, Xsave, @@ -1052,9 +1052,11 @@ impl cpu::Vcpu for KvmVcpu { /// Returns the vCPU general purpose registers. /// fn get_regs(&self) -> cpu::Result { - self.fd + Ok(self + .fd .get_regs() - .map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into())) + .map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into()))? + .into()) } /// /// Returns the vCPU general purpose registers. @@ -1158,8 +1160,9 @@ impl cpu::Vcpu for KvmVcpu { /// Sets the vCPU general purpose registers using the `KVM_SET_REGS` ioctl. /// fn set_regs(&self, regs: &StandardRegisters) -> cpu::Result<()> { + let regs = (*regs).into(); self.fd - .set_regs(regs) + .set_regs(®s) .map_err(|e| cpu::HypervisorCpuError::SetStandardRegs(e.into())) } @@ -1869,7 +1872,7 @@ impl cpu::Vcpu for KvmVcpu { cpuid, msrs, vcpu_events, - regs, + regs: regs.into(), sregs, fpu, lapic_state, @@ -1938,7 +1941,7 @@ impl cpu::Vcpu for KvmVcpu { let state: VcpuKvmState = state.clone().into(); self.set_cpuid2(&state.cpuid)?; self.set_mp_state(state.mp_state.into())?; - self.set_regs(&state.regs)?; + self.set_regs(&state.regs.into())?; self.set_sregs(&state.sregs)?; self.set_xsave(&state.xsave)?; self.set_xcrs(&state.xcrs)?; diff --git a/hypervisor/src/kvm/x86_64/mod.rs b/hypervisor/src/kvm/x86_64/mod.rs index b05f474a7..3e2530081 100644 --- a/hypervisor/src/kvm/x86_64/mod.rs +++ b/hypervisor/src/kvm/x86_64/mod.rs @@ -8,7 +8,7 @@ // // -use crate::arch::x86::SegmentRegisterOps; +use crate::arch::x86::{SegmentRegisterOps, StandardRegisters}; use crate::kvm::{Cap, Kvm, KvmError, KvmResult}; use serde::{Deserialize, Serialize}; @@ -19,7 +19,7 @@ pub use { kvm_bindings::kvm_cpuid_entry2 as CpuIdEntry, kvm_bindings::kvm_dtable as DescriptorTable, kvm_bindings::kvm_fpu as FpuState, kvm_bindings::kvm_lapic_state as LapicState, kvm_bindings::kvm_mp_state as MpState, kvm_bindings::kvm_msr_entry as MsrEntry, - kvm_bindings::kvm_regs as StandardRegisters, kvm_bindings::kvm_segment as SegmentRegister, + kvm_bindings::kvm_regs, kvm_bindings::kvm_segment as SegmentRegister, kvm_bindings::kvm_sregs as SpecialRegisters, kvm_bindings::kvm_vcpu_events as VcpuEvents, kvm_bindings::kvm_xcrs as ExtendedControlRegisters, kvm_bindings::kvm_xsave as Xsave, kvm_bindings::CpuId, kvm_bindings::MsrList, kvm_bindings::Msrs as MsrEntries, @@ -120,7 +120,7 @@ pub struct VcpuKvmState { pub cpuid: CpuId, pub msrs: MsrEntries, pub vcpu_events: VcpuEvents, - pub regs: StandardRegisters, + pub regs: kvm_regs, pub sregs: SpecialRegisters, pub fpu: FpuState, pub lapic_state: LapicState, @@ -128,3 +128,53 @@ pub struct VcpuKvmState { pub xcrs: ExtendedControlRegisters, pub mp_state: MpState, } + +impl From for kvm_regs { + fn from(regs: StandardRegisters) -> Self { + Self { + rax: regs.rax, + rbx: regs.rbx, + rcx: regs.rcx, + rdx: regs.rdx, + rsi: regs.rsi, + rdi: regs.rdi, + rsp: regs.rsp, + rbp: regs.rbp, + r8: regs.r8, + r9: regs.r9, + r10: regs.r10, + r11: regs.r11, + r12: regs.r12, + r13: regs.r13, + r14: regs.r14, + r15: regs.r15, + rip: regs.rip, + rflags: regs.rflags, + } + } +} + +impl From for StandardRegisters { + fn from(regs: kvm_regs) -> Self { + Self { + rax: regs.rax, + rbx: regs.rbx, + rcx: regs.rcx, + rdx: regs.rdx, + rsi: regs.rsi, + rdi: regs.rdi, + rsp: regs.rsp, + rbp: regs.rbp, + r8: regs.r8, + r9: regs.r9, + r10: regs.r10, + r11: regs.r11, + r12: regs.r12, + r13: regs.r13, + r14: regs.r14, + r15: regs.r15, + rip: regs.rip, + rflags: regs.rflags, + } + } +} diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 14e4a3414..0caed8bf5 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -36,6 +36,9 @@ pub use x86_64::*; use std::fs::File; use std::os::unix::io::AsRawFd; +#[cfg(target_arch = "x86_64")] +use crate::arch::x86::StandardRegisters; + const DIRTY_BITMAP_CLEAR_DIRTY: u64 = 0x4; const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8; @@ -272,17 +275,20 @@ impl cpu::Vcpu for MshvVcpu { /// Returns the vCPU general purpose registers. /// fn get_regs(&self) -> cpu::Result { - self.fd + Ok(self + .fd .get_regs() - .map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into())) + .map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into()))? + .into()) } #[cfg(target_arch = "x86_64")] /// /// Sets the vCPU general purpose registers. /// fn set_regs(&self, regs: &StandardRegisters) -> cpu::Result<()> { + let regs = (*regs).into(); self.fd - .set_regs(regs) + .set_regs(®s) .map_err(|e| cpu::HypervisorCpuError::SetStandardRegs(e.into())) } #[cfg(target_arch = "x86_64")] @@ -619,7 +625,7 @@ impl cpu::Vcpu for MshvVcpu { let state: VcpuMshvState = state.clone().into(); self.set_msrs(&state.msrs)?; self.set_vcpu_events(&state.vcpu_events)?; - self.set_regs(&state.regs)?; + self.set_regs(&state.regs.into())?; self.set_sregs(&state.sregs)?; self.set_fpu(&state.fpu)?; self.set_xcrs(&state.xcrs)?; @@ -662,7 +668,7 @@ impl cpu::Vcpu for MshvVcpu { Ok(VcpuMshvState { msrs, vcpu_events, - regs, + regs: regs.into(), sregs, fpu, xcrs, diff --git a/hypervisor/src/mshv/x86_64/mod.rs b/hypervisor/src/mshv/x86_64/mod.rs index 978739993..e414444f0 100644 --- a/hypervisor/src/mshv/x86_64/mod.rs +++ b/hypervisor/src/mshv/x86_64/mod.rs @@ -7,7 +7,7 @@ // Copyright 2018-2019 CrowdStrike, Inc. // // -use crate::arch::x86::SegmentRegisterOps; +use crate::arch::x86::{SegmentRegisterOps, StandardRegisters}; use serde::{Deserialize, Serialize}; use std::fmt; @@ -21,7 +21,7 @@ pub use { mshv_bindings::FloatingPointUnit as FpuState, mshv_bindings::LapicState, mshv_bindings::MiscRegs as MiscRegisters, mshv_bindings::MsrList, mshv_bindings::Msrs as MsrEntries, mshv_bindings::Msrs, mshv_bindings::SegmentRegister, - mshv_bindings::SpecialRegisters, mshv_bindings::StandardRegisters, + mshv_bindings::SpecialRegisters, mshv_bindings::StandardRegisters as MshvStandardRegisters, mshv_bindings::SuspendRegisters, mshv_bindings::VcpuEvents, mshv_bindings::XSave as Xsave, mshv_bindings::Xcrs as ExtendedControlRegisters, }; @@ -32,7 +32,7 @@ pub const CPUID_FLAG_VALID_INDEX: u32 = 0; pub struct VcpuMshvState { pub msrs: MsrEntries, pub vcpu_events: VcpuEvents, - pub regs: StandardRegisters, + pub regs: MshvStandardRegisters, pub sregs: SpecialRegisters, pub fpu: FpuState, pub xcrs: ExtendedControlRegisters, @@ -130,3 +130,53 @@ impl SegmentRegisterOps for SegmentRegister { self.db = val; } } + +impl From for MshvStandardRegisters { + fn from(regs: StandardRegisters) -> Self { + Self { + rax: regs.rax, + rbx: regs.rbx, + rcx: regs.rcx, + rdx: regs.rdx, + rsi: regs.rsi, + rdi: regs.rdi, + rsp: regs.rsp, + rbp: regs.rbp, + r8: regs.r8, + r9: regs.r9, + r10: regs.r10, + r11: regs.r11, + r12: regs.r12, + r13: regs.r13, + r14: regs.r14, + r15: regs.r15, + rip: regs.rip, + rflags: regs.rflags, + } + } +} + +impl From for StandardRegisters { + fn from(regs: MshvStandardRegisters) -> Self { + Self { + rax: regs.rax, + rbx: regs.rbx, + rcx: regs.rcx, + rdx: regs.rdx, + rsi: regs.rsi, + rdi: regs.rdi, + rsp: regs.rsp, + rbp: regs.rbp, + r8: regs.r8, + r9: regs.r9, + r10: regs.r10, + r11: regs.r11, + r12: regs.r12, + r13: regs.r13, + r14: regs.r14, + r15: regs.r15, + rip: regs.rip, + rflags: regs.rflags, + } + } +} diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 76e6cdd53..ee2199fa8 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -36,16 +36,18 @@ use devices::interrupt_controller::InterruptController; use gdbstub_arch::x86::reg::{X86SegmentRegs, X86_64CoreRegs}; #[cfg(feature = "guest_debug")] use hypervisor::arch::x86::msr_index; +#[cfg(all(target_arch = "x86_64", feature = "gdb"))] +use hypervisor::arch::x86::StandardRegisters; #[cfg(target_arch = "aarch64")] use hypervisor::kvm::kvm_bindings; #[cfg(feature = "tdx")] use hypervisor::kvm::{TdxExitDetails, TdxExitStatus}; #[cfg(target_arch = "x86_64")] use hypervisor::x86_64::CpuId; +#[cfg(all(target_arch = "x86_64", feature = "gdb"))] +use hypervisor::x86_64::SpecialRegisters; #[cfg(feature = "guest_debug")] use hypervisor::x86_64::{MsrEntries, MsrEntry}; -#[cfg(all(target_arch = "x86_64", feature = "gdb"))] -use hypervisor::x86_64::{SpecialRegisters, StandardRegisters}; use hypervisor::{CpuState, HypervisorCpuError, VmExit, VmOps}; use libc::{c_void, siginfo_t}; #[cfg(feature = "guest_debug")] @@ -2336,7 +2338,8 @@ impl CpuElf64Writable for CpuManager { mod tests { use arch::x86_64::interrupts::*; use arch::x86_64::regs::*; - use hypervisor::x86_64::{FpuState, LapicState, StandardRegisters}; + use hypervisor::arch::x86::StandardRegisters; + use hypervisor::x86_64::{FpuState, LapicState}; #[test] fn test_setlint() {