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