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 {