From 7b3fc72aeae1670196017c75d6035aef6ea2a762 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 17 Dec 2019 10:49:05 +0000 Subject: [PATCH] vmm: cpu: Notify guest OS that it should offline vCPUs Allow the resizing of the number of vCPUs to less than the current active vCPUs. This does not currently remove them from the system but the kernel will take them offline. Signed-off-by: Rob Bradford --- vmm/src/cpu.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index f020eaaa2..1d5b76145 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -389,6 +389,7 @@ pub struct CpuManager { const CPU_ENABLE_FLAG: usize = 0; const CPU_INSERTING_FLAG: usize = 1; +const CPU_REMOVING_FLAG: usize = 2; const CPU_STATUS_OFFSET: u64 = 4; const CPU_SELECTION_OFFSET: u64 = 0; @@ -405,6 +406,9 @@ impl BusDevice for CpuManager { if state.inserting { data[0] |= 1 << CPU_INSERTING_FLAG; } + if state.removing { + data[0] |= 1 << CPU_REMOVING_FLAG; + } } } _ => { @@ -429,6 +433,11 @@ impl BusDevice for CpuManager { { state.inserting = false; } + // Ditto for removal + if (data[0] & (1 << CPU_REMOVING_FLAG) == 1 << CPU_REMOVING_FLAG) && state.removing + { + state.removing = false; + } } _ => { warn!( @@ -443,6 +452,7 @@ impl BusDevice for CpuManager { #[derive(Default)] struct VcpuState { inserting: bool, + removing: bool, handle: Option>, } @@ -621,13 +631,27 @@ impl CpuManager { Ok(()) } + fn mark_vcpus_for_removal(&mut self, desired_vcpus: u8) -> Result<()> { + // Mark vCPUs for removal, actual removal happens on ejection + for cpu_id in desired_vcpus..self.present_vcpus() { + self.vcpu_states[usize::from(cpu_id)].removing = true; + } + 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(), Some(entry_addr)) } pub fn resize(&mut self, desired_vcpus: u8) -> Result<()> { - self.activate_vcpus(desired_vcpus, None) + if desired_vcpus > self.present_vcpus() { + self.activate_vcpus(desired_vcpus, None)?; + } else if desired_vcpus < self.present_vcpus() { + self.mark_vcpus_for_removal(desired_vcpus)?; + } + + Ok(()) } pub fn shutdown(&mut self) -> Result<()> { @@ -857,6 +881,22 @@ impl Aml for CPUMethods { ), ], ), + // Check if CRMV bit is set + &aml::If::new( + &aml::Equal::new(&aml::Path::new("\\_SB_.PRES.CRMV"), &aml::ONE), + // Notify device if it is (with the eject constant 0x3) + vec![ + &aml::MethodCall::new( + "CTFY".into(), + vec![&aml::Local(0), &3u8], + ), + // Reset CRMV bit + &aml::Store::new( + &aml::Path::new("\\_SB_.PRES.CRMV"), + &aml::ONE, + ), + ], + ), &aml::Add::new(&aml::Local(0), &aml::Local(0), &aml::ONE), ], ),