xref: /aosp_15_r20/external/crosvm/hypervisor/src/whpx.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker //! Implementation for WHPX hypervisor aka Windows Hyper-V platform.
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use core::ffi::c_void;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::arch::x86_64::__cpuid_count;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
11*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
12*bb4ee6a4SAndroid Build Coastguard Worker use base::Error;
13*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
14*bb4ee6a4SAndroid Build Coastguard Worker use once_cell::sync::Lazy;
15*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error as ThisError;
16*bb4ee6a4SAndroid Build Coastguard Worker use winapi::shared::winerror::S_OK;
17*bb4ee6a4SAndroid Build Coastguard Worker 
18*bb4ee6a4SAndroid Build Coastguard Worker use crate::CpuId;
19*bb4ee6a4SAndroid Build Coastguard Worker use crate::CpuIdEntry;
20*bb4ee6a4SAndroid Build Coastguard Worker use crate::Hypervisor;
21*bb4ee6a4SAndroid Build Coastguard Worker use crate::HypervisorCap;
22*bb4ee6a4SAndroid Build Coastguard Worker use crate::HypervisorX86_64;
23*bb4ee6a4SAndroid Build Coastguard Worker 
24*bb4ee6a4SAndroid Build Coastguard Worker #[macro_export]
25*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! check_whpx {
26*bb4ee6a4SAndroid Build Coastguard Worker     ($x: expr) => {{
27*bb4ee6a4SAndroid Build Coastguard Worker         match $x {
28*bb4ee6a4SAndroid Build Coastguard Worker             S_OK => Ok(()),
29*bb4ee6a4SAndroid Build Coastguard Worker             _ => Err(Error::new($x)),
30*bb4ee6a4SAndroid Build Coastguard Worker         }
31*bb4ee6a4SAndroid Build Coastguard Worker     }};
32*bb4ee6a4SAndroid Build Coastguard Worker }
33*bb4ee6a4SAndroid Build Coastguard Worker 
34*bb4ee6a4SAndroid Build Coastguard Worker mod types;
35*bb4ee6a4SAndroid Build Coastguard Worker mod vcpu;
36*bb4ee6a4SAndroid Build Coastguard Worker pub use vcpu::*;
37*bb4ee6a4SAndroid Build Coastguard Worker mod vm;
38*bb4ee6a4SAndroid Build Coastguard Worker pub use vm::*;
39*bb4ee6a4SAndroid Build Coastguard Worker pub mod whpx_sys;
40*bb4ee6a4SAndroid Build Coastguard Worker pub use whpx_sys::*;
41*bb4ee6a4SAndroid Build Coastguard Worker 
42*bb4ee6a4SAndroid Build Coastguard Worker // used by both the vm and vcpu
43*bb4ee6a4SAndroid Build Coastguard Worker struct SafePartition {
44*bb4ee6a4SAndroid Build Coastguard Worker     partition: WHV_PARTITION_HANDLE,
45*bb4ee6a4SAndroid Build Coastguard Worker }
46*bb4ee6a4SAndroid Build Coastguard Worker 
47*bb4ee6a4SAndroid Build Coastguard Worker // we can send the partition over safely even though it is void*, it can be sent
48*bb4ee6a4SAndroid Build Coastguard Worker // in another thread safely.
49*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Send for SafePartition {}
50*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Sync for SafePartition {}
51*bb4ee6a4SAndroid Build Coastguard Worker 
52*bb4ee6a4SAndroid Build Coastguard Worker impl SafePartition {
new() -> WhpxResult<SafePartition>53*bb4ee6a4SAndroid Build Coastguard Worker     fn new() -> WhpxResult<SafePartition> {
54*bb4ee6a4SAndroid Build Coastguard Worker         let mut partition_handle: WHV_PARTITION_HANDLE = std::ptr::null_mut();
55*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we pass in the partition handle for the system to fill in.
56*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe { WHvCreatePartition(&mut partition_handle) })
57*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(WhpxError::CreatePartitionError)?;
58*bb4ee6a4SAndroid Build Coastguard Worker 
59*bb4ee6a4SAndroid Build Coastguard Worker         Ok(SafePartition {
60*bb4ee6a4SAndroid Build Coastguard Worker             partition: partition_handle,
61*bb4ee6a4SAndroid Build Coastguard Worker         })
62*bb4ee6a4SAndroid Build Coastguard Worker     }
63*bb4ee6a4SAndroid Build Coastguard Worker }
64*bb4ee6a4SAndroid Build Coastguard Worker 
65*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for SafePartition {
drop(&mut self)66*bb4ee6a4SAndroid Build Coastguard Worker     fn drop(&mut self) {
67*bb4ee6a4SAndroid Build Coastguard Worker         // safe because we own this partition
68*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe { WHvDeletePartition(self.partition) }).unwrap();
69*bb4ee6a4SAndroid Build Coastguard Worker     }
70*bb4ee6a4SAndroid Build Coastguard Worker }
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
73*bb4ee6a4SAndroid Build Coastguard Worker pub struct Whpx {
74*bb4ee6a4SAndroid Build Coastguard Worker     // there is no general whpx object, the vm contains the partition.
75*bb4ee6a4SAndroid Build Coastguard Worker }
76*bb4ee6a4SAndroid Build Coastguard Worker 
77*bb4ee6a4SAndroid Build Coastguard Worker /// Enum of WHPX Features. Similar to WHV_CAPABILITY_FEATURES but allows us to avoid making the
78*bb4ee6a4SAndroid Build Coastguard Worker /// whpx_sys crate pub.
79*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
80*bb4ee6a4SAndroid Build Coastguard Worker pub enum WhpxFeature {
81*bb4ee6a4SAndroid Build Coastguard Worker     PartialUnmap = 0x0,
82*bb4ee6a4SAndroid Build Coastguard Worker     LocalApicEmulation = 0x1,
83*bb4ee6a4SAndroid Build Coastguard Worker     Xsave = 0x2,
84*bb4ee6a4SAndroid Build Coastguard Worker     DirtyPageTracking = 0x4,
85*bb4ee6a4SAndroid Build Coastguard Worker     SpeculationControl = 0x8,
86*bb4ee6a4SAndroid Build Coastguard Worker     ApicRemoteRead = 0x10,
87*bb4ee6a4SAndroid Build Coastguard Worker     IdleSuspend = 0x20,
88*bb4ee6a4SAndroid Build Coastguard Worker }
89*bb4ee6a4SAndroid Build Coastguard Worker 
90*bb4ee6a4SAndroid Build Coastguard Worker #[derive(ThisError, Debug, Clone, Copy)]
91*bb4ee6a4SAndroid Build Coastguard Worker pub enum WhpxError {
92*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create WHPX partition: {0}")]
93*bb4ee6a4SAndroid Build Coastguard Worker     CreatePartitionError(base::Error),
94*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to get WHPX capability {0}: {1}")]
95*bb4ee6a4SAndroid Build Coastguard Worker     GetCapability(WHV_CAPABILITY_CODE, base::Error),
96*bb4ee6a4SAndroid Build Coastguard Worker     #[error("WHPX local apic emulation is not supported on this host")]
97*bb4ee6a4SAndroid Build Coastguard Worker     LocalApicEmulationNotSupported,
98*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to map guest physical address range: {0}")]
99*bb4ee6a4SAndroid Build Coastguard Worker     MapGpaRange(base::Error),
100*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set WHPX partition processor count: {0}")]
101*bb4ee6a4SAndroid Build Coastguard Worker     SetProcessorCount(base::Error),
102*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set WHPX partition cpuid result list: {0}")]
103*bb4ee6a4SAndroid Build Coastguard Worker     SetCpuidResultList(base::Error),
104*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set WHPX partition cpuid exit list: {0}")]
105*bb4ee6a4SAndroid Build Coastguard Worker     SetCpuidExitList(base::Error),
106*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set WHPX partition extended vm exits: {0}")]
107*bb4ee6a4SAndroid Build Coastguard Worker     SetExtendedVmExits(base::Error),
108*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set WHPX partition local apic emulation mode: {0}")]
109*bb4ee6a4SAndroid Build Coastguard Worker     SetLocalApicEmulationMode(base::Error),
110*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to setup WHPX partition: {0}")]
111*bb4ee6a4SAndroid Build Coastguard Worker     SetupPartition(base::Error),
112*bb4ee6a4SAndroid Build Coastguard Worker }
113*bb4ee6a4SAndroid Build Coastguard Worker 
114*bb4ee6a4SAndroid Build Coastguard Worker impl From<WhpxError> for Box<dyn std::error::Error + Send> {
from(e: WhpxError) -> Self115*bb4ee6a4SAndroid Build Coastguard Worker     fn from(e: WhpxError) -> Self {
116*bb4ee6a4SAndroid Build Coastguard Worker         Box::new(e)
117*bb4ee6a4SAndroid Build Coastguard Worker     }
118*bb4ee6a4SAndroid Build Coastguard Worker }
119*bb4ee6a4SAndroid Build Coastguard Worker 
120*bb4ee6a4SAndroid Build Coastguard Worker type WhpxResult<T> = std::result::Result<T, WhpxError>;
121*bb4ee6a4SAndroid Build Coastguard Worker 
122*bb4ee6a4SAndroid Build Coastguard Worker impl Whpx {
new() -> Result<Whpx>123*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> Result<Whpx> {
124*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Whpx {})
125*bb4ee6a4SAndroid Build Coastguard Worker     }
126*bb4ee6a4SAndroid Build Coastguard Worker 
is_enabled() -> bool127*bb4ee6a4SAndroid Build Coastguard Worker     pub fn is_enabled() -> bool {
128*bb4ee6a4SAndroid Build Coastguard Worker         let res = Whpx::get_capability(WHV_CAPABILITY_CODE_WHvCapabilityCodeHypervisorPresent);
129*bb4ee6a4SAndroid Build Coastguard Worker         match res {
130*bb4ee6a4SAndroid Build Coastguard Worker             Ok(cap_code) => {
131*bb4ee6a4SAndroid Build Coastguard Worker                 // safe because we trust the kernel to fill in hypervisor present in the union
132*bb4ee6a4SAndroid Build Coastguard Worker                 unsafe { cap_code.HypervisorPresent > 0 }
133*bb4ee6a4SAndroid Build Coastguard Worker             }
134*bb4ee6a4SAndroid Build Coastguard Worker             _ => {
135*bb4ee6a4SAndroid Build Coastguard Worker                 warn!("error checking if whpx was enabled. Assuming whpx is disabled");
136*bb4ee6a4SAndroid Build Coastguard Worker                 false
137*bb4ee6a4SAndroid Build Coastguard Worker             }
138*bb4ee6a4SAndroid Build Coastguard Worker         }
139*bb4ee6a4SAndroid Build Coastguard Worker     }
140*bb4ee6a4SAndroid Build Coastguard Worker 
get_capability(cap: WHV_CAPABILITY_CODE) -> WhpxResult<WHV_CAPABILITY>141*bb4ee6a4SAndroid Build Coastguard Worker     fn get_capability(cap: WHV_CAPABILITY_CODE) -> WhpxResult<WHV_CAPABILITY> {
142*bb4ee6a4SAndroid Build Coastguard Worker         let mut capability: WHV_CAPABILITY = Default::default();
143*bb4ee6a4SAndroid Build Coastguard Worker         let mut written_size = 0;
144*bb4ee6a4SAndroid Build Coastguard Worker         check_whpx!(unsafe {
145*bb4ee6a4SAndroid Build Coastguard Worker             WHvGetCapability(
146*bb4ee6a4SAndroid Build Coastguard Worker                 cap,
147*bb4ee6a4SAndroid Build Coastguard Worker                 &mut capability as *mut _ as *mut c_void,
148*bb4ee6a4SAndroid Build Coastguard Worker                 std::mem::size_of::<WHV_CAPABILITY>() as u32,
149*bb4ee6a4SAndroid Build Coastguard Worker                 &mut written_size,
150*bb4ee6a4SAndroid Build Coastguard Worker             )
151*bb4ee6a4SAndroid Build Coastguard Worker         })
152*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|e| WhpxError::GetCapability(cap, e))?;
153*bb4ee6a4SAndroid Build Coastguard Worker         Ok(capability)
154*bb4ee6a4SAndroid Build Coastguard Worker     }
155*bb4ee6a4SAndroid Build Coastguard Worker 
check_whpx_feature(feature: WhpxFeature) -> WhpxResult<bool>156*bb4ee6a4SAndroid Build Coastguard Worker     pub fn check_whpx_feature(feature: WhpxFeature) -> WhpxResult<bool> {
157*bb4ee6a4SAndroid Build Coastguard Worker         // use Lazy to cache the results of the get_capability call
158*bb4ee6a4SAndroid Build Coastguard Worker         static FEATURES: Lazy<WhpxResult<WHV_CAPABILITY>> =
159*bb4ee6a4SAndroid Build Coastguard Worker             Lazy::new(|| Whpx::get_capability(WHV_CAPABILITY_CODE_WHvCapabilityCodeFeatures));
160*bb4ee6a4SAndroid Build Coastguard Worker 
161*bb4ee6a4SAndroid Build Coastguard Worker         Ok((unsafe { (*FEATURES)?.Features.AsUINT64 } & feature as u64) != 0)
162*bb4ee6a4SAndroid Build Coastguard Worker     }
163*bb4ee6a4SAndroid Build Coastguard Worker }
164*bb4ee6a4SAndroid Build Coastguard Worker 
165*bb4ee6a4SAndroid Build Coastguard Worker impl Hypervisor for Whpx {
166*bb4ee6a4SAndroid Build Coastguard Worker     /// Makes a shallow clone of this `Hypervisor`.
try_clone(&self) -> Result<Self>167*bb4ee6a4SAndroid Build Coastguard Worker     fn try_clone(&self) -> Result<Self> {
168*bb4ee6a4SAndroid Build Coastguard Worker         Ok(self.clone())
169*bb4ee6a4SAndroid Build Coastguard Worker     }
170*bb4ee6a4SAndroid Build Coastguard Worker 
171*bb4ee6a4SAndroid Build Coastguard Worker     /// Checks if a particular `HypervisorCap` is available.
check_capability(&self, cap: HypervisorCap) -> bool172*bb4ee6a4SAndroid Build Coastguard Worker     fn check_capability(&self, cap: HypervisorCap) -> bool {
173*bb4ee6a4SAndroid Build Coastguard Worker         // whpx supports immediate exit, user memory, and the xcr0 state
174*bb4ee6a4SAndroid Build Coastguard Worker         match cap {
175*bb4ee6a4SAndroid Build Coastguard Worker             HypervisorCap::ImmediateExit => true,
176*bb4ee6a4SAndroid Build Coastguard Worker             HypervisorCap::UserMemory => true,
177*bb4ee6a4SAndroid Build Coastguard Worker             HypervisorCap::Xcrs => {
178*bb4ee6a4SAndroid Build Coastguard Worker                 Whpx::check_whpx_feature(WhpxFeature::Xsave).unwrap_or_else(|e| {
179*bb4ee6a4SAndroid Build Coastguard Worker                     error!(
180*bb4ee6a4SAndroid Build Coastguard Worker                         "failed to check whpx feature {:?}: {}",
181*bb4ee6a4SAndroid Build Coastguard Worker                         WhpxFeature::Xsave,
182*bb4ee6a4SAndroid Build Coastguard Worker                         e
183*bb4ee6a4SAndroid Build Coastguard Worker                     );
184*bb4ee6a4SAndroid Build Coastguard Worker                     false
185*bb4ee6a4SAndroid Build Coastguard Worker                 })
186*bb4ee6a4SAndroid Build Coastguard Worker             }
187*bb4ee6a4SAndroid Build Coastguard Worker             // under whpx, guests rely on this leaf to calibrate their clocksource.
188*bb4ee6a4SAndroid Build Coastguard Worker             HypervisorCap::CalibratedTscLeafRequired => true,
189*bb4ee6a4SAndroid Build Coastguard Worker             _ => false,
190*bb4ee6a4SAndroid Build Coastguard Worker         }
191*bb4ee6a4SAndroid Build Coastguard Worker     }
192*bb4ee6a4SAndroid Build Coastguard Worker }
193*bb4ee6a4SAndroid Build Coastguard Worker 
194*bb4ee6a4SAndroid Build Coastguard Worker /// Build a CpuIdEntry for a given `function`/`index` from the host results for that
195*bb4ee6a4SAndroid Build Coastguard Worker /// `function`/`index`.
cpuid_entry_from_host(function: u32, index: u32) -> CpuIdEntry196*bb4ee6a4SAndroid Build Coastguard Worker fn cpuid_entry_from_host(function: u32, index: u32) -> CpuIdEntry {
197*bb4ee6a4SAndroid Build Coastguard Worker     // Safe because arguments are passed by value
198*bb4ee6a4SAndroid Build Coastguard Worker     let result = unsafe { __cpuid_count(function, index) };
199*bb4ee6a4SAndroid Build Coastguard Worker     CpuIdEntry {
200*bb4ee6a4SAndroid Build Coastguard Worker         function,
201*bb4ee6a4SAndroid Build Coastguard Worker         index,
202*bb4ee6a4SAndroid Build Coastguard Worker         flags: 0,
203*bb4ee6a4SAndroid Build Coastguard Worker         cpuid: result,
204*bb4ee6a4SAndroid Build Coastguard Worker     }
205*bb4ee6a4SAndroid Build Coastguard Worker }
206*bb4ee6a4SAndroid Build Coastguard Worker 
207*bb4ee6a4SAndroid Build Coastguard Worker impl HypervisorX86_64 for Whpx {
208*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the system supported CPUID values.
209*bb4ee6a4SAndroid Build Coastguard Worker     ///
210*bb4ee6a4SAndroid Build Coastguard Worker     /// WHPX does not have an API for getting this information, so we just return the host values
211*bb4ee6a4SAndroid Build Coastguard Worker     /// instead. This is not technically accurate, since WHPX does modify the contents of various
212*bb4ee6a4SAndroid Build Coastguard Worker     /// leaves, but in practice this is fine because this function is only used for pre-setting
213*bb4ee6a4SAndroid Build Coastguard Worker     /// the contents of certain leaves that we can safely base off of the host value.
get_supported_cpuid(&self) -> Result<CpuId>214*bb4ee6a4SAndroid Build Coastguard Worker     fn get_supported_cpuid(&self) -> Result<CpuId> {
215*bb4ee6a4SAndroid Build Coastguard Worker         Ok(CpuId {
216*bb4ee6a4SAndroid Build Coastguard Worker             cpu_id_entries: vec![
217*bb4ee6a4SAndroid Build Coastguard Worker                 // Leaf 0 just contains information about the max leaf. WHPX seems to set this to
218*bb4ee6a4SAndroid Build Coastguard Worker                 // a value lower than the host value but we want it to be at least 0x15. We set it
219*bb4ee6a4SAndroid Build Coastguard Worker                 // to the host value here assuming that the leaves above 0x15 probably won't hurt
220*bb4ee6a4SAndroid Build Coastguard Worker                 // the guest.
221*bb4ee6a4SAndroid Build Coastguard Worker                 cpuid_entry_from_host(0, 0),
222*bb4ee6a4SAndroid Build Coastguard Worker                 // crosvm overrides the entirety of leaves 2, 0x80000005, and 0x80000006 to the
223*bb4ee6a4SAndroid Build Coastguard Worker                 // host value, so we just return the host value here.
224*bb4ee6a4SAndroid Build Coastguard Worker                 cpuid_entry_from_host(2, 0),
225*bb4ee6a4SAndroid Build Coastguard Worker                 cpuid_entry_from_host(0x80000005, 0),
226*bb4ee6a4SAndroid Build Coastguard Worker                 cpuid_entry_from_host(0x80000006, 0),
227*bb4ee6a4SAndroid Build Coastguard Worker             ],
228*bb4ee6a4SAndroid Build Coastguard Worker         })
229*bb4ee6a4SAndroid Build Coastguard Worker     }
230*bb4ee6a4SAndroid Build Coastguard Worker 
231*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the list of supported MSRs.
232*bb4ee6a4SAndroid Build Coastguard Worker     /// TODO: this is only used by the plugin
get_msr_index_list(&self) -> Result<Vec<u32>>233*bb4ee6a4SAndroid Build Coastguard Worker     fn get_msr_index_list(&self) -> Result<Vec<u32>> {
234*bb4ee6a4SAndroid Build Coastguard Worker         Ok(vec![])
235*bb4ee6a4SAndroid Build Coastguard Worker     }
236*bb4ee6a4SAndroid Build Coastguard Worker }
237*bb4ee6a4SAndroid Build Coastguard Worker 
238*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
239*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
240*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
241*bb4ee6a4SAndroid Build Coastguard Worker 
242*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
new_whpx()243*bb4ee6a4SAndroid Build Coastguard Worker     fn new_whpx() {
244*bb4ee6a4SAndroid Build Coastguard Worker         Whpx::new().expect("failed to instantiate whpx");
245*bb4ee6a4SAndroid Build Coastguard Worker     }
246*bb4ee6a4SAndroid Build Coastguard Worker 
247*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
clone_whpx()248*bb4ee6a4SAndroid Build Coastguard Worker     fn clone_whpx() {
249*bb4ee6a4SAndroid Build Coastguard Worker         let whpx = Whpx::new().expect("failed to instantiate whpx");
250*bb4ee6a4SAndroid Build Coastguard Worker         let _whpx_clone = whpx.try_clone().unwrap();
251*bb4ee6a4SAndroid Build Coastguard Worker     }
252*bb4ee6a4SAndroid Build Coastguard Worker 
253*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
check_capability()254*bb4ee6a4SAndroid Build Coastguard Worker     fn check_capability() {
255*bb4ee6a4SAndroid Build Coastguard Worker         let whpx = Whpx::new().expect("failed to instantiate whpx");
256*bb4ee6a4SAndroid Build Coastguard Worker         assert!(whpx.check_capability(HypervisorCap::UserMemory));
257*bb4ee6a4SAndroid Build Coastguard Worker         assert!(whpx.check_capability(HypervisorCap::Xcrs));
258*bb4ee6a4SAndroid Build Coastguard Worker         assert!(whpx.check_capability(HypervisorCap::ImmediateExit));
259*bb4ee6a4SAndroid Build Coastguard Worker         assert!(!whpx.check_capability(HypervisorCap::S390UserSigp));
260*bb4ee6a4SAndroid Build Coastguard Worker     }
261*bb4ee6a4SAndroid Build Coastguard Worker }
262