diff --git a/hypervisor/src/cpu.rs b/hypervisor/src/cpu.rs index 41fbe08bc..9c7aa91f4 100644 --- a/hypervisor/src/cpu.rs +++ b/hypervisor/src/cpu.rs @@ -14,14 +14,14 @@ use thiserror::Error; #[cfg(not(target_arch = "riscv64"))] use vm_memory::GuestAddress; -#[cfg(target_arch = "aarch64")] -use crate::aarch64::VcpuInit; #[cfg(target_arch = "x86_64")] use crate::arch::x86::{CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters}; #[cfg(feature = "tdx")] use crate::kvm::{TdxExitDetails, TdxExitStatus}; #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] use crate::RegList; +#[cfg(target_arch = "aarch64")] +use crate::VcpuInit; use crate::{CpuState, MpState, StandardRegisters}; #[cfg(target_arch = "x86_64")] diff --git a/hypervisor/src/kvm/aarch64/mod.rs b/hypervisor/src/kvm/aarch64/mod.rs index f39cf24e8..0bef5e07d 100644 --- a/hypervisor/src/kvm/aarch64/mod.rs +++ b/hypervisor/src/kvm/aarch64/mod.rs @@ -10,7 +10,6 @@ pub mod gic; -pub use kvm_bindings::kvm_vcpu_init as VcpuInit; use kvm_bindings::{ kvm_mp_state, kvm_one_reg, kvm_regs, KVM_REG_ARM_COPROC_MASK, KVM_REG_ARM_CORE, KVM_REG_SIZE_MASK, KVM_REG_SIZE_U32, KVM_REG_SIZE_U64, diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 23d848ac9..ccc70d5a3 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -30,8 +30,7 @@ use vmm_sys_util::eventfd::EventFd; use crate::aarch64::gic::KvmGicV3Its; #[cfg(target_arch = "aarch64")] pub use crate::aarch64::{ - check_required_kvm_extensions, gic::Gicv3ItsState as GicState, is_system_register, VcpuInit, - VcpuKvmState, + check_required_kvm_extensions, gic::Gicv3ItsState as GicState, is_system_register, VcpuKvmState, }; #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::gic::{Vgic, VgicConfig}; @@ -369,6 +368,25 @@ impl From for kvm_bindings::kvm_one_reg { } } +#[cfg(target_arch = "aarch64")] +impl From for crate::VcpuInit { + fn from(s: kvm_bindings::kvm_vcpu_init) -> Self { + crate::VcpuInit::Kvm(s) + } +} + +#[cfg(target_arch = "aarch64")] +impl From for kvm_bindings::kvm_vcpu_init { + fn from(e: crate::VcpuInit) -> Self { + match e { + crate::VcpuInit::Kvm(e) => e, + /* Needed in case other hypervisors are enabled */ + #[allow(unreachable_patterns)] + _ => panic!("VcpuInit is not valid"), + } + } +} + #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] impl From for crate::RegList { fn from(s: kvm_bindings::RegList) -> Self { @@ -789,10 +807,13 @@ impl vm::Vm for KvmVm { /// Returns the preferred CPU target type which can be emulated by KVM on underlying host. /// #[cfg(target_arch = "aarch64")] - fn get_preferred_target(&self, kvi: &mut VcpuInit) -> vm::Result<()> { + fn get_preferred_target(&self, kvi: &mut crate::VcpuInit) -> vm::Result<()> { + let mut kvm_kvi: kvm_bindings::kvm_vcpu_init = (*kvi).into(); self.fd - .get_preferred_target(kvi) - .map_err(|e| vm::HypervisorVmError::GetPreferredTarget(e.into())) + .get_preferred_target(&mut kvm_kvi) + .map_err(|e| vm::HypervisorVmError::GetPreferredTarget(e.into()))?; + *kvi = kvm_kvi.into(); + Ok(()) } #[cfg(target_arch = "x86_64")] @@ -2637,11 +2658,12 @@ impl cpu::Vcpu for KvmVcpu { } #[cfg(target_arch = "aarch64")] - fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> { + fn vcpu_init(&self, kvi: &crate::VcpuInit) -> cpu::Result<()> { + let kvm_kvi: kvm_bindings::kvm_vcpu_init = (*kvi).into(); self.fd .lock() .unwrap() - .vcpu_init(kvi) + .vcpu_init(&kvm_kvi) .map_err(|e| cpu::HypervisorCpuError::VcpuInit(e.into())) } diff --git a/hypervisor/src/lib.rs b/hypervisor/src/lib.rs index 756cd8fe5..72fa0c508 100644 --- a/hypervisor/src/lib.rs +++ b/hypervisor/src/lib.rs @@ -196,6 +196,12 @@ pub enum IrqRoutingEntry { Mshv(mshv_bindings::mshv_user_irq_entry), } +#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)] +pub enum VcpuInit { + #[cfg(all(feature = "kvm", target_arch = "aarch64"))] + Kvm(kvm_bindings::kvm_vcpu_init), +} + #[derive(Debug, Clone, PartialEq)] pub enum RegList { #[cfg(all(feature = "kvm", any(target_arch = "aarch64", target_arch = "riscv64")))] diff --git a/hypervisor/src/vm.rs b/hypervisor/src/vm.rs index b6f11c9ff..3ce209942 100644 --- a/hypervisor/src/vm.rs +++ b/hypervisor/src/vm.rs @@ -22,8 +22,6 @@ use igvm_defs::IGVM_VHS_SNP_ID_BLOCK; use thiserror::Error; use vmm_sys_util::eventfd::EventFd; -#[cfg(target_arch = "aarch64")] -use crate::aarch64::VcpuInit; #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::gic::{Vgic, VgicConfig}; #[cfg(target_arch = "riscv64")] @@ -351,7 +349,7 @@ pub trait Vm: Send + Sync + Any { fn remove_user_memory_region(&self, user_memory_region: UserMemoryRegion) -> Result<()>; /// Returns the preferred CPU target type which can be emulated by KVM on underlying host. #[cfg(target_arch = "aarch64")] - fn get_preferred_target(&self, kvi: &mut VcpuInit) -> Result<()>; + fn get_preferred_target(&self, kvi: &mut crate::VcpuInit) -> Result<()>; /// Enable split Irq capability #[cfg(target_arch = "x86_64")] fn enable_split_irq(&self) -> Result<()>; diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 20dbb467a..3c7f4ab5b 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -427,7 +427,7 @@ impl Vcpu { let sve_supported = is_aarch64_feature_detected!("sve") || is_aarch64_feature_detected!("sve2"); // This reads back the kernel's preferred target type. - vm.get_preferred_target(&mut kvi) + vm.get_preferred_target(&mut kvi.into()) .map_err(Error::VcpuArmPreferredTarget)?; // We already checked that the capability is supported. kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_PSCI_0_2; @@ -454,7 +454,9 @@ impl Vcpu { if self.id > 0 { kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_POWER_OFF; } - self.vcpu.vcpu_init(&kvi).map_err(Error::VcpuArmInit)?; + self.vcpu + .vcpu_init(&kvi.into()) + .map_err(Error::VcpuArmInit)?; if sve_supported { self.vcpu .vcpu_finalize(kvm_bindings::KVM_ARM_VCPU_SVE as i32) @@ -2965,8 +2967,8 @@ mod tests { vcpu.setup_regs(0, 0x0, layout::FDT_START.0).unwrap_err(); let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default(); - vm.get_preferred_target(&mut kvi).unwrap(); - vcpu.vcpu_init(&kvi).unwrap(); + vm.get_preferred_target(&mut kvi.into()).unwrap(); + vcpu.vcpu_init(&kvi.into()).unwrap(); vcpu.setup_regs(0, 0x0, layout::FDT_START.0).unwrap(); } @@ -2977,12 +2979,12 @@ mod tests { let vm = hv.create_vm().unwrap(); let vcpu = vm.create_vcpu(0, None).unwrap(); let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default(); - vm.get_preferred_target(&mut kvi).unwrap(); + vm.get_preferred_target(&mut kvi.into()).unwrap(); // Must fail when vcpu is not initialized yet. vcpu.get_sys_reg(regs::MPIDR_EL1).unwrap_err(); - vcpu.vcpu_init(&kvi).unwrap(); + vcpu.vcpu_init(&kvi.into()).unwrap(); assert_eq!(vcpu.get_sys_reg(regs::MPIDR_EL1).unwrap(), 0x80000000); } @@ -3001,7 +3003,7 @@ mod tests { let vm = hv.create_vm().unwrap(); let vcpu = vm.create_vcpu(0, None).unwrap(); let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default(); - vm.get_preferred_target(&mut kvi).unwrap(); + vm.get_preferred_target(&mut kvi.into()).unwrap(); // Must fail when vcpu is not initialized yet. assert_eq!( @@ -3015,7 +3017,7 @@ mod tests { "Failed to set aarch64 core register: Exec format error (os error 8)" ); - vcpu.vcpu_init(&kvi).unwrap(); + vcpu.vcpu_init(&kvi.into()).unwrap(); state = vcpu.get_regs().unwrap(); assert_eq!(state.get_pstate(), 0x3C5); @@ -3028,7 +3030,7 @@ mod tests { let vm = hv.create_vm().unwrap(); let vcpu = vm.create_vcpu(0, None).unwrap(); let mut kvi: kvm_vcpu_init = kvm_vcpu_init::default(); - vm.get_preferred_target(&mut kvi).unwrap(); + vm.get_preferred_target(&mut kvi.into()).unwrap(); let state = vcpu.get_mp_state().unwrap(); vcpu.set_mp_state(state).unwrap();