mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
arch, vmm: Add new struct CpuidConfig
This struct contains all configuration fields that controls the way how we generate CPUID for the guest on x86_64. This allows cleaner extension when adding new configuration fields. Signed-off-by: Bo Chen <chen.bo@intel.com>
This commit is contained in:
+1
-1
@@ -92,7 +92,7 @@ pub mod x86_64;
|
|||||||
pub use x86_64::{
|
pub use x86_64::{
|
||||||
arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid,
|
arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid,
|
||||||
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
|
get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
|
||||||
layout::CMDLINE_START, regs, CpuidFeatureEntry, EntryPoint, _NSIG,
|
layout::CMDLINE_START, regs, CpuidConfig, CpuidFeatureEntry, EntryPoint, _NSIG,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
||||||
|
|||||||
+19
-11
@@ -145,6 +145,14 @@ struct BootParamsWrapper(boot_params);
|
|||||||
// SAFETY: BootParamsWrap is a wrapper over `boot_params` (a series of ints).
|
// SAFETY: BootParamsWrap is a wrapper over `boot_params` (a series of ints).
|
||||||
unsafe impl ByteValued for BootParamsWrapper {}
|
unsafe impl ByteValued for BootParamsWrapper {}
|
||||||
|
|
||||||
|
pub struct CpuidConfig {
|
||||||
|
pub sgx_epc_sections: Option<Vec<SgxEpcSection>>,
|
||||||
|
pub phys_bits: u8,
|
||||||
|
pub kvm_hyperv: bool,
|
||||||
|
#[cfg(feature = "tdx")]
|
||||||
|
pub tdx: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Error writing MP table to memory.
|
/// Error writing MP table to memory.
|
||||||
@@ -552,10 +560,7 @@ impl CpuidFeatureEntry {
|
|||||||
|
|
||||||
pub fn generate_common_cpuid(
|
pub fn generate_common_cpuid(
|
||||||
hypervisor: &Arc<dyn hypervisor::Hypervisor>,
|
hypervisor: &Arc<dyn hypervisor::Hypervisor>,
|
||||||
sgx_epc_sections: Option<Vec<SgxEpcSection>>,
|
config: &CpuidConfig,
|
||||||
phys_bits: u8,
|
|
||||||
kvm_hyperv: bool,
|
|
||||||
#[cfg(feature = "tdx")] tdx_enabled: bool,
|
|
||||||
) -> super::Result<Vec<CpuIdEntry>> {
|
) -> super::Result<Vec<CpuIdEntry>> {
|
||||||
// SAFETY: cpuid called with valid leaves
|
// SAFETY: cpuid called with valid leaves
|
||||||
if unsafe { x86_64::__cpuid(1) }.ecx & 1 << HYPERVISOR_ECX_BIT == 1 << HYPERVISOR_ECX_BIT {
|
if unsafe { x86_64::__cpuid(1) }.ecx & 1 << HYPERVISOR_ECX_BIT == 1 << HYPERVISOR_ECX_BIT {
|
||||||
@@ -573,7 +578,10 @@ pub fn generate_common_cpuid(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Generating guest CPUID for with physical address size: {phys_bits}");
|
info!(
|
||||||
|
"Generating guest CPUID for with physical address size: {}",
|
||||||
|
config.phys_bits
|
||||||
|
);
|
||||||
let cpuid_patches = vec![
|
let cpuid_patches = vec![
|
||||||
// Patch tsc deadline timer bit
|
// Patch tsc deadline timer bit
|
||||||
CpuidPatch {
|
CpuidPatch {
|
||||||
@@ -614,12 +622,12 @@ pub fn generate_common_cpuid(
|
|||||||
|
|
||||||
CpuidPatch::patch_cpuid(&mut cpuid, cpuid_patches);
|
CpuidPatch::patch_cpuid(&mut cpuid, cpuid_patches);
|
||||||
|
|
||||||
if let Some(sgx_epc_sections) = sgx_epc_sections {
|
if let Some(sgx_epc_sections) = &config.sgx_epc_sections {
|
||||||
update_cpuid_sgx(&mut cpuid, sgx_epc_sections)?;
|
update_cpuid_sgx(&mut cpuid, sgx_epc_sections)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
let tdx_capabilities = if tdx_enabled {
|
let tdx_capabilities = if config.tdx {
|
||||||
let caps = hypervisor
|
let caps = hypervisor
|
||||||
.tdx_capabilities()
|
.tdx_capabilities()
|
||||||
.map_err(Error::TdxCapabilities)?;
|
.map_err(Error::TdxCapabilities)?;
|
||||||
@@ -667,12 +675,12 @@ pub fn generate_common_cpuid(
|
|||||||
}
|
}
|
||||||
// Set CPU physical bits
|
// Set CPU physical bits
|
||||||
0x8000_0008 => {
|
0x8000_0008 => {
|
||||||
entry.eax = (entry.eax & 0xffff_ff00) | (phys_bits as u32 & 0xff);
|
entry.eax = (entry.eax & 0xffff_ff00) | (config.phys_bits as u32 & 0xff);
|
||||||
}
|
}
|
||||||
0x4000_0001 => {
|
0x4000_0001 => {
|
||||||
// These features are not supported by TDX
|
// These features are not supported by TDX
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
if tdx_enabled {
|
if config.tdx {
|
||||||
entry.eax &= !(1 << KVM_FEATURE_CLOCKSOURCE_BIT
|
entry.eax &= !(1 << KVM_FEATURE_CLOCKSOURCE_BIT
|
||||||
| 1 << KVM_FEATURE_CLOCKSOURCE2_BIT
|
| 1 << KVM_FEATURE_CLOCKSOURCE2_BIT
|
||||||
| 1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT
|
| 1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT
|
||||||
@@ -700,7 +708,7 @@ pub fn generate_common_cpuid(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if kvm_hyperv {
|
if config.kvm_hyperv {
|
||||||
// Remove conflicting entries
|
// Remove conflicting entries
|
||||||
cpuid.retain(|c| c.function != 0x4000_0000);
|
cpuid.retain(|c| c.function != 0x4000_0000);
|
||||||
cpuid.retain(|c| c.function != 0x4000_0001);
|
cpuid.retain(|c| c.function != 0x4000_0001);
|
||||||
@@ -1293,7 +1301,7 @@ fn update_cpuid_topology(
|
|||||||
// sections exposed to the guest.
|
// sections exposed to the guest.
|
||||||
fn update_cpuid_sgx(
|
fn update_cpuid_sgx(
|
||||||
cpuid: &mut Vec<CpuIdEntry>,
|
cpuid: &mut Vec<CpuIdEntry>,
|
||||||
epc_sections: Vec<SgxEpcSection>,
|
epc_sections: &Vec<SgxEpcSection>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// Something's wrong if there's no EPC section.
|
// Something's wrong if there's no EPC section.
|
||||||
if epc_sections.is_empty() {
|
if epc_sections.is_empty() {
|
||||||
|
|||||||
+8
-6
@@ -726,7 +726,7 @@ impl CpuManager {
|
|||||||
&mut self,
|
&mut self,
|
||||||
memory_manager: &Arc<Mutex<MemoryManager>>,
|
memory_manager: &Arc<Mutex<MemoryManager>>,
|
||||||
hypervisor: &Arc<dyn hypervisor::Hypervisor>,
|
hypervisor: &Arc<dyn hypervisor::Hypervisor>,
|
||||||
#[cfg(feature = "tdx")] tdx_enabled: bool,
|
#[cfg(feature = "tdx")] tdx: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let sgx_epc_sections = memory_manager
|
let sgx_epc_sections = memory_manager
|
||||||
.lock()
|
.lock()
|
||||||
@@ -739,11 +739,13 @@ impl CpuManager {
|
|||||||
let phys_bits = physical_bits(hypervisor, self.config.max_phys_bits);
|
let phys_bits = physical_bits(hypervisor, self.config.max_phys_bits);
|
||||||
arch::generate_common_cpuid(
|
arch::generate_common_cpuid(
|
||||||
hypervisor,
|
hypervisor,
|
||||||
sgx_epc_sections,
|
&arch::CpuidConfig {
|
||||||
phys_bits,
|
sgx_epc_sections,
|
||||||
self.config.kvm_hyperv,
|
phys_bits,
|
||||||
#[cfg(feature = "tdx")]
|
kvm_hyperv: self.config.kvm_hyperv,
|
||||||
tdx_enabled,
|
#[cfg(feature = "tdx")]
|
||||||
|
tdx,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.map_err(Error::CommonCpuId)?
|
.map_err(Error::CommonCpuId)?
|
||||||
};
|
};
|
||||||
|
|||||||
+15
-11
@@ -1664,16 +1664,18 @@ impl Vmm {
|
|||||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||||
let common_cpuid = {
|
let common_cpuid = {
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
let tdx_enabled = vm_config.lock().unwrap().is_tdx_enabled();
|
let tdx = vm_config.lock().unwrap().is_tdx_enabled();
|
||||||
let phys_bits =
|
let phys_bits =
|
||||||
vm::physical_bits(&hypervisor, vm_config.lock().unwrap().cpus.max_phys_bits);
|
vm::physical_bits(&hypervisor, vm_config.lock().unwrap().cpus.max_phys_bits);
|
||||||
arch::generate_common_cpuid(
|
arch::generate_common_cpuid(
|
||||||
&hypervisor,
|
&hypervisor,
|
||||||
None,
|
&arch::CpuidConfig {
|
||||||
phys_bits,
|
sgx_epc_sections: None,
|
||||||
vm_config.lock().unwrap().cpus.kvm_hyperv,
|
phys_bits,
|
||||||
#[cfg(feature = "tdx")]
|
kvm_hyperv: vm_config.lock().unwrap().cpus.kvm_hyperv,
|
||||||
tdx_enabled,
|
#[cfg(feature = "tdx")]
|
||||||
|
tdx,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
MigratableError::MigrateReceive(anyhow!("Error generating common cpuid': {:?}", e))
|
MigratableError::MigrateReceive(anyhow!("Error generating common cpuid': {:?}", e))
|
||||||
@@ -1858,11 +1860,13 @@ impl Vmm {
|
|||||||
let phys_bits = vm::physical_bits(&self.hypervisor, vm_config.cpus.max_phys_bits);
|
let phys_bits = vm::physical_bits(&self.hypervisor, vm_config.cpus.max_phys_bits);
|
||||||
arch::generate_common_cpuid(
|
arch::generate_common_cpuid(
|
||||||
&self.hypervisor.clone(),
|
&self.hypervisor.clone(),
|
||||||
None,
|
&arch::CpuidConfig {
|
||||||
phys_bits,
|
sgx_epc_sections: None,
|
||||||
vm_config.cpus.kvm_hyperv,
|
phys_bits,
|
||||||
#[cfg(feature = "tdx")]
|
kvm_hyperv: vm_config.cpus.kvm_hyperv,
|
||||||
vm_config.is_tdx_enabled(),
|
#[cfg(feature = "tdx")]
|
||||||
|
tdx: vm_config.is_tdx_enabled(),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
MigratableError::MigrateReceive(anyhow!("Error generating common cpuid: {:?}", e))
|
MigratableError::MigrateReceive(anyhow!("Error generating common cpuid: {:?}", e))
|
||||||
|
|||||||
+7
-5
@@ -2415,11 +2415,13 @@ impl Snapshottable for Vm {
|
|||||||
);
|
);
|
||||||
arch::generate_common_cpuid(
|
arch::generate_common_cpuid(
|
||||||
&self.hypervisor,
|
&self.hypervisor,
|
||||||
None,
|
&arch::CpuidConfig {
|
||||||
phys_bits,
|
sgx_epc_sections: None,
|
||||||
self.config.lock().unwrap().cpus.kvm_hyperv,
|
phys_bits,
|
||||||
#[cfg(feature = "tdx")]
|
kvm_hyperv: self.config.lock().unwrap().cpus.kvm_hyperv,
|
||||||
tdx_enabled,
|
#[cfg(feature = "tdx")]
|
||||||
|
tdx: tdx_enabled,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
MigratableError::MigrateReceive(anyhow!("Error generating common cpuid: {:?}", e))
|
MigratableError::MigrateReceive(anyhow!("Error generating common cpuid: {:?}", e))
|
||||||
|
|||||||
Reference in New Issue
Block a user