cpu: Implement AMD compatible topology handling

cpu: Pass APIC id explicitly where needed
topology: Set subleaf number explicitly

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2023-04-28 20:44:07 +02:00
committed by Anatol Belski
parent 31686b91d3
commit b52966a12c
4 changed files with 125 additions and 25 deletions

View File

@@ -56,6 +56,8 @@ use hypervisor::kvm::kvm_bindings;
use hypervisor::kvm::kvm_ioctls::Cap;
#[cfg(feature = "tdx")]
use hypervisor::kvm::{TdxExitDetails, TdxExitStatus};
#[cfg(target_arch = "x86_64")]
use hypervisor::CpuVendor;
use hypervisor::{CpuState, HypervisorCpuError, HypervisorType, VmExit, VmOps};
use libc::{c_void, siginfo_t};
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
@@ -85,7 +87,6 @@ use vm_migration::{
use vmm_sys_util::eventfd::EventFd;
use vmm_sys_util::signal::{register_signal_handler, SIGRTMIN};
use zerocopy::AsBytes;
#[cfg(all(target_arch = "aarch64", feature = "guest_debug"))]
/// Extract the specified bits of a 64-bit integer.
/// For example, to extrace 2 bits from offset 1 (zero based) of `6u64`,
@@ -315,6 +316,8 @@ pub struct Vcpu {
#[cfg(target_arch = "aarch64")]
mpidr: u64,
saved_state: Option<CpuState>,
#[cfg(target_arch = "x86_64")]
vendor: CpuVendor,
}
impl Vcpu {
@@ -325,10 +328,12 @@ impl Vcpu {
/// * `id` - Represents the CPU number between [0, max vcpus).
/// * `vm` - The virtual machine this vcpu will get attached to.
/// * `vm_ops` - Optional object for exit handling.
/// * `cpu_vendor` - CPU vendor as reported by __cpuid(0x0)
pub fn new(
id: u8,
vm: &Arc<dyn hypervisor::Vm>,
vm_ops: Option<Arc<dyn VmOps>>,
#[cfg(target_arch = "x86_64")] cpu_vendor: CpuVendor,
) -> Result<Self> {
let vcpu = vm
.create_vcpu(id, vm_ops)
@@ -340,6 +345,8 @@ impl Vcpu {
#[cfg(target_arch = "aarch64")]
mpidr: 0,
saved_state: None,
#[cfg(target_arch = "x86_64")]
vendor: cpu_vendor,
})
}
@@ -356,6 +363,7 @@ impl Vcpu {
boot_setup: Option<(EntryPoint, &GuestMemoryAtomic<GuestMemoryMmap>)>,
#[cfg(target_arch = "x86_64")] cpuid: Vec<CpuIdEntry>,
#[cfg(target_arch = "x86_64")] kvm_hyperv: bool,
#[cfg(target_arch = "x86_64")] topology: Option<(u8, u8, u8)>,
) -> Result<()> {
#[cfg(target_arch = "aarch64")]
{
@@ -365,8 +373,16 @@ impl Vcpu {
}
info!("Configuring vCPU: cpu_id = {}", self.id);
#[cfg(target_arch = "x86_64")]
arch::configure_vcpu(&self.vcpu, self.id, boot_setup, cpuid, kvm_hyperv)
.map_err(Error::VcpuConfiguration)?;
arch::configure_vcpu(
&self.vcpu,
self.id,
boot_setup,
cpuid,
kvm_hyperv,
self.vendor,
topology,
)
.map_err(Error::VcpuConfiguration)?;
Ok(())
}
@@ -463,6 +479,8 @@ pub struct CpuManager {
proximity_domain_per_cpu: BTreeMap<u8, u32>,
affinity: BTreeMap<u8, Vec<u8>>,
dynamic: bool,
#[cfg(target_arch = "x86_64")]
cpu_vendor: CpuVendor,
}
const CPU_ENABLE_FLAG: usize = 0;
@@ -619,6 +637,8 @@ impl CpuManager {
let mut vcpu_states = Vec::with_capacity(usize::from(config.max_vcpus));
vcpu_states.resize_with(usize::from(config.max_vcpus), VcpuState::default);
let hypervisor_type = hypervisor.hypervisor_type();
#[cfg(target_arch = "x86_64")]
let cpu_vendor = hypervisor.get_cpu_vendor();
#[cfg(target_arch = "x86_64")]
if config.features.amx {
@@ -700,6 +720,8 @@ impl CpuManager {
proximity_domain_per_cpu,
affinity,
dynamic,
#[cfg(target_arch = "x86_64")]
cpu_vendor,
})))
}
@@ -717,22 +739,10 @@ impl CpuManager {
.as_ref()
.map(|sgx_epc_region| sgx_epc_region.epc_sections().values().cloned().collect());
let topology = self.config.topology.clone().map_or_else(
|| {
#[cfg(feature = "mshv")]
if matches!(hypervisor.hypervisor_type(), HypervisorType::Mshv) {
return Some((1, self.boot_vcpus(), 1));
}
None
},
|t| Some((t.threads_per_core, t.cores_per_die, t.dies_per_package)),
);
self.cpuid = {
let phys_bits = physical_bits(hypervisor, self.config.max_phys_bits);
arch::generate_common_cpuid(
hypervisor,
topology,
sgx_epc_sections,
phys_bits,
self.config.kvm_hyperv,
@@ -748,7 +758,13 @@ impl CpuManager {
fn create_vcpu(&mut self, cpu_id: u8, snapshot: Option<Snapshot>) -> Result<Arc<Mutex<Vcpu>>> {
info!("Creating vCPU: cpu_id = {}", cpu_id);
let mut vcpu = Vcpu::new(cpu_id, &self.vm, Some(self.vm_ops.clone()))?;
let mut vcpu = Vcpu::new(
cpu_id,
&self.vm,
Some(self.vm_ops.clone()),
#[cfg(target_arch = "x86_64")]
self.cpu_vendor,
)?;
if let Some(snapshot) = snapshot {
// AArch64 vCPUs should be initialized after created.
@@ -784,7 +800,23 @@ impl CpuManager {
assert!(!self.cpuid.is_empty());
#[cfg(target_arch = "x86_64")]
vcpu.configure(boot_setup, self.cpuid.clone(), self.config.kvm_hyperv)?;
let topology = self.config.topology.clone().map_or_else(
|| {
#[cfg(feature = "mshv")]
if matches!(self.hypervisor_type, HypervisorType::Mshv) {
return Some((1, self.boot_vcpus(), 1));
}
None
},
|t| Some((t.threads_per_core, t.cores_per_die, t.dies_per_package)),
);
#[cfg(target_arch = "x86_64")]
vcpu.configure(
boot_setup,
self.cpuid.clone(),
self.config.kvm_hyperv,
topology,
)?;
#[cfg(target_arch = "aarch64")]
vcpu.configure(&self.vm, boot_setup)?;

View File

@@ -1668,7 +1668,6 @@ impl Vmm {
arch::generate_common_cpuid(
&hypervisor,
None,
None,
phys_bits,
vm_config.lock().unwrap().cpus.kvm_hyperv,
#[cfg(feature = "tdx")]
@@ -1858,7 +1857,6 @@ impl Vmm {
arch::generate_common_cpuid(
&self.hypervisor.clone(),
None,
None,
phys_bits,
vm_config.cpus.kvm_hyperv,
#[cfg(feature = "tdx")]

View File

@@ -2402,7 +2402,6 @@ impl Snapshottable for Vm {
arch::generate_common_cpuid(
&self.hypervisor,
None,
None,
phys_bits,
self.config.lock().unwrap().cpus.kvm_hyperv,
#[cfg(feature = "tdx")]