From a0f4376eb0d0d62f9adf4e4fa217d27a5b224ad7 Mon Sep 17 00:00:00 2001 From: Chao Peng Date: Tue, 11 Jun 2019 13:53:38 +0000 Subject: [PATCH] vmm: Set the APIC ID in the extended topology KVM exposes CPUID 0BH when host supports that, but the APIC ID that KVM provides is the host APIC ID so we need replace that with ours. Without this Linux guest reports something like: [Firmware Bug]: CPU1: APIC id mismatch. Firmware: 1 APIC: 21 Fixes #42 Signed-off-by: Chao Peng --- src/main.rs | 8 ++++++++ vmm/src/vm.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 5ad2a8337..922b83081 100755 --- a/src/main.rs +++ b/src/main.rs @@ -202,6 +202,13 @@ mod tests { .unwrap() } + fn get_initial_apicid() -> u32 { + ssh_command("grep \"initial apicid\" /proc/cpuinfo | grep -o \"[0-9]*\"") + .trim() + .parse() + .unwrap() + } + fn get_total_memory() -> u32 { ssh_command("grep MemTotal /proc/meminfo | grep -o \"[0-9]*\"") .trim() @@ -232,6 +239,7 @@ mod tests { thread::sleep(std::time::Duration::new(10, 0)); aver_eq!(tb, get_cpu_count(), 1); + aver_eq!(tb, get_initial_apicid(), 0); aver!(tb, get_total_memory() > 496_000); aver!(tb, get_entropy() >= 1000); diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index a43607e5e..b8c78e197 100755 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -193,6 +193,15 @@ pub enum DeviceManagerError { } pub type DeviceManagerResult = result::Result; +#[allow(dead_code)] +#[derive(Copy, Clone)] +enum CpuidReg { + EAX, + EBX, + ECX, + EDX, +} + /// A wrapper around creating and using a kvm-based VCPU. pub struct Vcpu { fd: VcpuFd, @@ -227,8 +236,10 @@ impl Vcpu { /// * `kernel_start_addr` - Offset from `guest_mem` at which the kernel starts. /// * `vm` - The virtual machine this vcpu will get attached to. pub fn configure(&mut self, kernel_start_addr: GuestAddress, vm: &Vm) -> Result<()> { + let mut cpuid = vm.cpuid.clone(); + Vcpu::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(self.id)); self.fd - .set_cpuid2(&vm.cpuid) + .set_cpuid2(&cpuid) .map_err(Error::SetSupportedCpusFailed)?; arch::x86_64::regs::setup_msrs(&self.fd).map_err(Error::MSRSConfiguration)?; @@ -285,6 +296,35 @@ impl Vcpu { }, } } + + fn set_cpuid_reg( + cpuid: &mut CpuId, + function: u32, + index: Option, + reg: CpuidReg, + value: u32, + ) { + let entries = cpuid.mut_entries_slice(); + + for entry in entries.iter_mut() { + if entry.function == function && (index == None || index.unwrap() == entry.index) { + match reg { + CpuidReg::EAX => { + entry.eax = value; + } + CpuidReg::EBX => { + entry.ebx = value; + } + CpuidReg::ECX => { + entry.ecx = value; + } + CpuidReg::EDX => { + entry.edx = value; + } + } + } + } + } } struct DeviceManager {