diff --git a/arch/src/x86_64/regs.rs b/arch/src/x86_64/regs.rs index d8dbb0806..f4ea570c6 100644 --- a/arch/src/x86_64/regs.rs +++ b/arch/src/x86_64/regs.rs @@ -10,8 +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::arch::x86::StandardRegisters; -use hypervisor::x86_64::{FpuState, SpecialRegisters}; +use hypervisor::arch::x86::{SpecialRegisters, StandardRegisters}; +use hypervisor::x86_64::FpuState; use std::sync::Arc; use std::{mem, result}; use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError}; @@ -148,13 +148,13 @@ pub fn configure_segments_and_sregs( sregs.idt.base = BOOT_IDT_START.raw_value(); sregs.idt.limit = mem::size_of::() as u16 - 1; - sregs.cs = code_seg.into(); - sregs.ds = data_seg.into(); - sregs.es = data_seg.into(); - sregs.fs = data_seg.into(); - sregs.gs = data_seg.into(); - sregs.ss = data_seg.into(); - sregs.tr = tss_seg.into(); + sregs.cs = code_seg; + sregs.ds = data_seg; + sregs.es = data_seg; + sregs.fs = data_seg; + sregs.gs = data_seg; + sregs.ss = data_seg; + sregs.tr = tss_seg; sregs.cr0 = CR0_PE; sregs.cr4 = 0; diff --git a/hypervisor/src/arch/x86/emulator/mod.rs b/hypervisor/src/arch/x86/emulator/mod.rs index 77e27687b..c0d2860a5 100644 --- a/hypervisor/src/arch/x86/emulator/mod.rs +++ b/hypervisor/src/arch/x86/emulator/mod.rs @@ -8,9 +8,9 @@ use crate::arch::emulator::{EmulationError, EmulationResult, PlatformEmulator, P 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, SegmentRegister, StandardRegisters, + segment_type_expand_down, segment_type_ro, Exception, SegmentRegister, SpecialRegisters, + StandardRegisters, }; -use crate::x86_64::SpecialRegisters; use anyhow::Context; use iced_x86::*; @@ -390,12 +390,12 @@ impl CpuStateManager for EmulatorCpuState { } match reg { - Register::CS => Ok(self.sregs.cs.into()), - Register::DS => Ok(self.sregs.ds.into()), - Register::ES => Ok(self.sregs.es.into()), - Register::FS => Ok(self.sregs.fs.into()), - Register::GS => Ok(self.sregs.gs.into()), - Register::SS => Ok(self.sregs.ss.into()), + Register::CS => Ok(self.sregs.cs), + Register::DS => Ok(self.sregs.ds), + Register::ES => Ok(self.sregs.es), + Register::FS => Ok(self.sregs.fs), + Register::GS => Ok(self.sregs.gs), + Register::SS => Ok(self.sregs.ss), r => Err(PlatformError::InvalidRegister(anyhow!( "read_segment invalid register {:?}", r @@ -413,12 +413,12 @@ impl CpuStateManager for EmulatorCpuState { } match reg { - Register::CS => self.sregs.cs = segment_register.into(), - Register::DS => self.sregs.ds = segment_register.into(), - Register::ES => self.sregs.es = segment_register.into(), - Register::FS => self.sregs.fs = segment_register.into(), - Register::GS => self.sregs.gs = segment_register.into(), - Register::SS => self.sregs.ss = segment_register.into(), + Register::CS => self.sregs.cs = segment_register, + Register::DS => self.sregs.ds = segment_register, + Register::ES => self.sregs.es = segment_register, + Register::FS => self.sregs.fs = segment_register, + Register::GS => self.sregs.gs = segment_register, + Register::SS => self.sregs.ss = segment_register, r => return Err(PlatformError::InvalidRegister(anyhow!("{:?}", r))), } diff --git a/hypervisor/src/arch/x86/mod.rs b/hypervisor/src/arch/x86/mod.rs index deb3996e1..4dd737471 100644 --- a/hypervisor/src/arch/x86/mod.rs +++ b/hypervisor/src/arch/x86/mod.rs @@ -205,3 +205,26 @@ pub struct DescriptorTable { pub base: u64, pub limit: u16, } + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "with-serde", derive(Deserialize, Serialize))] +pub struct SpecialRegisters { + pub cs: SegmentRegister, + pub ds: SegmentRegister, + pub es: SegmentRegister, + pub fs: SegmentRegister, + pub gs: SegmentRegister, + pub ss: SegmentRegister, + pub tr: SegmentRegister, + pub ldt: SegmentRegister, + pub gdt: DescriptorTable, + pub idt: DescriptorTable, + pub cr0: u64, + pub cr2: u64, + pub cr3: u64, + pub cr4: u64, + pub cr8: u64, + pub efer: u64, + pub apic_base: u64, + pub interrupt_bitmap: [u64; 4usize], +} diff --git a/hypervisor/src/cpu.rs b/hypervisor/src/cpu.rs index dfce39074..649794d0b 100644 --- a/hypervisor/src/cpu.rs +++ b/hypervisor/src/cpu.rs @@ -13,7 +13,7 @@ use crate::aarch64::VcpuInit; #[cfg(target_arch = "aarch64")] use crate::aarch64::{RegList, Register, StandardRegisters}; #[cfg(target_arch = "x86_64")] -use crate::arch::x86::StandardRegisters; +use crate::arch::x86::{SpecialRegisters, StandardRegisters}; #[cfg(feature = "tdx")] use crate::kvm::{TdxExitDetails, TdxExitStatus}; #[cfg(all(feature = "mshv", target_arch = "x86_64"))] @@ -23,7 +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, VcpuEvents}; +use crate::x86_64::{ExtendedControlRegisters, FpuState, MsrEntries, 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 5acdeba90..7104be078 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::{StandardRegisters, NUM_IOAPIC_PINS}; +use crate::arch::x86::{SpecialRegisters, 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}; +use x86_64::{check_required_kvm_extensions, FpuState}; #[cfg(target_arch = "x86_64")] pub use x86_64::{ CpuId, CpuIdEntry, ExtendedControlRegisters, LapicState, MsrEntries, VcpuKvmState, Xsave, @@ -1273,17 +1273,20 @@ impl cpu::Vcpu for KvmVcpu { /// Returns the vCPU special registers. /// fn get_sregs(&self) -> cpu::Result { - self.fd + Ok(self + .fd .get_sregs() - .map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into())) + .map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into()))? + .into()) } #[cfg(target_arch = "x86_64")] /// /// Sets the vCPU special registers using the `KVM_SET_SREGS` ioctl. /// fn set_sregs(&self, sregs: &SpecialRegisters) -> cpu::Result<()> { + let sregs = (*sregs).into(); self.fd - .set_sregs(sregs) + .set_sregs(&sregs) .map_err(|e| cpu::HypervisorCpuError::SetSpecialRegs(e.into())) } #[cfg(target_arch = "x86_64")] @@ -1873,7 +1876,7 @@ impl cpu::Vcpu for KvmVcpu { msrs, vcpu_events, regs: regs.into(), - sregs, + sregs: sregs.into(), fpu, lapic_state, xsave, @@ -1942,7 +1945,7 @@ impl cpu::Vcpu for KvmVcpu { self.set_cpuid2(&state.cpuid)?; self.set_mp_state(state.mp_state.into())?; self.set_regs(&state.regs.into())?; - self.set_sregs(&state.sregs)?; + self.set_sregs(&state.sregs.into())?; self.set_xsave(&state.xsave)?; self.set_xcrs(&state.xcrs)?; self.set_lapic(&state.lapic_state)?; diff --git a/hypervisor/src/kvm/x86_64/mod.rs b/hypervisor/src/kvm/x86_64/mod.rs index f44e451c0..cae0fa393 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::{DescriptorTable, SegmentRegister, StandardRegisters}; +use crate::arch::x86::{DescriptorTable, SegmentRegister, SpecialRegisters, 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, 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, kvm_bindings::kvm_segment, kvm_bindings::kvm_sregs as SpecialRegisters, + kvm_bindings::kvm_regs, kvm_bindings::kvm_segment, kvm_bindings::kvm_sregs, 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, @@ -56,7 +56,7 @@ pub struct VcpuKvmState { pub msrs: MsrEntries, pub vcpu_events: VcpuEvents, pub regs: kvm_regs, - pub sregs: SpecialRegisters, + pub sregs: kvm_sregs, pub fpu: FpuState, pub lapic_state: LapicState, pub xsave: Xsave, @@ -171,3 +171,53 @@ impl From for DescriptorTable { } } } + +impl From for kvm_sregs { + fn from(s: SpecialRegisters) -> Self { + Self { + cs: s.cs.into(), + ds: s.ds.into(), + es: s.es.into(), + fs: s.fs.into(), + gs: s.gs.into(), + ss: s.ss.into(), + tr: s.tr.into(), + ldt: s.ldt.into(), + gdt: s.gdt.into(), + idt: s.idt.into(), + cr0: s.cr0, + cr2: s.cr2, + cr3: s.cr3, + cr4: s.cr4, + cr8: s.cr8, + efer: s.efer, + apic_base: s.apic_base, + interrupt_bitmap: s.interrupt_bitmap, + } + } +} + +impl From for SpecialRegisters { + fn from(s: kvm_sregs) -> Self { + Self { + cs: s.cs.into(), + ds: s.ds.into(), + es: s.es.into(), + fs: s.fs.into(), + gs: s.gs.into(), + ss: s.ss.into(), + tr: s.tr.into(), + ldt: s.ldt.into(), + gdt: s.gdt.into(), + idt: s.idt.into(), + cr0: s.cr0, + cr2: s.cr2, + cr3: s.cr3, + cr4: s.cr4, + cr8: s.cr8, + efer: s.efer, + apic_base: s.apic_base, + interrupt_bitmap: s.interrupt_bitmap, + } + } +} diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 0caed8bf5..ae602a450 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -37,7 +37,7 @@ use std::fs::File; use std::os::unix::io::AsRawFd; #[cfg(target_arch = "x86_64")] -use crate::arch::x86::StandardRegisters; +use crate::arch::x86::{SpecialRegisters, StandardRegisters}; const DIRTY_BITMAP_CLEAR_DIRTY: u64 = 0x4; const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8; @@ -296,17 +296,20 @@ impl cpu::Vcpu for MshvVcpu { /// Returns the vCPU special registers. /// fn get_sregs(&self) -> cpu::Result { - self.fd + Ok(self + .fd .get_sregs() - .map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into())) + .map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into()))? + .into()) } #[cfg(target_arch = "x86_64")] /// /// Sets the vCPU special registers. /// fn set_sregs(&self, sregs: &SpecialRegisters) -> cpu::Result<()> { + let sregs = (*sregs).into(); self.fd - .set_sregs(sregs) + .set_sregs(&sregs) .map_err(|e| cpu::HypervisorCpuError::SetSpecialRegs(e.into())) } #[cfg(target_arch = "x86_64")] @@ -626,7 +629,7 @@ impl cpu::Vcpu for MshvVcpu { self.set_msrs(&state.msrs)?; self.set_vcpu_events(&state.vcpu_events)?; self.set_regs(&state.regs.into())?; - self.set_sregs(&state.sregs)?; + self.set_sregs(&state.sregs.into())?; self.set_fpu(&state.fpu)?; self.set_xcrs(&state.xcrs)?; self.set_lapic(&state.lapic)?; @@ -669,7 +672,7 @@ impl cpu::Vcpu for MshvVcpu { msrs, vcpu_events, regs: regs.into(), - sregs, + sregs: sregs.into(), fpu, xcrs, lapic, diff --git a/hypervisor/src/mshv/x86_64/mod.rs b/hypervisor/src/mshv/x86_64/mod.rs index 06c567216..7992c35fe 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::{DescriptorTable, SegmentRegister, StandardRegisters}; +use crate::arch::x86::{DescriptorTable, SegmentRegister, SpecialRegisters, StandardRegisters}; use serde::{Deserialize, Serialize}; use std::fmt; @@ -21,7 +21,8 @@ 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 as MshvSegmentRegister, mshv_bindings::SpecialRegisters, + mshv_bindings::SegmentRegister as MshvSegmentRegister, + mshv_bindings::SpecialRegisters as MshvSpecialRegisters, mshv_bindings::StandardRegisters as MshvStandardRegisters, mshv_bindings::SuspendRegisters, mshv_bindings::TableRegister, mshv_bindings::VcpuEvents, mshv_bindings::XSave as Xsave, mshv_bindings::Xcrs as ExtendedControlRegisters, @@ -34,7 +35,7 @@ pub struct VcpuMshvState { pub msrs: MsrEntries, pub vcpu_events: VcpuEvents, pub regs: MshvStandardRegisters, - pub sregs: SpecialRegisters, + pub sregs: MshvSpecialRegisters, pub fpu: FpuState, pub xcrs: ExtendedControlRegisters, pub lapic: LapicState, @@ -173,3 +174,53 @@ impl From for DescriptorTable { } } } + +impl From for MshvSpecialRegisters { + fn from(s: SpecialRegisters) -> Self { + Self { + cs: s.cs.into(), + ds: s.ds.into(), + es: s.es.into(), + fs: s.fs.into(), + gs: s.gs.into(), + ss: s.ss.into(), + tr: s.tr.into(), + ldt: s.ldt.into(), + gdt: s.gdt.into(), + idt: s.idt.into(), + cr0: s.cr0, + cr2: s.cr2, + cr3: s.cr3, + cr4: s.cr4, + cr8: s.cr8, + efer: s.efer, + apic_base: s.apic_base, + interrupt_bitmap: s.interrupt_bitmap, + } + } +} + +impl From for SpecialRegisters { + fn from(s: MshvSpecialRegisters) -> Self { + Self { + cs: s.cs.into(), + ds: s.ds.into(), + es: s.es.into(), + fs: s.fs.into(), + gs: s.gs.into(), + ss: s.ss.into(), + tr: s.tr.into(), + ldt: s.ldt.into(), + gdt: s.gdt.into(), + idt: s.idt.into(), + cr0: s.cr0, + cr2: s.cr2, + cr3: s.cr3, + cr4: s.cr4, + cr8: s.cr8, + efer: s.efer, + apic_base: s.apic_base, + interrupt_bitmap: s.interrupt_bitmap, + } + } +} diff --git a/vmm/src/coredump.rs b/vmm/src/coredump.rs index 7b75ada44..11376472d 100644 --- a/vmm/src/coredump.rs +++ b/vmm/src/coredump.rs @@ -4,9 +4,7 @@ // #[cfg(target_arch = "x86_64")] -use hypervisor::arch::x86::SegmentRegister; -#[cfg(target_arch = "x86_64")] -use hypervisor::kvm::kvm_bindings::kvm_dtable as DTableRegister; +use hypervisor::arch::x86::{DescriptorTable, SegmentRegister}; use linux_loader::elf; use std::fs::File; use std::io::Write; @@ -135,7 +133,7 @@ impl CpuSegment { } } - pub fn new_from_table(reg: DTableRegister) -> Self { + pub fn new_from_table(reg: DescriptorTable) -> Self { CpuSegment { selector: 0, limit: reg.limit as u32, diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 43955becf..db57ffe31 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -37,15 +37,13 @@ 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; +use hypervisor::arch::x86::{SpecialRegisters, 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}; use hypervisor::{CpuState, HypervisorCpuError, VmExit, VmOps}; @@ -2287,14 +2285,14 @@ impl CpuElf64Writable for CpuManager { .map_err(|_e| GuestDebuggableError::Coredump(anyhow!("get msr failed")))?; let kernel_gs_base = msrs.as_slice()[0].data; - let cs = CpuSegment::new(sregs.cs.into()); - let ds = CpuSegment::new(sregs.ds.into()); - let es = CpuSegment::new(sregs.es.into()); - let fs = CpuSegment::new(sregs.fs.into()); - let gs = CpuSegment::new(sregs.gs.into()); - let ss = CpuSegment::new(sregs.ss.into()); - let ldt = CpuSegment::new(sregs.ldt.into()); - let tr = CpuSegment::new(sregs.tr.into()); + let cs = CpuSegment::new(sregs.cs); + let ds = CpuSegment::new(sregs.ds); + let es = CpuSegment::new(sregs.es); + let fs = CpuSegment::new(sregs.fs); + let gs = CpuSegment::new(sregs.gs); + let ss = CpuSegment::new(sregs.ss); + let ldt = CpuSegment::new(sregs.ldt); + let tr = CpuSegment::new(sregs.tr); let gdt = CpuSegment::new_from_table(sregs.gdt); let idt = CpuSegment::new_from_table(sregs.idt); let cr = [sregs.cr0, sregs.cr8, sregs.cr2, sregs.cr3, sregs.cr4];