1683210d6SMuminul Islam // Copyright © 2019 Intel Corporation 2683210d6SMuminul Islam // 372ae1577SMuminul Islam // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause 4683210d6SMuminul Islam // 5683210d6SMuminul Islam // Copyright © 2020, Microsoft Corporation 6683210d6SMuminul Islam // 7683210d6SMuminul Islam // Copyright 2018-2019 CrowdStrike, Inc. 8683210d6SMuminul Islam // 9683210d6SMuminul Islam // 1008135fa0SWei Liu #[cfg(target_arch = "x86_64")] 1188a9f799SRob Bradford use std::arch::x86_64; 1288a9f799SRob Bradford use std::sync::Arc; 1388a9f799SRob Bradford 1488a9f799SRob Bradford use thiserror::Error; 1588a9f799SRob Bradford 1688a9f799SRob Bradford #[cfg(target_arch = "x86_64")] 1708135fa0SWei Liu use crate::arch::x86::CpuIdEntry; 187df80220SAnatol Belski #[cfg(target_arch = "x86_64")] 197df80220SAnatol Belski use crate::cpu::CpuVendor; 20218be264SRob Bradford #[cfg(feature = "tdx")] 21218be264SRob Bradford use crate::kvm::TdxCapabilities; 22683210d6SMuminul Islam use crate::vm::Vm; 239fc3379eSWei Liu use crate::HypervisorType; 24683210d6SMuminul Islam 25683210d6SMuminul Islam #[derive(Error, Debug)] 26683210d6SMuminul Islam pub enum HypervisorError { 27683210d6SMuminul Islam /// 28aa66526eSWei Liu /// Hypervisor availability check error 29aa66526eSWei Liu /// 30*72c81783SPhilipp Schuster #[error("Failed to check availability of the hypervisor")] 31aa66526eSWei Liu HypervisorAvailableCheck(#[source] anyhow::Error), 32aa66526eSWei Liu /// 3323c46b16SMuminul Islam /// hypervisor creation error 3423c46b16SMuminul Islam /// 35*72c81783SPhilipp Schuster #[error("Failed to create the hypervisor")] 3623c46b16SMuminul Islam HypervisorCreate(#[source] anyhow::Error), 3723c46b16SMuminul Islam /// 38683210d6SMuminul Islam /// Vm creation failure 39683210d6SMuminul Islam /// 40*72c81783SPhilipp Schuster #[error("Failed to create Vm")] 41683210d6SMuminul Islam VmCreate(#[source] anyhow::Error), 42683210d6SMuminul Islam /// 43683210d6SMuminul Islam /// Vm setup failure 44683210d6SMuminul Islam /// 45*72c81783SPhilipp Schuster #[error("Failed to setup Vm")] 46683210d6SMuminul Islam VmSetup(#[source] anyhow::Error), 47683210d6SMuminul Islam /// 48683210d6SMuminul Islam /// API version error 49683210d6SMuminul Islam /// 50*72c81783SPhilipp Schuster #[error("Failed to get API Version")] 51683210d6SMuminul Islam GetApiVersion(#[source] anyhow::Error), 52683210d6SMuminul Islam /// 53683210d6SMuminul Islam /// CpuId error 54683210d6SMuminul Islam /// 55*72c81783SPhilipp Schuster #[error("Failed to get cpuid")] 56683210d6SMuminul Islam GetCpuId(#[source] anyhow::Error), 5749b4fba2SSebastien Boeuf /// 5849b4fba2SSebastien Boeuf /// Failed to retrieve list of MSRs. 5949b4fba2SSebastien Boeuf /// 60*72c81783SPhilipp Schuster #[error("Failed to get the list of supported MSRs")] 6149b4fba2SSebastien Boeuf GetMsrList(#[source] anyhow::Error), 62d73971e4SWei Liu /// 63d73971e4SWei Liu /// API version is not compatible 64d73971e4SWei Liu /// 65d73971e4SWei Liu #[error("Incompatible API version")] 66d73971e4SWei Liu IncompatibleApiVersion, 6784454f14SRob Bradford /// 6884454f14SRob Bradford /// Checking extensions failed 6984454f14SRob Bradford /// 70*72c81783SPhilipp Schuster #[error("Checking extensions")] 7184454f14SRob Bradford CheckExtensions(#[source] anyhow::Error), 72b0077f0bSSebastien Boeuf /// 73b0077f0bSSebastien Boeuf /// Failed to retrieve TDX capabilities 74b0077f0bSSebastien Boeuf /// 75*72c81783SPhilipp Schuster #[error("Failed to retrieve TDX capabilities")] 76b0077f0bSSebastien Boeuf TdxCapabilities(#[source] anyhow::Error), 77ada85f68SJinank Jain /// 78ada85f68SJinank Jain /// Failed to set partition property 79ada85f68SJinank Jain /// 80*72c81783SPhilipp Schuster #[error("Failed to set partition property")] 81ada85f68SJinank Jain SetPartitionProperty(#[source] anyhow::Error), 827df80220SAnatol Belski /// 837df80220SAnatol Belski /// Running on an unsupported CPU 847df80220SAnatol Belski /// 85*72c81783SPhilipp Schuster #[error("Unsupported CPU")] 867df80220SAnatol Belski UnsupportedCpu(#[source] anyhow::Error), 87200cba0eSJinank Jain /// 88200cba0eSJinank Jain /// Launching a VM with unsupported VM Type 89200cba0eSJinank Jain /// 90200cba0eSJinank Jain #[error("Unsupported VmType")] 91200cba0eSJinank Jain UnsupportedVmType(), 92683210d6SMuminul Islam } 93683210d6SMuminul Islam 94683210d6SMuminul Islam /// 95683210d6SMuminul Islam /// Result type for returning from a function 96683210d6SMuminul Islam /// 97683210d6SMuminul Islam pub type Result<T> = std::result::Result<T, HypervisorError>; 98683210d6SMuminul Islam 99683210d6SMuminul Islam /// 100683210d6SMuminul Islam /// Trait to represent a Hypervisor 101683210d6SMuminul Islam /// 102683210d6SMuminul Islam /// This crate provides a hypervisor-agnostic interfaces 103683210d6SMuminul Islam /// 104683210d6SMuminul Islam pub trait Hypervisor: Send + Sync { 105683210d6SMuminul Islam /// 1069fc3379eSWei Liu /// Returns the type of the hypervisor 1079fc3379eSWei Liu /// hypervisor_type(&self) -> HypervisorType1089fc3379eSWei Liu fn hypervisor_type(&self) -> HypervisorType; 1099fc3379eSWei Liu /// 110683210d6SMuminul Islam /// Create a Vm using the underlying hypervisor 111683210d6SMuminul Islam /// Return a hypervisor-agnostic Vm trait object 112683210d6SMuminul Islam /// create_vm(&self) -> Result<Arc<dyn Vm>>113683210d6SMuminul Islam fn create_vm(&self) -> Result<Arc<dyn Vm>>; 114683210d6SMuminul Islam /// 1151c54fc3aSRob Bradford /// Create a Vm of a specific type using the underlying hypervisor 1161c54fc3aSRob Bradford /// Return a hypervisor-agnostic Vm trait object 1171c54fc3aSRob Bradford /// create_vm_with_type(&self, _vm_type: u64) -> Result<Arc<dyn Vm>>118a335cbb8SRob Bradford fn create_vm_with_type(&self, _vm_type: u64) -> Result<Arc<dyn Vm>> { 119a335cbb8SRob Bradford unreachable!() 120a335cbb8SRob Bradford } 1214054a49eSMuminul Islam /// 1224054a49eSMuminul Islam /// Create a Vm of a specific type using the underlying hypervisor, passing memory size 1234054a49eSMuminul Islam /// Return a hypervisor-agnostic Vm trait object 1244054a49eSMuminul Islam /// create_vm_with_type_and_memory( &self, _vm_type: u64, #[cfg(feature = "sev_snp")] _mem_size: u64, ) -> Result<Arc<dyn Vm>>1254054a49eSMuminul Islam fn create_vm_with_type_and_memory( 1264054a49eSMuminul Islam &self, 1274054a49eSMuminul Islam _vm_type: u64, 1284054a49eSMuminul Islam #[cfg(feature = "sev_snp")] _mem_size: u64, 1294054a49eSMuminul Islam ) -> Result<Arc<dyn Vm>> { 1304054a49eSMuminul Islam unreachable!() 1314054a49eSMuminul Islam } 132683210d6SMuminul Islam #[cfg(target_arch = "x86_64")] 133683210d6SMuminul Islam /// 134683210d6SMuminul Islam /// Get the supported CpuID 135683210d6SMuminul Islam /// get_supported_cpuid(&self) -> Result<Vec<CpuIdEntry>>136de3ca970SWei Liu fn get_supported_cpuid(&self) -> Result<Vec<CpuIdEntry>>; 137683210d6SMuminul Islam /// 138683210d6SMuminul Islam /// Check particular extensions if any 139683210d6SMuminul Islam /// check_required_extensions(&self) -> Result<()>1400cf9218dSRob Bradford fn check_required_extensions(&self) -> Result<()> { 1410cf9218dSRob Bradford Ok(()) 1420cf9218dSRob Bradford } 143805cb303SHenry Wang #[cfg(target_arch = "aarch64")] 144805cb303SHenry Wang /// 145223b1f6cSMichael Zhao /// Retrieve AArch64 host maximum IPA size supported by KVM 146805cb303SHenry Wang /// get_host_ipa_limit(&self) -> i32147805cb303SHenry Wang fn get_host_ipa_limit(&self) -> i32; 148b0077f0bSSebastien Boeuf /// 149b0077f0bSSebastien Boeuf /// Retrieve TDX capabilities 150b0077f0bSSebastien Boeuf /// 151b0077f0bSSebastien Boeuf #[cfg(feature = "tdx")] tdx_capabilities(&self) -> Result<TdxCapabilities>152b8503b5fSRob Bradford fn tdx_capabilities(&self) -> Result<TdxCapabilities> { 153b8503b5fSRob Bradford unimplemented!() 154b8503b5fSRob Bradford } 155223b1f6cSMichael Zhao /// 156223b1f6cSMichael Zhao /// Get the number of supported hardware breakpoints 157223b1f6cSMichael Zhao /// get_guest_debug_hw_bps(&self) -> usize158223b1f6cSMichael Zhao fn get_guest_debug_hw_bps(&self) -> usize { 159223b1f6cSMichael Zhao unimplemented!() 160223b1f6cSMichael Zhao } 161ceb81517SRob Bradford 162ceb81517SRob Bradford /// Get maximum number of vCPUs get_max_vcpus(&self) -> u32163ceb81517SRob Bradford fn get_max_vcpus(&self) -> u32; 1647df80220SAnatol Belski #[cfg(target_arch = "x86_64")] 1657df80220SAnatol Belski /// 1667df80220SAnatol Belski /// Determine CPU vendor 1677df80220SAnatol Belski /// get_cpu_vendor(&self) -> CpuVendor1687df80220SAnatol Belski fn get_cpu_vendor(&self) -> CpuVendor { 1697df80220SAnatol Belski // SAFETY: call cpuid with valid leaves 1707df80220SAnatol Belski unsafe { 1717df80220SAnatol Belski let leaf = x86_64::__cpuid(0x0); 1727df80220SAnatol Belski 1737df80220SAnatol Belski if leaf.ebx == 0x756e_6547 && leaf.ecx == 0x6c65_746e && leaf.edx == 0x4965_6e69 { 1747df80220SAnatol Belski // Vendor string GenuineIntel 1757df80220SAnatol Belski CpuVendor::Intel 1767df80220SAnatol Belski } else if leaf.ebx == 0x6874_7541 && leaf.ecx == 0x444d_4163 && leaf.edx == 0x6974_6e65 1777df80220SAnatol Belski { 1787df80220SAnatol Belski // Vendor string AuthenticAMD 1797df80220SAnatol Belski CpuVendor::AMD 1807df80220SAnatol Belski } else { 1817df80220SAnatol Belski // Not known yet, the corresponding manufacturer manual should contain the 18242e9632cSJosh Soref // necessary info. See also https://wiki.osdev.org/CPUID#CPU_Vendor_ID_String 1837df80220SAnatol Belski CpuVendor::default() 1847df80220SAnatol Belski } 1857df80220SAnatol Belski } 1867df80220SAnatol Belski } 187683210d6SMuminul Islam } 188