1 // Copyright © 2019 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause 4 // 5 // Copyright © 2020, Microsoft Corporation 6 // 7 // Copyright 2018-2019 CrowdStrike, Inc. 8 // 9 // 10 #[cfg(target_arch = "x86_64")] 11 use std::arch::x86_64; 12 use std::sync::Arc; 13 14 use thiserror::Error; 15 16 #[cfg(target_arch = "x86_64")] 17 use crate::arch::x86::CpuIdEntry; 18 #[cfg(target_arch = "x86_64")] 19 use crate::cpu::CpuVendor; 20 #[cfg(feature = "tdx")] 21 use crate::kvm::TdxCapabilities; 22 use crate::vm::Vm; 23 use crate::HypervisorType; 24 25 #[derive(Error, Debug)] 26 pub enum HypervisorError { 27 /// 28 /// Hypervisor availability check error 29 /// 30 #[error("Failed to check availability of the hypervisor: {0}")] 31 HypervisorAvailableCheck(#[source] anyhow::Error), 32 /// 33 /// hypervisor creation error 34 /// 35 #[error("Failed to create the hypervisor: {0}")] 36 HypervisorCreate(#[source] anyhow::Error), 37 /// 38 /// Vm creation failure 39 /// 40 #[error("Failed to create Vm: {0}")] 41 VmCreate(#[source] anyhow::Error), 42 /// 43 /// Vm setup failure 44 /// 45 #[error("Failed to setup Vm: {0}")] 46 VmSetup(#[source] anyhow::Error), 47 /// 48 /// API version error 49 /// 50 #[error("Failed to get API Version: {0}")] 51 GetApiVersion(#[source] anyhow::Error), 52 /// 53 /// CpuId error 54 /// 55 #[error("Failed to get cpuid: {0}")] 56 GetCpuId(#[source] anyhow::Error), 57 /// 58 /// Failed to retrieve list of MSRs. 59 /// 60 #[error("Failed to get the list of supported MSRs: {0}")] 61 GetMsrList(#[source] anyhow::Error), 62 /// 63 /// API version is not compatible 64 /// 65 #[error("Incompatible API version")] 66 IncompatibleApiVersion, 67 /// 68 /// Checking extensions failed 69 /// 70 #[error("Checking extensions:{0}")] 71 CheckExtensions(#[source] anyhow::Error), 72 /// 73 /// Failed to retrieve TDX capabilities 74 /// 75 #[error("Failed to retrieve TDX capabilities:{0}")] 76 TdxCapabilities(#[source] anyhow::Error), 77 /// 78 /// Failed to set partition property 79 /// 80 #[error("Failed to set partition property:{0}")] 81 SetPartitionProperty(#[source] anyhow::Error), 82 /// 83 /// Running on an unsupported CPU 84 /// 85 #[error("Unsupported CPU:{0}")] 86 UnsupportedCpu(#[source] anyhow::Error), 87 /// 88 /// Launching a VM with unsupported VM Type 89 /// 90 #[error("Unsupported VmType")] 91 UnsupportedVmType(), 92 } 93 94 /// 95 /// Result type for returning from a function 96 /// 97 pub type Result<T> = std::result::Result<T, HypervisorError>; 98 99 /// 100 /// Trait to represent a Hypervisor 101 /// 102 /// This crate provides a hypervisor-agnostic interfaces 103 /// 104 pub trait Hypervisor: Send + Sync { 105 /// 106 /// Returns the type of the hypervisor 107 /// 108 fn hypervisor_type(&self) -> HypervisorType; 109 /// 110 /// Create a Vm using the underlying hypervisor 111 /// Return a hypervisor-agnostic Vm trait object 112 /// 113 fn create_vm(&self) -> Result<Arc<dyn Vm>>; 114 /// 115 /// Create a Vm of a specific type using the underlying hypervisor 116 /// Return a hypervisor-agnostic Vm trait object 117 /// 118 fn create_vm_with_type(&self, _vm_type: u64) -> Result<Arc<dyn Vm>> { 119 unreachable!() 120 } 121 /// 122 /// Create a Vm of a specific type using the underlying hypervisor, passing memory size 123 /// Return a hypervisor-agnostic Vm trait object 124 /// 125 fn create_vm_with_type_and_memory( 126 &self, 127 _vm_type: u64, 128 #[cfg(feature = "sev_snp")] _mem_size: u64, 129 ) -> Result<Arc<dyn Vm>> { 130 unreachable!() 131 } 132 #[cfg(target_arch = "x86_64")] 133 /// 134 /// Get the supported CpuID 135 /// 136 fn get_supported_cpuid(&self) -> Result<Vec<CpuIdEntry>>; 137 /// 138 /// Check particular extensions if any 139 /// 140 fn check_required_extensions(&self) -> Result<()> { 141 Ok(()) 142 } 143 #[cfg(target_arch = "aarch64")] 144 /// 145 /// Retrieve AArch64 host maximum IPA size supported by KVM 146 /// 147 fn get_host_ipa_limit(&self) -> i32; 148 /// 149 /// Retrieve TDX capabilities 150 /// 151 #[cfg(feature = "tdx")] 152 fn tdx_capabilities(&self) -> Result<TdxCapabilities> { 153 unimplemented!() 154 } 155 /// 156 /// Get the number of supported hardware breakpoints 157 /// 158 fn get_guest_debug_hw_bps(&self) -> usize { 159 unimplemented!() 160 } 161 162 /// Get maximum number of vCPUs 163 fn get_max_vcpus(&self) -> u32; 164 #[cfg(target_arch = "x86_64")] 165 /// 166 /// Determine CPU vendor 167 /// 168 fn get_cpu_vendor(&self) -> CpuVendor { 169 // SAFETY: call cpuid with valid leaves 170 unsafe { 171 let leaf = x86_64::__cpuid(0x0); 172 173 if leaf.ebx == 0x756e_6547 && leaf.ecx == 0x6c65_746e && leaf.edx == 0x4965_6e69 { 174 // Vendor string GenuineIntel 175 CpuVendor::Intel 176 } else if leaf.ebx == 0x6874_7541 && leaf.ecx == 0x444d_4163 && leaf.edx == 0x6974_6e65 177 { 178 // Vendor string AuthenticAMD 179 CpuVendor::AMD 180 } else { 181 // Not known yet, the corresponding manufacturer manual should contain the 182 // necessary info. See also https://wiki.osdev.org/CPUID#CPU_Vendor_ID_String 183 CpuVendor::default() 184 } 185 } 186 } 187 } 188