vmm: Move DeviceManager into an Arc<Mutex<>>

In anticipation of the support for device hotplug, this commit moves the
DeviceManager object into an Arc<Mutex<>> when the DeviceManager is
being created. The reason is, we need the DeviceManager to implement the
BusDevice trait and then provide it to the IO bus, so that IO accesses
related to device hotplug can be handled correctly.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2020-02-27 10:29:03 +01:00
parent 531f4ff6b0
commit 8142c823ed
4 changed files with 20 additions and 13 deletions

View File

@ -80,14 +80,14 @@ struct IortIdMapping {
} }
pub fn create_dsdt_table( pub fn create_dsdt_table(
device_manager: &DeviceManager, device_manager: &Arc<Mutex<DeviceManager>>,
cpu_manager: &Arc<Mutex<CpuManager>>, cpu_manager: &Arc<Mutex<CpuManager>>,
memory_manager: &Arc<Mutex<MemoryManager>>, memory_manager: &Arc<Mutex<MemoryManager>>,
) -> SDT { ) -> SDT {
// DSDT // DSDT
let mut dsdt = SDT::new(*b"DSDT", 36, 6, *b"CLOUDH", *b"CHDSDT ", 1); let mut dsdt = SDT::new(*b"DSDT", 36, 6, *b"CLOUDH", *b"CHDSDT ", 1);
dsdt.append_slice(device_manager.to_aml_bytes().as_slice()); dsdt.append_slice(device_manager.lock().unwrap().to_aml_bytes().as_slice());
dsdt.append_slice(cpu_manager.lock().unwrap().to_aml_bytes().as_slice()); dsdt.append_slice(cpu_manager.lock().unwrap().to_aml_bytes().as_slice());
dsdt.append_slice(memory_manager.lock().unwrap().to_aml_bytes().as_slice()); dsdt.append_slice(memory_manager.lock().unwrap().to_aml_bytes().as_slice());
@ -96,7 +96,7 @@ pub fn create_dsdt_table(
pub fn create_acpi_tables( pub fn create_acpi_tables(
guest_mem: &GuestMemoryMmap, guest_mem: &GuestMemoryMmap,
device_manager: &DeviceManager, device_manager: &Arc<Mutex<DeviceManager>>,
cpu_manager: &Arc<Mutex<CpuManager>>, cpu_manager: &Arc<Mutex<CpuManager>>,
memory_manager: &Arc<Mutex<MemoryManager>>, memory_manager: &Arc<Mutex<MemoryManager>>,
) -> GuestAddress { ) -> GuestAddress {

View File

@ -494,7 +494,7 @@ impl CpuManager {
pub fn new( pub fn new(
boot_vcpus: u8, boot_vcpus: u8,
max_vcpus: u8, max_vcpus: u8,
device_manager: &DeviceManager, device_manager: &Arc<Mutex<DeviceManager>>,
guest_memory: GuestMemoryAtomic<GuestMemoryMmap>, guest_memory: GuestMemoryAtomic<GuestMemoryMmap>,
fd: Arc<VmFd>, fd: Arc<VmFd>,
cpuid: CpuId, cpuid: CpuId,
@ -503,6 +503,7 @@ impl CpuManager {
let mut vcpu_states = Vec::with_capacity(usize::from(max_vcpus)); let mut vcpu_states = Vec::with_capacity(usize::from(max_vcpus));
vcpu_states.resize_with(usize::from(max_vcpus), VcpuState::default); vcpu_states.resize_with(usize::from(max_vcpus), VcpuState::default);
let device_manager = device_manager.lock().unwrap();
let cpu_manager = Arc::new(Mutex::new(CpuManager { let cpu_manager = Arc::new(Mutex::new(CpuManager {
boot_vcpus, boot_vcpus,
max_vcpus, max_vcpus,

View File

@ -440,7 +440,7 @@ impl DeviceManager {
_exit_evt: &EventFd, _exit_evt: &EventFd,
reset_evt: &EventFd, reset_evt: &EventFd,
vmm_path: PathBuf, vmm_path: PathBuf,
) -> DeviceManagerResult<Self> { ) -> DeviceManagerResult<Arc<Mutex<Self>>> {
let io_bus = devices::Bus::new(); let io_bus = devices::Bus::new();
let mmio_bus = devices::Bus::new(); let mmio_bus = devices::Bus::new();
@ -543,7 +543,7 @@ impl DeviceManager {
device_manager.virtio_devices = virtio_devices; device_manager.virtio_devices = virtio_devices;
Ok(device_manager) Ok(Arc::new(Mutex::new(device_manager)))
} }
#[allow(unused_variables)] #[allow(unused_variables)]

View File

@ -212,7 +212,7 @@ impl VmState {
pub struct Vm { pub struct Vm {
kernel: File, kernel: File,
threads: Vec<thread::JoinHandle<()>>, threads: Vec<thread::JoinHandle<()>>,
devices: DeviceManager, devices: Arc<Mutex<DeviceManager>>,
config: Arc<Mutex<VmConfig>>, config: Arc<Mutex<VmConfig>>,
on_tty: bool, on_tty: bool,
signals: Option<Signals>, signals: Option<Signals>,
@ -384,7 +384,7 @@ impl Vm {
cmdline cmdline
.insert_str(self.config.lock().unwrap().cmdline.args.clone()) .insert_str(self.config.lock().unwrap().cmdline.args.clone())
.map_err(Error::CmdLineInsertStr)?; .map_err(Error::CmdLineInsertStr)?;
for entry in self.devices.cmdline_additions() { for entry in self.devices.lock().unwrap().cmdline_additions() {
cmdline.insert_str(entry).map_err(Error::CmdLineInsertStr)?; cmdline.insert_str(entry).map_err(Error::CmdLineInsertStr)?;
} }
@ -513,6 +513,8 @@ impl Vm {
.map_err(Error::CpuManager)? .map_err(Error::CpuManager)?
{ {
self.devices self.devices
.lock()
.unwrap()
.notify_hotplug(HotPlugNotificationFlags::CPU_DEVICES_CHANGED) .notify_hotplug(HotPlugNotificationFlags::CPU_DEVICES_CHANGED)
.map_err(Error::DeviceManager)?; .map_err(Error::DeviceManager)?;
} }
@ -528,6 +530,8 @@ impl Vm {
.map_err(Error::MemoryManager)? .map_err(Error::MemoryManager)?
{ {
self.devices self.devices
.lock()
.unwrap()
.notify_hotplug(HotPlugNotificationFlags::MEMORY_DEVICES_CHANGED) .notify_hotplug(HotPlugNotificationFlags::MEMORY_DEVICES_CHANGED)
.map_err(Error::DeviceManager)?; .map_err(Error::DeviceManager)?;
} }
@ -574,8 +578,8 @@ impl Vm {
.start_boot_vcpus(entry_addr) .start_boot_vcpus(entry_addr)
.map_err(Error::CpuManager)?; .map_err(Error::CpuManager)?;
if self.devices.console().input_enabled() { if self.devices.lock().unwrap().console().input_enabled() {
let console = self.devices.console().clone(); let console = self.devices.lock().unwrap().console().clone();
let signals = Signals::new(&[SIGWINCH, SIGINT, SIGTERM]); let signals = Signals::new(&[SIGWINCH, SIGINT, SIGTERM]);
match signals { match signals {
Ok(signals) => { Ok(signals) => {
@ -613,8 +617,10 @@ impl Vm {
.read_raw(&mut out) .read_raw(&mut out)
.map_err(Error::Console)?; .map_err(Error::Console)?;
if self.devices.console().input_enabled() { if self.devices.lock().unwrap().console().input_enabled() {
self.devices self.devices
.lock()
.unwrap()
.console() .console()
.queue_input_bytes(&out[..count]) .queue_input_bytes(&out[..count])
.map_err(Error::Console)?; .map_err(Error::Console)?;
@ -650,7 +656,7 @@ impl Pausable for Vm {
.map_err(|e| MigratableError::Pause(anyhow!("Invalid transition: {:?}", e)))?; .map_err(|e| MigratableError::Pause(anyhow!("Invalid transition: {:?}", e)))?;
self.cpu_manager.lock().unwrap().pause()?; self.cpu_manager.lock().unwrap().pause()?;
self.devices.pause()?; self.devices.lock().unwrap().pause()?;
*state = new_state; *state = new_state;
@ -668,7 +674,7 @@ impl Pausable for Vm {
.valid_transition(new_state) .valid_transition(new_state)
.map_err(|e| MigratableError::Pause(anyhow!("Invalid transition: {:?}", e)))?; .map_err(|e| MigratableError::Pause(anyhow!("Invalid transition: {:?}", e)))?;
self.devices.resume()?; self.devices.lock().unwrap().resume()?;
self.cpu_manager.lock().unwrap().resume()?; self.cpu_manager.lock().unwrap().resume()?;
// And we're back to the Running state. // And we're back to the Running state.