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:
Bo Chen
2023-10-11 11:52:24 -07:00
committed by Bo Chen
parent 30975ea102
commit 7dd260f82f
5 changed files with 50 additions and 34 deletions
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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))