xref: /cloud-hypervisor/hypervisor/src/hypervisor.rs (revision 19d36c765fdf00be749d95b3e61028bc302d6d73)
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     #[cfg(target_arch = "x86_64")]
122     ///
123     /// Get the supported CpuID
124     ///
125     fn get_supported_cpuid(&self) -> Result<Vec<CpuIdEntry>>;
126     ///
127     /// Check particular extensions if any
128     ///
129     fn check_required_extensions(&self) -> Result<()> {
130         Ok(())
131     }
132     #[cfg(target_arch = "aarch64")]
133     ///
134     /// Retrieve AArch64 host maximum IPA size supported by KVM
135     ///
136     fn get_host_ipa_limit(&self) -> i32;
137     ///
138     /// Retrieve TDX capabilities
139     ///
140     #[cfg(feature = "tdx")]
141     fn tdx_capabilities(&self) -> Result<TdxCapabilities> {
142         unimplemented!()
143     }
144     ///
145     /// Get the number of supported hardware breakpoints
146     ///
147     fn get_guest_debug_hw_bps(&self) -> usize {
148         unimplemented!()
149     }
150 
151     /// Get maximum number of vCPUs
152     fn get_max_vcpus(&self) -> u32;
153     #[cfg(target_arch = "x86_64")]
154     ///
155     /// Determine CPU vendor
156     ///
157     fn get_cpu_vendor(&self) -> CpuVendor {
158         // SAFETY: call cpuid with valid leaves
159         unsafe {
160             let leaf = x86_64::__cpuid(0x0);
161 
162             if leaf.ebx == 0x756e_6547 && leaf.ecx == 0x6c65_746e && leaf.edx == 0x4965_6e69 {
163                 // Vendor string GenuineIntel
164                 CpuVendor::Intel
165             } else if leaf.ebx == 0x6874_7541 && leaf.ecx == 0x444d_4163 && leaf.edx == 0x6974_6e65
166             {
167                 // Vendor string AuthenticAMD
168                 CpuVendor::AMD
169             } else {
170                 // Not known yet, the corresponding manufacturer manual should contain the
171                 // necessary info. See also https://wiki.osdev.org/CPUID#CPU_Vendor_ID_String
172                 CpuVendor::default()
173             }
174         }
175     }
176 }
177