x86::__cpuid is safe on Rust ≥1.94 but unsafe on older versions. This causes unused_unsafe warnings when compiling with Rust ≥1.94. However, on earlier Rust versions, the code won’t compile if the unsafe blocks are absent. Work around this by adding #[allow(unused_unsafe)] where needed to suppress the warnings. See #7588 for more discussion. Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
192 lines
5.7 KiB
Rust
192 lines
5.7 KiB
Rust
// Copyright © 2019 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
|
//
|
|
// Copyright © 2020, Microsoft Corporation
|
|
//
|
|
// Copyright 2018-2019 CrowdStrike, Inc.
|
|
//
|
|
//
|
|
#[cfg(target_arch = "x86_64")]
|
|
use std::arch::x86_64;
|
|
use std::sync::Arc;
|
|
|
|
use thiserror::Error;
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
use crate::arch::x86::CpuIdEntry;
|
|
#[cfg(target_arch = "x86_64")]
|
|
use crate::cpu::CpuVendor;
|
|
#[cfg(feature = "tdx")]
|
|
use crate::kvm::TdxCapabilities;
|
|
use crate::vm::Vm;
|
|
use crate::{HypervisorType, HypervisorVmConfig};
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum HypervisorError {
|
|
///
|
|
/// Hypervisor availability check error
|
|
///
|
|
#[error("Failed to check availability of the hypervisor")]
|
|
HypervisorAvailableCheck(#[source] anyhow::Error),
|
|
///
|
|
/// hypervisor creation error
|
|
///
|
|
#[error("Failed to create the hypervisor")]
|
|
HypervisorCreate(#[source] anyhow::Error),
|
|
///
|
|
/// Vm creation failure
|
|
///
|
|
#[error("Failed to create Vm")]
|
|
VmCreate(#[source] anyhow::Error),
|
|
///
|
|
/// Vm setup failure
|
|
///
|
|
#[error("Failed to setup Vm")]
|
|
VmSetup(#[source] anyhow::Error),
|
|
///
|
|
/// API version error
|
|
///
|
|
#[error("Failed to get API Version")]
|
|
GetApiVersion(#[source] anyhow::Error),
|
|
///
|
|
/// CpuId error
|
|
///
|
|
#[error("Failed to get cpuid")]
|
|
GetCpuId(#[source] anyhow::Error),
|
|
///
|
|
/// Failed to retrieve list of MSRs.
|
|
///
|
|
#[error("Failed to get the list of supported MSRs")]
|
|
GetMsrList(#[source] anyhow::Error),
|
|
///
|
|
/// API version is not compatible
|
|
///
|
|
#[error("Incompatible API version")]
|
|
IncompatibleApiVersion,
|
|
///
|
|
/// Checking extensions failed
|
|
///
|
|
#[error("Checking extensions")]
|
|
CheckExtensions(#[source] anyhow::Error),
|
|
///
|
|
/// Failed to retrieve TDX capabilities
|
|
///
|
|
#[error("Failed to retrieve TDX capabilities")]
|
|
TdxCapabilities(#[source] anyhow::Error),
|
|
///
|
|
/// Failed to set partition property
|
|
///
|
|
#[error("Failed to set partition property")]
|
|
SetPartitionProperty(#[source] anyhow::Error),
|
|
///
|
|
/// Running on an unsupported CPU
|
|
///
|
|
#[error("Unsupported CPU")]
|
|
UnsupportedCpu(#[source] anyhow::Error),
|
|
///
|
|
/// Launching a VM with unsupported VM Type
|
|
///
|
|
#[error("Unsupported VmType")]
|
|
UnsupportedVmType(),
|
|
|
|
///
|
|
/// The attempt to enable AMX tile state components failed
|
|
///
|
|
#[cfg(target_arch = "x86_64")]
|
|
#[error("Failed to enable AMX tile state components")]
|
|
CouldNotEnableAmxStateComponents(#[source] crate::arch::x86::AmxGuestSupportError),
|
|
}
|
|
|
|
///
|
|
/// Result type for returning from a function
|
|
///
|
|
pub type Result<T> = std::result::Result<T, HypervisorError>;
|
|
|
|
///
|
|
/// Trait to represent a Hypervisor
|
|
///
|
|
/// This crate provides a hypervisor-agnostic interfaces
|
|
///
|
|
pub trait Hypervisor: Send + Sync {
|
|
///
|
|
/// Returns the type of the hypervisor
|
|
///
|
|
fn hypervisor_type(&self) -> HypervisorType;
|
|
///
|
|
/// Create a Vm using the underlying hypervisor
|
|
/// Return a hypervisor-agnostic Vm trait object
|
|
///
|
|
fn create_vm(&self, config: HypervisorVmConfig) -> Result<Arc<dyn Vm>>;
|
|
#[cfg(target_arch = "x86_64")]
|
|
///
|
|
/// Get the supported CpuID
|
|
///
|
|
fn get_supported_cpuid(&self) -> Result<Vec<CpuIdEntry>>;
|
|
///
|
|
/// Check particular extensions if any
|
|
///
|
|
fn check_required_extensions(&self) -> Result<()> {
|
|
Ok(())
|
|
}
|
|
#[cfg(target_arch = "aarch64")]
|
|
///
|
|
/// Retrieve AArch64 host maximum IPA size supported by KVM
|
|
///
|
|
fn get_host_ipa_limit(&self) -> i32;
|
|
///
|
|
/// Retrieve TDX capabilities
|
|
///
|
|
#[cfg(feature = "tdx")]
|
|
fn tdx_capabilities(&self) -> Result<TdxCapabilities> {
|
|
unimplemented!()
|
|
}
|
|
///
|
|
/// Get the number of supported hardware breakpoints
|
|
///
|
|
fn get_guest_debug_hw_bps(&self) -> usize {
|
|
unimplemented!()
|
|
}
|
|
|
|
/// Get maximum number of vCPUs
|
|
fn get_max_vcpus(&self) -> u32;
|
|
#[cfg(target_arch = "x86_64")]
|
|
///
|
|
/// Determine CPU vendor
|
|
///
|
|
fn get_cpu_vendor(&self) -> CpuVendor {
|
|
#[allow(unused_unsafe)]
|
|
// SAFETY: not actually unsafe, but considered unsafe by current stable
|
|
unsafe {
|
|
let leaf = x86_64::__cpuid(0x0);
|
|
|
|
if leaf.ebx == 0x756e_6547 && leaf.ecx == 0x6c65_746e && leaf.edx == 0x4965_6e69 {
|
|
// Vendor string GenuineIntel
|
|
CpuVendor::Intel
|
|
} else if leaf.ebx == 0x6874_7541 && leaf.ecx == 0x444d_4163 && leaf.edx == 0x6974_6e65
|
|
{
|
|
// Vendor string AuthenticAMD
|
|
CpuVendor::AMD
|
|
} else {
|
|
// Not known yet, the corresponding manufacturer manual should contain the
|
|
// necessary info. See also https://wiki.osdev.org/CPUID#CPU_Vendor_ID_String
|
|
CpuVendor::default()
|
|
}
|
|
}
|
|
}
|
|
|
|
/// This function enables the AMX related TILECFG and TILEDATA state components for guests.
|
|
///
|
|
/// # Background
|
|
/// AMX uses a concept of tiles which are small 2D blocks of data stored in registers on the CPU,
|
|
/// where the TILECFG state component defines the shape and size of each tile (rows and columns),
|
|
/// and the TILEDATA state component holds the actual elements of these tiles used by matrix operations.
|
|
#[cfg(target_arch = "x86_64")]
|
|
fn enable_amx_state_components(&self) -> Result<()> {
|
|
let cpu_vendor = self.get_cpu_vendor();
|
|
crate::arch::x86::amx_supported(cpu_vendor)
|
|
.map_err(HypervisorError::CouldNotEnableAmxStateComponents)?;
|
|
crate::arch::x86::request_guest_amx_support()
|
|
.map_err(HypervisorError::CouldNotEnableAmxStateComponents)
|
|
}
|
|
}
|