diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 681256db0..4e693f98d 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -720,15 +720,28 @@ impl CpuManager { }))) } - fn create_vcpu( - &mut self, - cpu_id: u8, + fn create_vcpu(&mut self, cpu_id: u8) -> Result>> { + info!("Creating vCPU: cpu_id = {}", cpu_id); + + let vcpu = Arc::new(Mutex::new(Vcpu::new( + cpu_id, + &self.vm, + Some(self.vm_ops.clone()), + )?)); + + // Adding vCPU to the CpuManager's vCPU list. + self.vcpus.push(vcpu.clone()); + + Ok(vcpu) + } + + pub fn configure_vcpu( + &self, + vcpu: Arc>, entry_point: Option, snapshot: Option, ) -> Result<()> { - 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.lock().unwrap(); if let Some(snapshot) = snapshot { // AArch64 vCPUs should be initialized after created. @@ -751,15 +764,12 @@ impl CpuManager { .expect("Failed to configure vCPU"); } - // Adding vCPU to the CpuManager's vCPU list. - let vcpu = Arc::new(Mutex::new(vcpu)); - self.vcpus.push(vcpu); - Ok(()) } /// Only create new vCPUs if there aren't any inactive ones to reuse - fn create_vcpus(&mut self, desired_vcpus: u8, entry_point: Option) -> Result<()> { + fn create_vcpus(&mut self, desired_vcpus: u8) -> Result>>> { + let mut vcpus: Vec>> = vec![]; info!( "Request to create new vCPUs: desired = {}, max = {}, allocated = {}, present = {}", desired_vcpus, @@ -774,10 +784,10 @@ impl CpuManager { // Only create vCPUs in excess of all the allocated vCPUs. for cpu_id in self.vcpus.len() as u8..desired_vcpus { - self.create_vcpu(cpu_id, entry_point, None)?; + vcpus.push(self.create_vcpu(cpu_id)?); } - Ok(()) + Ok(vcpus) } #[cfg(target_arch = "aarch64")] @@ -799,6 +809,10 @@ impl CpuManager { Ok(true) } + pub fn vcpus(&self) -> Vec>> { + self.vcpus.clone() + } + fn start_vcpu( &mut self, vcpu: Arc>, @@ -1102,10 +1116,10 @@ impl CpuManager { Ok(()) } - pub fn create_boot_vcpus(&mut self, entry_point: Option) -> Result<()> { + pub fn create_boot_vcpus(&mut self) -> Result>>> { trace_scoped!("create_boot_vcpus"); - self.create_vcpus(self.boot_vcpus(), entry_point) + self.create_vcpus(self.boot_vcpus()) } // Starts all the vCPUs that the VM is booting with. Blocks until all vCPUs are running. @@ -1133,7 +1147,10 @@ impl CpuManager { match desired_vcpus.cmp(&self.present_vcpus()) { cmp::Ordering::Greater => { - self.create_vcpus(desired_vcpus, None)?; + let vcpus = self.create_vcpus(desired_vcpus)?; + for vcpu in vcpus { + self.configure_vcpu(vcpu, None, None)? + } self.activate_vcpus(desired_vcpus, true, None)?; Ok(true) } @@ -2066,8 +2083,13 @@ impl Snapshottable for CpuManager { fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> { for (cpu_id, snapshot) in snapshot.snapshots.iter() { info!("Restoring VCPU {}", cpu_id); - self.create_vcpu(cpu_id.parse::().unwrap(), None, Some(*snapshot.clone())) + let vcpu = self + .create_vcpu(cpu_id.parse::().unwrap()) .map_err(|e| MigratableError::Restore(anyhow!("Could not create vCPU {:?}", e)))?; + self.configure_vcpu(vcpu, None, Some(*snapshot.clone())) + .map_err(|e| { + MigratableError::Restore(anyhow!("Could not configure vCPU {:?}", e)) + })? } Ok(()) diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index c2ac1f8ae..7d7273c51 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -2087,12 +2087,15 @@ impl Vm { self.init_tdx()?; } - // Create and configure vcpus - self.cpu_manager - .lock() - .unwrap() - .create_boot_vcpus(entry_point) - .map_err(Error::CpuManager)?; + // Configure the vcpus that have been created + let vcpus = self.cpu_manager.lock().unwrap().vcpus(); + for vcpu in vcpus { + self.cpu_manager + .lock() + .unwrap() + .configure_vcpu(vcpu, entry_point, None) + .map_err(Error::CpuManager)?; + } #[cfg(feature = "tdx")] let sections = if tdx_enabled {