diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index f04efc9ce..afa489b9d 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -15,7 +15,7 @@ pub mod regs; use crate::GuestMemoryMmap; use crate::InitramfsConfig; use crate::RegionType; -use hypervisor::x86_64::{CpuIdEntry, CPUID_FLAG_VALID_INDEX}; +use hypervisor::arch::x86::{CpuIdEntry, CPUID_FLAG_VALID_INDEX}; use hypervisor::HypervisorError; use linux_loader::loader::bootparam::boot_params; use linux_loader::loader::elf::start_info::{ diff --git a/hypervisor/src/arch/x86/mod.rs b/hypervisor/src/arch/x86/mod.rs index 4dd737471..034edd759 100644 --- a/hypervisor/src/arch/x86/mod.rs +++ b/hypervisor/src/arch/x86/mod.rs @@ -228,3 +228,16 @@ pub struct SpecialRegisters { pub apic_base: u64, pub interrupt_bitmap: [u64; 4usize], } + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)] +pub struct CpuIdEntry { + pub function: u32, + pub index: u32, + pub flags: u32, + pub eax: u32, + pub ebx: u32, + pub ecx: u32, + pub edx: u32, +} + +pub const CPUID_FLAG_VALID_INDEX: u32 = 1; diff --git a/hypervisor/src/cpu.rs b/hypervisor/src/cpu.rs index dacf35aa8..6ec8cf2cd 100644 --- a/hypervisor/src/cpu.rs +++ b/hypervisor/src/cpu.rs @@ -13,13 +13,13 @@ use crate::aarch64::VcpuInit; #[cfg(target_arch = "aarch64")] use crate::aarch64::{RegList, Register, StandardRegisters}; #[cfg(target_arch = "x86_64")] -use crate::arch::x86::{SpecialRegisters, StandardRegisters}; +use crate::arch::x86::{CpuIdEntry, SpecialRegisters, StandardRegisters}; #[cfg(feature = "tdx")] use crate::kvm::{TdxExitDetails, TdxExitStatus}; #[cfg(target_arch = "x86_64")] -use crate::x86_64::Xsave; +use crate::x86_64::LapicState; #[cfg(target_arch = "x86_64")] -use crate::x86_64::{CpuIdEntry, LapicState}; +use crate::x86_64::Xsave; #[cfg(target_arch = "x86_64")] use crate::x86_64::{ExtendedControlRegisters, FpuState, MsrEntries, VcpuEvents}; use crate::CpuState; diff --git a/hypervisor/src/hypervisor.rs b/hypervisor/src/hypervisor.rs index 27efd0da0..3ad975abb 100644 --- a/hypervisor/src/hypervisor.rs +++ b/hypervisor/src/hypervisor.rs @@ -7,12 +7,12 @@ // Copyright 2018-2019 CrowdStrike, Inc. // // +#[cfg(target_arch = "x86_64")] +use crate::arch::x86::CpuIdEntry; #[cfg(feature = "tdx")] use crate::kvm::TdxCapabilities; use crate::vm::Vm; #[cfg(target_arch = "x86_64")] -use crate::x86_64::CpuIdEntry; -#[cfg(target_arch = "x86_64")] use crate::x86_64::MsrList; use std::sync::Arc; use thiserror::Error; diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 7cb0457ad..ca547f009 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::{SpecialRegisters, StandardRegisters, NUM_IOAPIC_PINS}; +use crate::arch::x86::{CpuIdEntry, SpecialRegisters, StandardRegisters, NUM_IOAPIC_PINS}; #[cfg(target_arch = "x86_64")] use crate::ClockData; use crate::{ @@ -63,10 +63,7 @@ use kvm_bindings::{ #[cfg(target_arch = "x86_64")] use x86_64::{check_required_kvm_extensions, FpuState}; #[cfg(target_arch = "x86_64")] -pub use x86_64::{ - CpuId, CpuIdEntry, ExtendedControlRegisters, LapicState, MsrEntries, VcpuKvmState, Xsave, - CPUID_FLAG_VALID_INDEX, -}; +pub use x86_64::{CpuId, ExtendedControlRegisters, LapicState, MsrEntries, VcpuKvmState, Xsave}; // aarch64 dependencies #[cfg(target_arch = "aarch64")] pub mod aarch64; @@ -757,7 +754,9 @@ impl vm::Vm for KvmVm { #[cfg(feature = "tdx")] fn tdx_init(&self, cpuid: &[CpuIdEntry], max_vcpus: u32) -> vm::Result<()> { use std::io::{Error, ErrorKind}; - let kvm_cpuid = kvm_bindings::CpuId::from_entries(cpuid).map_err(|_| { + let cpuid: Vec = + cpuid.iter().map(|e| (*e).into()).collect(); + let kvm_cpuid = kvm_bindings::CpuId::from_entries(&cpuid).map_err(|_| { vm::HypervisorVmError::InitializeTdx(Error::new( ErrorKind::Other, "failed to allocate CpuId", @@ -997,7 +996,7 @@ impl hypervisor::Hypervisor for KvmHypervisor { .get_supported_cpuid(kvm_bindings::KVM_MAX_CPUID_ENTRIES) .map_err(|e| hypervisor::HypervisorError::GetCpuId(e.into()))?; - let v = kvm_cpuid.as_slice().to_vec(); + let v = kvm_cpuid.as_slice().iter().map(|e| (*e).into()).collect(); Ok(v) } @@ -1325,7 +1324,9 @@ impl cpu::Vcpu for KvmVcpu { /// X86 specific call to setup the CPUID registers. /// fn set_cpuid2(&self, cpuid: &[CpuIdEntry]) -> cpu::Result<()> { - let kvm_cpuid = CpuId::from_entries(cpuid) + let cpuid: Vec = + cpuid.iter().map(|e| (*e).into()).collect(); + let kvm_cpuid = ::from_entries(&cpuid) .map_err(|_| cpu::HypervisorCpuError::SetCpuid(anyhow!("failed to create CpuId")))?; self.fd @@ -1359,7 +1360,7 @@ impl cpu::Vcpu for KvmVcpu { .get_cpuid2(num_entries) .map_err(|e| cpu::HypervisorCpuError::GetCpuid(e.into()))?; - let v = kvm_cpuid.as_slice().to_vec(); + let v = kvm_cpuid.as_slice().iter().map(|e| (*e).into()).collect(); Ok(v) } diff --git a/hypervisor/src/kvm/x86_64/mod.rs b/hypervisor/src/kvm/x86_64/mod.rs index 94fd83e61..83befa195 100644 --- a/hypervisor/src/kvm/x86_64/mod.rs +++ b/hypervisor/src/kvm/x86_64/mod.rs @@ -8,7 +8,10 @@ // // -use crate::arch::x86::{DescriptorTable, SegmentRegister, SpecialRegisters, StandardRegisters}; +use crate::arch::x86::{ + CpuIdEntry, DescriptorTable, SegmentRegister, SpecialRegisters, StandardRegisters, + CPUID_FLAG_VALID_INDEX, +}; use crate::kvm::{Cap, Kvm, KvmError, KvmResult}; use serde::{Deserialize, Serialize}; @@ -16,14 +19,13 @@ use serde::{Deserialize, Serialize}; /// Export generically-named wrappers of kvm-bindings for Unix-based platforms /// 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, - kvm_bindings::kvm_vcpu_events as VcpuEvents, + kvm_bindings::kvm_cpuid_entry2, 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, 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, - kvm_bindings::KVM_CPUID_FLAG_SIGNIFCANT_INDEX as CPUID_FLAG_VALID_INDEX, + kvm_bindings::KVM_CPUID_FLAG_SIGNIFCANT_INDEX, }; /// @@ -221,3 +223,42 @@ impl From for SpecialRegisters { } } } + +impl From for kvm_cpuid_entry2 { + fn from(e: CpuIdEntry) -> Self { + let flags = if e.flags & CPUID_FLAG_VALID_INDEX != 0 { + KVM_CPUID_FLAG_SIGNIFCANT_INDEX + } else { + 0 + }; + Self { + function: e.function, + index: e.index, + flags, + eax: e.eax, + ebx: e.ebx, + ecx: e.ecx, + edx: e.edx, + ..Default::default() + } + } +} + +impl From for CpuIdEntry { + fn from(e: kvm_cpuid_entry2) -> Self { + let flags = if e.flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX != 0 { + CPUID_FLAG_VALID_INDEX + } else { + 0 + }; + Self { + function: e.function, + index: e.index, + flags, + eax: e.eax, + ebx: e.ebx, + ecx: e.ecx, + edx: e.edx, + } + } +} diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 01ac8d210..f9571189f 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::{SpecialRegisters, StandardRegisters}; +use crate::arch::x86::{CpuIdEntry, SpecialRegisters, StandardRegisters}; const DIRTY_BITMAP_CLEAR_DIRTY: u64 = 0x4; const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8; diff --git a/hypervisor/src/mshv/x86_64/mod.rs b/hypervisor/src/mshv/x86_64/mod.rs index 7992c35fe..19f53ca8b 100644 --- a/hypervisor/src/mshv/x86_64/mod.rs +++ b/hypervisor/src/mshv/x86_64/mod.rs @@ -7,7 +7,9 @@ // Copyright 2018-2019 CrowdStrike, Inc. // // -use crate::arch::x86::{DescriptorTable, SegmentRegister, SpecialRegisters, StandardRegisters}; +use crate::arch::x86::{ + CpuIdEntry, DescriptorTable, SegmentRegister, SpecialRegisters, StandardRegisters, +}; use serde::{Deserialize, Serialize}; use std::fmt; @@ -15,9 +17,8 @@ use std::fmt; /// Export generically-named wrappers of mshv_bindings for Unix-based platforms /// pub use { - mshv_bindings::hv_cpuid_entry as CpuIdEntry, - mshv_bindings::mshv_user_mem_region as MemoryRegion, mshv_bindings::msr_entry as MsrEntry, - mshv_bindings::CpuId, mshv_bindings::DebugRegisters, + mshv_bindings::hv_cpuid_entry, mshv_bindings::mshv_user_mem_region as MemoryRegion, + mshv_bindings::msr_entry as MsrEntry, mshv_bindings::CpuId, mshv_bindings::DebugRegisters, mshv_bindings::FloatingPointUnit as FpuState, mshv_bindings::LapicState, mshv_bindings::MiscRegs as MiscRegisters, mshv_bindings::MsrList, mshv_bindings::Msrs as MsrEntries, mshv_bindings::Msrs, @@ -28,8 +29,6 @@ pub use { mshv_bindings::Xcrs as ExtendedControlRegisters, }; -pub const CPUID_FLAG_VALID_INDEX: u32 = 0; - #[derive(Clone, Serialize, Deserialize)] pub struct VcpuMshvState { pub msrs: MsrEntries, @@ -224,3 +223,32 @@ impl From for SpecialRegisters { } } } + +impl From for hv_cpuid_entry { + fn from(e: CpuIdEntry) -> Self { + Self { + function: e.function, + index: e.index, + flags: e.flags, + eax: e.eax, + ebx: e.ebx, + ecx: e.ecx, + edx: e.edx, + ..Default::default() + } + } +} + +impl From for CpuIdEntry { + fn from(e: hv_cpuid_entry) -> Self { + Self { + function: e.function, + index: e.index, + flags: e.flags, + eax: e.eax, + ebx: e.ebx, + ecx: e.ecx, + edx: e.edx, + } + } +} diff --git a/hypervisor/src/vm.rs b/hypervisor/src/vm.rs index 7c9e53e3c..ae2954a44 100644 --- a/hypervisor/src/vm.rs +++ b/hypervisor/src/vm.rs @@ -12,10 +12,10 @@ use crate::aarch64::VcpuInit; #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::gic::Vgic; +#[cfg(feature = "tdx")] +use crate::arch::x86::CpuIdEntry; use crate::cpu::Vcpu; use crate::device::Device; -#[cfg(feature = "tdx")] -use crate::x86_64::CpuIdEntry; #[cfg(target_arch = "x86_64")] use crate::ClockData; use crate::CreateDevice; diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 5addb365e..c0aa1f9f5 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -36,14 +36,14 @@ use devices::interrupt_controller::InterruptController; use gdbstub_arch::x86::reg::{X86SegmentRegs, X86_64CoreRegs}; #[cfg(feature = "guest_debug")] use hypervisor::arch::x86::msr_index; +#[cfg(target_arch = "x86_64")] +use hypervisor::arch::x86::CpuIdEntry; #[cfg(all(target_arch = "x86_64", feature = "gdb"))] 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::CpuIdEntry; #[cfg(feature = "guest_debug")] use hypervisor::x86_64::{MsrEntries, MsrEntry}; use hypervisor::{CpuState, HypervisorCpuError, VmExit, VmOps}; diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 621530bfb..8d415afbe 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -355,7 +355,7 @@ pub fn start_vmm_thread( struct VmMigrationConfig { vm_config: Arc>, #[cfg(all(feature = "kvm", target_arch = "x86_64"))] - common_cpuid: Vec, + common_cpuid: Vec, memory_manager_data: MemoryManagerSnapshotData, } @@ -1593,7 +1593,7 @@ impl Vmm { fn vm_check_cpuid_compatibility( &self, src_vm_config: &Arc>, - src_vm_cpuid: &[hypervisor::x86_64::CpuIdEntry], + src_vm_cpuid: &[hypervisor::arch::x86::CpuIdEntry], ) -> result::Result<(), MigratableError> { // We check the `CPUID` compatibility of between the source vm and destination, which is // mostly about feature compatibility and "topology/sgx" leaves are not relevant. diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 26a7f7214..28d37cd49 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -2618,7 +2618,7 @@ pub struct VmSnapshot { #[cfg(all(feature = "kvm", target_arch = "x86_64"))] pub clock: Option, #[cfg(all(feature = "kvm", target_arch = "x86_64"))] - pub common_cpuid: Vec, + pub common_cpuid: Vec, } pub const VM_SNAPSHOT_ID: &str = "vm";