diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 538ae500c..25ca31c0d 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -117,6 +117,9 @@ pub enum Error { /// Failed to allocate IO port AllocateIOPort, + + /// Asking for more vCPUs that we can have + DesiredVCPUCountExceedsMax, } pub type Result = result::Result; @@ -444,7 +447,7 @@ impl CpuManager { fd, vcpus_kill_signalled: Arc::new(AtomicBool::new(false)), vcpus_pause_signalled: Arc::new(AtomicBool::new(false)), - threads: Vec::with_capacity(boot_vcpus as usize), + vcpu_states: Vec::with_capacity(max_vcpus as usize), reset_evt, selected_cpu: 0, })); @@ -468,13 +471,17 @@ impl CpuManager { Ok(cpu_manager) } - // Starts all the vCPUs that the VM is booting with. Blocks until all vCPUs are running. - pub fn start_boot_vcpus(&mut self, entry_addr: GuestAddress) -> Result<()> { + fn activate_vcpus(&mut self, desired_vcpus: u8, entry_addr: GuestAddress) -> Result<()> { + if desired_vcpus > self.max_vcpus { + return Err(Error::DesiredVCPUCountExceedsMax); + } + let creation_ts = std::time::Instant::now(); + let vcpu_thread_barrier = Arc::new(Barrier::new( + (desired_vcpus - self.present_vcpus() + 1) as usize, + )); - let vcpu_thread_barrier = Arc::new(Barrier::new((self.boot_vcpus + 1) as usize)); - - for cpu_id in 0..self.boot_vcpus { + for cpu_id in self.present_vcpus()..desired_vcpus { let ioapic = if let Some(ioapic) = &self.ioapic { Some(ioapic.clone()) } else { @@ -559,6 +566,11 @@ impl CpuManager { Ok(()) } + // Starts all the vCPUs that the VM is booting with. Blocks until all vCPUs are running. + pub fn start_boot_vcpus(&mut self, entry_addr: GuestAddress) -> Result<()> { + self.activate_vcpus(self.boot_vcpus(), entry_addr) + } + pub fn shutdown(&mut self) -> Result<()> { // Tell the vCPUs to stop themselves next time they go through the loop self.vcpus_kill_signalled.store(true, Ordering::SeqCst);