Merge pull request #6009 from openanolis/dragonball/add_cpu_resize

Dragonball: add cpu resize ability
This commit is contained in:
Bin Liu
2023-02-05 19:54:08 +08:00
committed by GitHub
7 changed files with 178 additions and 83 deletions

View File

@@ -35,6 +35,9 @@ pub use crate::device_manager::virtio_net_dev_mgr::{
#[cfg(feature = "virtio-vsock")] #[cfg(feature = "virtio-vsock")]
pub use crate::device_manager::vsock_dev_mgr::{VsockDeviceConfigInfo, VsockDeviceError}; pub use crate::device_manager::vsock_dev_mgr::{VsockDeviceConfigInfo, VsockDeviceError};
#[cfg(feature = "hotplug")]
pub use crate::vcpu::{VcpuResizeError, VcpuResizeInfo};
use super::*; use super::*;
/// Wrapper for all errors associated with VMM actions. /// Wrapper for all errors associated with VMM actions.
@@ -44,9 +47,13 @@ pub enum VmmActionError {
#[error("the virtual machine instance ID is invalid")] #[error("the virtual machine instance ID is invalid")]
InvalidVMID, InvalidVMID,
/// VM doesn't exist and can't get VM information.
#[error("VM doesn't exist and can't get VM information")]
VmNotExist,
/// Failed to hotplug, due to Upcall not ready. /// Failed to hotplug, due to Upcall not ready.
#[error("Upcall not ready, can't hotplug device.")] #[error("Upcall not ready, can't hotplug device.")]
UpcallNotReady, UpcallServerNotReady,
/// The action `ConfigureBootSource` failed either because of bad user input or an internal /// The action `ConfigureBootSource` failed either because of bad user input or an internal
/// error. /// error.
@@ -85,6 +92,11 @@ pub enum VmmActionError {
/// The action `InsertFsDevice` failed either because of bad user input or an internal error. /// The action `InsertFsDevice` failed either because of bad user input or an internal error.
#[error("virtio-fs device error: {0}")] #[error("virtio-fs device error: {0}")]
FsDevice(#[source] FsDeviceError), FsDevice(#[source] FsDeviceError),
#[cfg(feature = "hotplug")]
/// The action `ResizeVcpu` Failed
#[error("vcpu resize error : {0}")]
ResizeVcpu(#[source] VcpuResizeError),
} }
/// This enum represents the public interface of the VMM. Each action contains various /// This enum represents the public interface of the VMM. Each action contains various
@@ -156,6 +168,10 @@ pub enum VmmAction {
#[cfg(feature = "virtio-fs")] #[cfg(feature = "virtio-fs")]
/// Update fs rate limiter, after microVM start. /// Update fs rate limiter, after microVM start.
UpdateFsDevice(FsDeviceConfigUpdateInfo), UpdateFsDevice(FsDeviceConfigUpdateInfo),
#[cfg(feature = "hotplug")]
/// Resize Vcpu number in the guest.
ResizeVcpu(VcpuResizeInfo),
} }
/// The enum represents the response sent by the VMM in case of success. The response is either /// The enum represents the response sent by the VMM in case of success. The response is either
@@ -256,6 +272,8 @@ impl VmmService {
VmmAction::UpdateFsDevice(fs_update_cfg) => { VmmAction::UpdateFsDevice(fs_update_cfg) => {
self.update_fs_rate_limiters(vmm, fs_update_cfg) self.update_fs_rate_limiters(vmm, fs_update_cfg)
} }
#[cfg(feature = "hotplug")]
VmmAction::ResizeVcpu(vcpu_resize_cfg) => self.resize_vcpu(vmm, vcpu_resize_cfg),
}; };
debug!("send vmm response: {:?}", response); debug!("send vmm response: {:?}", response);
@@ -462,8 +480,8 @@ impl VmmService {
let ctx = vm let ctx = vm
.create_device_op_context(Some(event_mgr.epoll_manager())) .create_device_op_context(Some(event_mgr.epoll_manager()))
.map_err(|e| { .map_err(|e| {
if let StartMicroVmError::UpcallNotReady = e { if let StartMicroVmError::UpcallServerNotReady = e {
return VmmActionError::UpcallNotReady; return VmmActionError::UpcallServerNotReady;
} }
VmmActionError::Block(BlockDeviceError::UpdateNotAllowedPostBoot) VmmActionError::Block(BlockDeviceError::UpdateNotAllowedPostBoot)
})?; })?;
@@ -518,8 +536,8 @@ impl VmmService {
.map_err(|e| { .map_err(|e| {
if let StartMicroVmError::MicroVMAlreadyRunning = e { if let StartMicroVmError::MicroVMAlreadyRunning = e {
VmmActionError::VirtioNet(VirtioNetDeviceError::UpdateNotAllowedPostBoot) VmmActionError::VirtioNet(VirtioNetDeviceError::UpdateNotAllowedPostBoot)
} else if let StartMicroVmError::UpcallNotReady = e { } else if let StartMicroVmError::UpcallServerNotReady = e {
VmmActionError::UpcallNotReady VmmActionError::UpcallServerNotReady
} else { } else {
VmmActionError::StartMicroVm(e) VmmActionError::StartMicroVm(e)
} }
@@ -595,6 +613,37 @@ impl VmmService {
.map(|_| VmmData::Empty) .map(|_| VmmData::Empty)
.map_err(VmmActionError::FsDevice) .map_err(VmmActionError::FsDevice)
} }
#[cfg(feature = "hotplug")]
fn resize_vcpu(&mut self, vmm: &mut Vmm, config: VcpuResizeInfo) -> VmmRequestResult {
if !cfg!(target_arch = "x86_64") {
// TODO: Arm need to support vcpu hotplug. issue: #6010
warn!("This arch do not support vm resize!");
return Ok(VmmData::Empty);
}
if !cfg!(feature = "dbs-upcall") {
warn!("We only support cpu resize through upcall server in the guest kernel now, please enable dbs-upcall feature.");
return Ok(VmmData::Empty);
}
let vm = vmm.get_vm_mut().ok_or(VmmActionError::VmNotExist)?;
if !vm.is_vm_initialized() {
return Err(VmmActionError::ResizeVcpu(
VcpuResizeError::UpdateNotAllowedPreBoot,
));
}
vm.resize_vcpu(config, None).map_err(|e| {
if let VcpuResizeError::UpcallServerNotReady = e {
return VmmActionError::UpcallServerNotReady;
}
VmmActionError::ResizeVcpu(e)
})?;
Ok(VmmData::Empty)
}
} }
fn handle_cpu_topology( fn handle_cpu_topology(

View File

@@ -100,7 +100,7 @@ pub enum StartMicroVmError {
/// Upcall is not ready /// Upcall is not ready
#[error("the upcall client is not ready")] #[error("the upcall client is not ready")]
UpcallNotReady, UpcallServerNotReady,
/// Configuration passed in is invalidate. /// Configuration passed in is invalidate.
#[error("invalid virtual machine configuration: {0} ")] #[error("invalid virtual machine configuration: {0} ")]

View File

@@ -10,7 +10,10 @@ mod vcpu_manager;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use dbs_arch::cpuid::VpmuFeatureLevel; use dbs_arch::cpuid::VpmuFeatureLevel;
pub use vcpu_manager::{VcpuManager, VcpuManagerError}; pub use vcpu_manager::{VcpuManager, VcpuManagerError, VcpuResizeInfo};
#[cfg(feature = "hotplug")]
pub use vcpu_manager::VcpuResizeError;
/// vcpu config collection /// vcpu config collection
pub struct VcpuConfig { pub struct VcpuConfig {

View File

@@ -214,10 +214,20 @@ pub enum VcpuResponse {
CacheRevalidated, CacheRevalidated,
} }
#[derive(Debug, PartialEq)]
/// Vcpu Hotplug Result returned from the guest
pub enum VcpuResizeResult {
/// All vCPU hotplug / hot-unplug operations are successful
Success = 0,
/// vCPU hotplug / hot-unplug failed
Failed = 1,
}
/// List of events that the vcpu_state_sender can send. /// List of events that the vcpu_state_sender can send.
pub enum VcpuStateEvent { pub enum VcpuStateEvent {
/// (result, response) for hotplug, result 0 means failure, 1 means success. /// (result, response) for hotplug / hot-unplugged.
Hotplug((i32, u32)), /// response records how many cpu has successfully being hotplugged / hot-unplugged.
Hotplug((VcpuResizeResult, u32)),
} }
/// Wrapper over vCPU that hides the underlying interactions with the vCPU thread. /// Wrapper over vCPU that hides the underlying interactions with the vCPU thread.

View File

@@ -29,7 +29,7 @@ use crate::address_space_manager::GuestAddressSpaceImpl;
use crate::api::v1::InstanceInfo; use crate::api::v1::InstanceInfo;
use crate::kvm_context::KvmContext; use crate::kvm_context::KvmContext;
use crate::vcpu::vcpu_impl::{ use crate::vcpu::vcpu_impl::{
Vcpu, VcpuError, VcpuEvent, VcpuHandle, VcpuResponse, VcpuStateEvent, Vcpu, VcpuError, VcpuEvent, VcpuHandle, VcpuResizeResult, VcpuResponse, VcpuStateEvent,
}; };
use crate::vcpu::VcpuConfig; use crate::vcpu::VcpuConfig;
use crate::vm::VmConfigInfo; use crate::vm::VmConfigInfo;
@@ -113,11 +113,6 @@ pub enum VcpuManagerError {
#[error("vcpu internal error: {0}")] #[error("vcpu internal error: {0}")]
Vcpu(#[source] VcpuError), Vcpu(#[source] VcpuError),
#[cfg(feature = "hotplug")]
/// vCPU resize error
#[error("resize vcpu error: {0}")]
VcpuResize(#[source] VcpuResizeError),
/// Kvm Ioctl Error /// Kvm Ioctl Error
#[error("failure in issuing KVM ioctl command: {0}")] #[error("failure in issuing KVM ioctl command: {0}")]
Kvm(#[source] kvm_ioctls::Error), Kvm(#[source] kvm_ioctls::Error),
@@ -132,6 +127,10 @@ pub enum VcpuResizeError {
VcpuIsHotplugging, VcpuIsHotplugging,
/// Cannot update the configuration of the microvm pre boot. /// Cannot update the configuration of the microvm pre boot.
#[error("resize vcpu operation is not allowed pre boot")]
UpdateNotAllowedPreBoot,
/// Cannot update the configuration of the microvm post boot.
#[error("resize vcpu operation is not allowed after boot")] #[error("resize vcpu operation is not allowed after boot")]
UpdateNotAllowedPostBoot, UpdateNotAllowedPostBoot,
@@ -147,10 +146,24 @@ pub enum VcpuResizeError {
#[error("Removable vcpu not enough, removable vcpu num: {0}, number to remove: {1}, present vcpu count {2}")] #[error("Removable vcpu not enough, removable vcpu num: {0}, number to remove: {1}, present vcpu count {2}")]
LackRemovableVcpus(u16, u16, u16), LackRemovableVcpus(u16, u16, u16),
#[cfg(all(feature = "hotplug", feature = "dbs-upcall"))] #[cfg(feature = "dbs-upcall")]
/// Cannot update the configuration by upcall channel. /// Cannot update the configuration by upcall channel.
#[error("cannot update the configuration by upcall channel: {0}")] #[error("cannot update the configuration by upcall channel: {0}")]
Upcall(#[source] dbs_upcall::UpcallClientError), Upcall(#[source] dbs_upcall::UpcallClientError),
#[cfg(feature = "dbs-upcall")]
/// Cannot find upcall client
#[error("Cannot find upcall client")]
UpcallClientMissing,
#[cfg(feature = "dbs-upcall")]
/// Upcall server is not ready
#[error("Upcall server is not ready")]
UpcallServerNotReady,
/// Vcpu manager error
#[error("Vcpu manager error : {0}")]
Vcpu(#[source] VcpuManagerError),
} }
/// Result for vCPU manager operations /// Result for vCPU manager operations
@@ -163,6 +176,13 @@ enum VcpuAction {
Hotunplug, Hotunplug,
} }
/// VcpuResizeInfo describes the information for vcpu hotplug / hot-unplug
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct VcpuResizeInfo {
/// The desired vcpu count to resize.
pub vcpu_count: Option<u8>,
}
/// Infos related to per vcpu /// Infos related to per vcpu
#[derive(Default)] #[derive(Default)]
pub(crate) struct VcpuInfo { pub(crate) struct VcpuInfo {
@@ -810,11 +830,9 @@ mod hotplug {
&mut self, &mut self,
vcpu_count: u8, vcpu_count: u8,
sync_tx: Option<Sender<bool>>, sync_tx: Option<Sender<bool>>,
) -> std::result::Result<(), VcpuManagerError> { ) -> std::result::Result<(), VcpuResizeError> {
if self.get_vcpus_action() != VcpuAction::None { if self.get_vcpus_action() != VcpuAction::None {
return Err(VcpuManagerError::VcpuResize( return Err(VcpuResizeError::VcpuIsHotplugging);
VcpuResizeError::VcpuIsHotplugging,
));
} }
self.action_sycn_tx = sync_tx; self.action_sycn_tx = sync_tx;
@@ -831,9 +849,7 @@ mod hotplug {
Ordering::Less => self.do_del_vcpu(vcpu_count, upcall), Ordering::Less => self.do_del_vcpu(vcpu_count, upcall),
} }
} else { } else {
Err(VcpuManagerError::VcpuResize( Err(VcpuResizeError::UpdateNotAllowedPostBoot)
VcpuResizeError::UpdateNotAllowedPostBoot,
))
} }
} }
@@ -841,28 +857,31 @@ mod hotplug {
&mut self, &mut self,
vcpu_count: u8, vcpu_count: u8,
upcall_client: Arc<UpcallClient<DevMgrService>>, upcall_client: Arc<UpcallClient<DevMgrService>>,
) -> std::result::Result<(), VcpuManagerError> { ) -> std::result::Result<(), VcpuResizeError> {
info!("resize vcpu: add"); info!("resize vcpu: add");
if vcpu_count > self.vcpu_config.max_vcpu_count { if vcpu_count > self.vcpu_config.max_vcpu_count {
return Err(VcpuManagerError::VcpuResize( return Err(VcpuResizeError::ExpectedVcpuExceedMax);
VcpuResizeError::ExpectedVcpuExceedMax,
));
} }
let created_vcpus = self.create_vcpus(vcpu_count, None, None)?; let created_vcpus = self
let cpu_ids = self.activate_vcpus(vcpu_count, true).map_err(|e| { .create_vcpus(vcpu_count, None, None)
// we need to rollback when activate vcpu error .map_err(VcpuResizeError::Vcpu)?;
error!("activate vcpu error, rollback! {:?}", e); let cpu_ids = self
let activated_vcpus: Vec<u8> = created_vcpus .activate_vcpus(vcpu_count, true)
.iter() .map_err(|e| {
.filter(|&cpu_id| self.vcpu_infos[*cpu_id as usize].handle.is_some()) // we need to rollback when activate vcpu error
.copied() error!("activate vcpu error, rollback! {:?}", e);
.collect(); let activated_vcpus: Vec<u8> = created_vcpus
if let Err(e) = self.exit_vcpus(&activated_vcpus) { .iter()
error!("try to rollback error, stop_vcpu: {:?}", e); .filter(|&cpu_id| self.vcpu_infos[*cpu_id as usize].handle.is_some())
} .copied()
e .collect();
})?; if let Err(e) = self.exit_vcpus(&activated_vcpus) {
error!("try to rollback error, stop_vcpu: {:?}", e);
}
e
})
.map_err(VcpuResizeError::Vcpu)?;
let mut cpu_ids_array = [0u8; (u8::MAX as usize) + 1]; let mut cpu_ids_array = [0u8; (u8::MAX as usize) + 1];
cpu_ids_array[..cpu_ids.len()].copy_from_slice(&cpu_ids[..cpu_ids.len()]); cpu_ids_array[..cpu_ids.len()].copy_from_slice(&cpu_ids[..cpu_ids.len()]);
@@ -882,23 +901,19 @@ mod hotplug {
&mut self, &mut self,
vcpu_count: u8, vcpu_count: u8,
upcall_client: Arc<UpcallClient<DevMgrService>>, upcall_client: Arc<UpcallClient<DevMgrService>>,
) -> std::result::Result<(), VcpuManagerError> { ) -> std::result::Result<(), VcpuResizeError> {
info!("resize vcpu: delete"); info!("resize vcpu: delete");
if vcpu_count == 0 { if vcpu_count == 0 {
return Err(VcpuManagerError::VcpuResize( return Err(VcpuResizeError::Vcpu0CanNotBeRemoved);
VcpuResizeError::Vcpu0CanNotBeRemoved,
));
} }
let mut cpu_ids = self.calculate_removable_vcpus(); let mut cpu_ids = self.calculate_removable_vcpus();
let cpu_num_to_be_del = (self.present_vcpus_count() - vcpu_count) as usize; let cpu_num_to_be_del = (self.present_vcpus_count() - vcpu_count) as usize;
if cpu_num_to_be_del >= cpu_ids.len() { if cpu_num_to_be_del >= cpu_ids.len() {
return Err(VcpuManagerError::VcpuResize( return Err(VcpuResizeError::LackRemovableVcpus(
VcpuResizeError::LackRemovableVcpus( cpu_ids.len() as u16,
cpu_ids.len() as u16, cpu_num_to_be_del as u16,
cpu_num_to_be_del as u16, self.present_vcpus_count() as u16,
self.present_vcpus_count() as u16,
),
)); ));
} }
@@ -924,7 +939,7 @@ mod hotplug {
&self, &self,
_upcall_client: Arc<UpcallClient<DevMgrService>>, _upcall_client: Arc<UpcallClient<DevMgrService>>,
_request: DevMgrRequest, _request: DevMgrRequest,
) -> std::result::Result<(), VcpuManagerError> { ) -> std::result::Result<(), VcpuResizeError> {
Ok(()) Ok(())
} }
@@ -933,7 +948,7 @@ mod hotplug {
&self, &self,
upcall_client: Arc<UpcallClient<DevMgrService>>, upcall_client: Arc<UpcallClient<DevMgrService>>,
request: DevMgrRequest, request: DevMgrRequest,
) -> std::result::Result<(), VcpuManagerError> { ) -> std::result::Result<(), VcpuResizeError> {
// This is used to fix clippy warnings. // This is used to fix clippy warnings.
use dbs_upcall::{DevMgrResponse, UpcallClientRequest, UpcallClientResponse}; use dbs_upcall::{DevMgrResponse, UpcallClientRequest, UpcallClientResponse};
@@ -946,9 +961,14 @@ mod hotplug {
Box::new(move |result| match result { Box::new(move |result| match result {
UpcallClientResponse::DevMgr(response) => { UpcallClientResponse::DevMgr(response) => {
if let DevMgrResponse::CpuDev(resp) = response { if let DevMgrResponse::CpuDev(resp) = response {
let result: VcpuResizeResult = if resp.result == 0 {
VcpuResizeResult::Success
} else {
VcpuResizeResult::Failed
};
vcpu_state_sender vcpu_state_sender
.send(VcpuStateEvent::Hotplug(( .send(VcpuStateEvent::Hotplug((
resp.result, result,
resp.info.apic_id_index, resp.info.apic_id_index,
))) )))
.unwrap(); .unwrap();
@@ -957,7 +977,7 @@ mod hotplug {
} }
UpcallClientResponse::UpcallReset => { UpcallClientResponse::UpcallReset => {
vcpu_state_sender vcpu_state_sender
.send(VcpuStateEvent::Hotplug((0, 0))) .send(VcpuStateEvent::Hotplug((VcpuResizeResult::Success, 0)))
.unwrap(); .unwrap();
vcpu_state_event.write(1).unwrap(); vcpu_state_event.write(1).unwrap();
} }
@@ -968,7 +988,6 @@ mod hotplug {
}), }),
) )
.map_err(VcpuResizeError::Upcall) .map_err(VcpuResizeError::Upcall)
.map_err(VcpuManagerError::VcpuResize)
} }
/// Get removable vcpus. /// Get removable vcpus.
@@ -993,16 +1012,19 @@ impl VcpuEpollHandler {
while let Ok(event) = self.rx.try_recv() { while let Ok(event) = self.rx.try_recv() {
match event { match event {
VcpuStateEvent::Hotplug((success, cpu_count)) => { VcpuStateEvent::Hotplug((success, cpu_count)) => {
info!("get vcpu event, cpu_index {}", cpu_count); info!(
self.process_cpu_action(success != 0, cpu_count); "get vcpu event, cpu_index {} success {:?}",
cpu_count, success
);
self.process_cpu_action(success, cpu_count);
} }
} }
} }
} }
fn process_cpu_action(&self, success: bool, _cpu_index: u32) { fn process_cpu_action(&self, result: VcpuResizeResult, _cpu_index: u32) {
let mut vcpu_manager = self.vcpu_manager.lock().unwrap(); let mut vcpu_manager = self.vcpu_manager.lock().unwrap();
if success { if result == VcpuResizeResult::Success {
match vcpu_manager.get_vcpus_action() { match vcpu_manager.get_vcpus_action() {
VcpuAction::Hotplug => { VcpuAction::Hotplug => {
// Notify hotplug success // Notify hotplug success
@@ -1362,12 +1384,7 @@ mod tests {
// vcpu is already in hotplug process // vcpu is already in hotplug process
let res = vcpu_manager.resize_vcpu(1, None); let res = vcpu_manager.resize_vcpu(1, None);
assert!(matches!( assert!(matches!(res, Err(VcpuResizeError::VcpuIsHotplugging)));
res,
Err(VcpuManagerError::VcpuResize(
VcpuResizeError::VcpuIsHotplugging
))
));
// clear vcpus action // clear vcpus action
let cpu_ids = vec![0]; let cpu_ids = vec![0];
@@ -1377,9 +1394,7 @@ mod tests {
let res = vcpu_manager.resize_vcpu(1, None); let res = vcpu_manager.resize_vcpu(1, None);
assert!(matches!( assert!(matches!(
res, res,
Err(VcpuManagerError::VcpuResize( Err(VcpuResizeError::UpdateNotAllowedPostBoot)
VcpuResizeError::UpdateNotAllowedPostBoot
))
)); ));
// init upcall channel // init upcall channel
@@ -1397,20 +1412,10 @@ mod tests {
// exceeed max vcpu count // exceeed max vcpu count
let res = vcpu_manager.resize_vcpu(4, None); let res = vcpu_manager.resize_vcpu(4, None);
assert!(matches!( assert!(matches!(res, Err(VcpuResizeError::ExpectedVcpuExceedMax)));
res,
Err(VcpuManagerError::VcpuResize(
VcpuResizeError::ExpectedVcpuExceedMax
))
));
// remove vcpu 0 // remove vcpu 0
let res = vcpu_manager.resize_vcpu(0, None); let res = vcpu_manager.resize_vcpu(0, None);
assert!(matches!( assert!(matches!(res, Err(VcpuResizeError::Vcpu0CanNotBeRemoved)));
res,
Err(VcpuManagerError::VcpuResize(
VcpuResizeError::Vcpu0CanNotBeRemoved
))
));
} }
} }

View File

@@ -4,6 +4,7 @@
use std::io::{self, Read, Seek, SeekFrom}; use std::io::{self, Read, Seek, SeekFrom};
use std::ops::Deref; use std::ops::Deref;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use dbs_address_space::AddressSpace; use dbs_address_space::AddressSpace;
@@ -22,6 +23,8 @@ use vmm_sys_util::eventfd::EventFd;
#[cfg(all(feature = "hotplug", feature = "dbs-upcall"))] #[cfg(all(feature = "hotplug", feature = "dbs-upcall"))]
use dbs_upcall::{DevMgrService, UpcallClient}; use dbs_upcall::{DevMgrService, UpcallClient};
#[cfg(feature = "hotplug")]
use std::sync::mpsc::Sender;
use crate::address_space_manager::{ use crate::address_space_manager::{
AddressManagerError, AddressSpaceMgr, AddressSpaceMgrBuilder, GuestAddressSpaceImpl, AddressManagerError, AddressSpaceMgr, AddressSpaceMgrBuilder, GuestAddressSpaceImpl,
@@ -35,6 +38,8 @@ use crate::event_manager::EventManager;
use crate::kvm_context::KvmContext; use crate::kvm_context::KvmContext;
use crate::resource_manager::ResourceManager; use crate::resource_manager::ResourceManager;
use crate::vcpu::{VcpuManager, VcpuManagerError}; use crate::vcpu::{VcpuManager, VcpuManagerError};
#[cfg(feature = "hotplug")]
use crate::vcpu::{VcpuResizeError, VcpuResizeInfo};
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
use dbs_arch::gic::Error as GICError; use dbs_arch::gic::Error as GICError;
@@ -795,7 +800,30 @@ impl Vm {
} else if self.is_upcall_client_ready() { } else if self.is_upcall_client_ready() {
Ok(DeviceOpContext::create_hotplug_ctx(self, epoll_mgr)) Ok(DeviceOpContext::create_hotplug_ctx(self, epoll_mgr))
} else { } else {
Err(StartMicroVmError::UpcallNotReady) Err(StartMicroVmError::UpcallServerNotReady)
}
}
/// Resize MicroVM vCPU number
#[cfg(feature = "hotplug")]
pub fn resize_vcpu(
&mut self,
config: VcpuResizeInfo,
sync_tx: Option<Sender<bool>>,
) -> std::result::Result<(), VcpuResizeError> {
if self.upcall_client().is_none() {
Err(VcpuResizeError::UpcallClientMissing)
} else if self.is_upcall_client_ready() {
if let Some(vcpu_count) = config.vcpu_count {
self.vcpu_manager()
.map_err(VcpuResizeError::Vcpu)?
.resize_vcpu(vcpu_count, sync_tx)?;
self.vm_config.vcpu_count = vcpu_count;
}
Ok(())
} else {
Err(VcpuResizeError::UpcallServerNotReady)
} }
} }

View File

@@ -314,7 +314,7 @@ impl VmmInstance {
return Ok(vmm_data); return Ok(vmm_data);
} }
Err(vmm_action_error) => { Err(vmm_action_error) => {
if let VmmActionError::UpcallNotReady = vmm_action_error { if let VmmActionError::UpcallServerNotReady = vmm_action_error {
std::thread::sleep(std::time::Duration::from_millis(10)); std::thread::sleep(std::time::Duration::from_millis(10));
continue; continue;
} else { } else {