diff --git a/src/main.rs b/src/main.rs index 018a740aa..85951eedf 100755 --- a/src/main.rs +++ b/src/main.rs @@ -377,7 +377,7 @@ fn main() { vmm::api::vm_create( api_evt.try_clone().unwrap(), api_request_sender, - Arc::new(vm_config), + Arc::new(Mutex::new(vm_config)), ) .expect("Could not create the VM"); vmm::api::vm_boot(api_evt.try_clone().unwrap(), sender).expect("Could not boot the VM"); diff --git a/vmm/src/api/http_endpoint.rs b/vmm/src/api/http_endpoint.rs index d0a0effbe..bab243df4 100644 --- a/vmm/src/api/http_endpoint.rs +++ b/vmm/src/api/http_endpoint.rs @@ -11,7 +11,7 @@ use crate::api::{ use micro_http::{Body, Method, Request, Response, StatusCode, Version}; use serde_json::Error as SerdeError; use std::sync::mpsc::Sender; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use vmm_sys_util::eventfd::EventFd; /// Errors associated with VMM management @@ -81,7 +81,7 @@ impl EndpointHandler for VmCreate { }; // Call vm_create() - match vm_create(api_notifier, api_sender, Arc::new(vm_config)) + match vm_create(api_notifier, api_sender, Arc::new(Mutex::new(vm_config))) .map_err(HttpError::VmCreate) { Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), diff --git a/vmm/src/api/mod.rs b/vmm/src/api/mod.rs index aa8f4c200..82a50f118 100644 --- a/vmm/src/api/mod.rs +++ b/vmm/src/api/mod.rs @@ -40,7 +40,7 @@ use crate::config::VmConfig; use crate::vm::{Error as VmError, VmState}; use std::io; use std::sync::mpsc::{channel, RecvError, SendError, Sender}; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use vmm_sys_util::eventfd::EventFd; /// API errors are sent back from the VMM API server through the ApiResponse. @@ -104,7 +104,7 @@ pub type ApiResult = std::result::Result; #[derive(Clone, Deserialize, Serialize)] pub struct VmInfo { - pub config: Arc, + pub config: Arc>, pub state: VmState, } @@ -138,7 +138,7 @@ pub enum ApiRequest { /// (VmConfig). /// If the VMM API server could not create the VM, it will send a VmCreate /// error back. - VmCreate(Arc, Sender), + VmCreate(Arc>, Sender), /// Boot the previously created virtual machine. /// If the VM was not previously created, the VMM API server will send a @@ -185,7 +185,7 @@ pub enum ApiRequest { pub fn vm_create( api_evt: EventFd, api_sender: Sender, - config: Arc, + config: Arc>, ) -> ApiResult<()> { let (response_sender, response_receiver) = channel(); diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index eac7dd66d..b7d42505d 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -525,7 +525,7 @@ impl DeviceManager { Arc::downgrade(&address_manager) as Weak, ); - let (mut iommu_device, iommu_mapping) = if vm_info.vm_cfg.iommu { + let (mut iommu_device, iommu_mapping) = if vm_info.vm_cfg.lock().unwrap().iommu { let (device, mapping) = vm_virtio::Iommu::new().map_err(DeviceManagerError::CreateVirtioIommu)?; (Some(device), Some(mapping)) @@ -765,15 +765,16 @@ impl DeviceManager { ioapic: &Option>>, virtio_devices: &mut Vec<(Box, bool)>, ) -> DeviceManagerResult> { - let serial_writer: Option> = match vm_info.vm_cfg.serial.mode { + let serial_config = vm_info.vm_cfg.lock().unwrap().serial.clone(); + let serial_writer: Option> = match serial_config.mode { ConsoleOutputMode::File => Some(Box::new( - File::create(vm_info.vm_cfg.serial.file.as_ref().unwrap()) + File::create(serial_config.file.as_ref().unwrap()) .map_err(DeviceManagerError::SerialOutputFileOpen)?, )), ConsoleOutputMode::Tty => Some(Box::new(stdout())), ConsoleOutputMode::Off | ConsoleOutputMode::Null => None, }; - let serial = if vm_info.vm_cfg.serial.mode != ConsoleOutputMode::Off { + let serial = if serial_config.mode != ConsoleOutputMode::Off { // Serial is tied to IRQ #4 let serial_irq = 4; let interrupt: Box = if let Some(ioapic) = &ioapic { @@ -811,20 +812,29 @@ impl DeviceManager { }; // Create serial and virtio-console - let console_writer: Option> = - match vm_info.vm_cfg.console.mode { - ConsoleOutputMode::File => Some(Box::new( - File::create(vm_info.vm_cfg.console.file.as_ref().unwrap()) - .map_err(DeviceManagerError::ConsoleOutputFileOpen)?, - )), - ConsoleOutputMode::Tty => Some(Box::new(stdout())), - ConsoleOutputMode::Null => Some(Box::new(sink())), - ConsoleOutputMode::Off => None, - }; + let console_config = vm_info.vm_cfg.lock().unwrap().console.clone(); + let console_writer: Option> = match console_config.mode { + ConsoleOutputMode::File => Some(Box::new( + File::create( + vm_info + .vm_cfg + .lock() + .unwrap() + .console + .file + .as_ref() + .unwrap(), + ) + .map_err(DeviceManagerError::ConsoleOutputFileOpen)?, + )), + ConsoleOutputMode::Tty => Some(Box::new(stdout())), + ConsoleOutputMode::Null => Some(Box::new(sink())), + ConsoleOutputMode::Off => None, + }; let (col, row) = get_win_size(); let console_input = if let Some(writer) = console_writer { let (virtio_console_device, console_input) = - vm_virtio::Console::new(writer, col, row, vm_info.vm_cfg.console.iommu) + vm_virtio::Console::new(writer, col, row, console_config.iommu) .map_err(DeviceManagerError::CreateVirtioConsole)?; virtio_devices.push(( Box::new(virtio_console_device) as Box, @@ -838,8 +848,8 @@ impl DeviceManager { Ok(Arc::new(Console { serial, console_input, - input_enabled: vm_info.vm_cfg.serial.mode.input_enabled() - || vm_info.vm_cfg.console.mode.input_enabled(), + input_enabled: serial_config.mode.input_enabled() + || console_config.mode.input_enabled(), })) } @@ -894,7 +904,7 @@ impl DeviceManager { ) -> DeviceManagerResult, bool)>> { let mut devices = Vec::new(); - if let Some(disk_list_cfg) = &vm_info.vm_cfg.disks { + if let Some(disk_list_cfg) = &vm_info.vm_cfg.lock().unwrap().disks { for disk_cfg in disk_list_cfg.iter() { // Open block device path let raw_img: File = OpenOptions::new() @@ -944,7 +954,7 @@ impl DeviceManager { let mut devices = Vec::new(); // Add virtio-net if required - if let Some(net_list_cfg) = &vm_info.vm_cfg.net { + if let Some(net_list_cfg) = &vm_info.vm_cfg.lock().unwrap().net { for net_cfg in net_list_cfg.iter() { let virtio_net_device = if let Some(ref tap_if_name) = net_cfg.tap { let tap = Tap::open_named(tap_if_name).map_err(DeviceManagerError::OpenTap)?; @@ -971,8 +981,9 @@ impl DeviceManager { let mut devices = Vec::new(); // Add virtio-rng if required - if let Some(rng_path) = vm_info.vm_cfg.rng.src.to_str() { - let virtio_rng_device = vm_virtio::Rng::new(rng_path, vm_info.vm_cfg.rng.iommu) + let rng_config = vm_info.vm_cfg.lock().unwrap().rng.clone(); + if let Some(rng_path) = rng_config.src.to_str() { + let virtio_rng_device = vm_virtio::Rng::new(rng_path, rng_config.iommu) .map_err(DeviceManagerError::CreateVirtioRng)?; devices.push(( Box::new(virtio_rng_device) as Box, @@ -991,7 +1002,7 @@ impl DeviceManager { ) -> DeviceManagerResult, bool)>> { let mut devices = Vec::new(); // Add virtio-fs if required - if let Some(fs_list_cfg) = &vm_info.vm_cfg.fs { + if let Some(fs_list_cfg) = &vm_info.vm_cfg.lock().unwrap().fs { for fs_cfg in fs_list_cfg.iter() { if let Some(fs_sock) = fs_cfg.sock.to_str() { let mut cache: Option<(VirtioSharedMemoryList, u64)> = None; @@ -1078,7 +1089,7 @@ impl DeviceManager { ) -> DeviceManagerResult, bool)>> { let mut devices = Vec::new(); // Add virtio-pmem if required - if let Some(pmem_list_cfg) = &vm_info.vm_cfg.pmem { + if let Some(pmem_list_cfg) = &vm_info.vm_cfg.lock().unwrap().pmem { for pmem_cfg in pmem_list_cfg.iter() { let size = pmem_cfg.size; @@ -1176,7 +1187,7 @@ impl DeviceManager { ) -> DeviceManagerResult, bool)>> { let mut devices = Vec::new(); // Add vhost-user-net if required - if let Some(vhost_user_net_list_cfg) = &vm_info.vm_cfg.vhost_user_net { + if let Some(vhost_user_net_list_cfg) = &vm_info.vm_cfg.lock().unwrap().vhost_user_net { for vhost_user_net_cfg in vhost_user_net_list_cfg.iter() { let vu_cfg = VhostUserConfig { sock: vhost_user_net_cfg.vu_cfg.sock.clone(), @@ -1202,7 +1213,7 @@ impl DeviceManager { ) -> DeviceManagerResult, bool)>> { let mut devices = Vec::new(); // Add vhost-user-blk if required - if let Some(vhost_user_blk_list_cfg) = &vm_info.vm_cfg.vhost_user_blk { + if let Some(vhost_user_blk_list_cfg) = &vm_info.vm_cfg.lock().unwrap().vhost_user_blk { for vhost_user_blk_cfg in vhost_user_blk_list_cfg.iter() { let vu_cfg = VhostUserConfig { sock: vhost_user_blk_cfg.vu_cfg.sock.clone(), @@ -1228,7 +1239,7 @@ impl DeviceManager { ) -> DeviceManagerResult, bool)>> { let mut devices = Vec::new(); // Add vsock if required - if let Some(vsock_list_cfg) = &vm_info.vm_cfg.vsock { + if let Some(vsock_list_cfg) = &vm_info.vm_cfg.lock().unwrap().vsock { for vsock_cfg in vsock_list_cfg.iter() { let socket_path = vsock_cfg .sock @@ -1282,7 +1293,7 @@ impl DeviceManager { let gsi_msi_routes: Arc>> = Arc::new(Mutex::new(HashMap::new())); - if let Some(device_list_cfg) = &vm_info.vm_cfg.devices { + if let Some(device_list_cfg) = &vm_info.vm_cfg.lock().unwrap().devices { // Create the KVM VFIO device let device_fd = DeviceManager::create_kvm_device(vm_info.vm_fd)?; let device_fd = Arc::new(device_fd); diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 08a08e7ab..247744c37 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -21,7 +21,7 @@ use libc::EFD_NONBLOCK; use std::io; use std::os::unix::io::{AsRawFd, RawFd}; use std::sync::mpsc::{Receiver, RecvError, SendError, Sender}; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use std::{result, thread}; use vmm_sys_util::eventfd::EventFd; @@ -178,7 +178,7 @@ pub struct Vmm { api_evt: EventFd, version: String, vm: Option, - vm_config: Option>, + vm_config: Option>>, } impl Vmm { diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 6b4ff5876..a89de5bbc 100755 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -151,7 +151,7 @@ pub type Result = result::Result; pub struct VmInfo<'a> { pub memory: &'a Arc>, pub vm_fd: &'a Arc, - pub vm_cfg: &'a VmConfig, + pub vm_cfg: Arc>, } #[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)] @@ -201,7 +201,7 @@ pub struct Vm { memory: Arc>, threads: Vec>, devices: DeviceManager, - config: Arc, + config: Arc>, on_tty: bool, signals: Option, state: RwLock, @@ -237,15 +237,19 @@ fn get_host_cpu_phys_bits() -> u8 { } impl Vm { - pub fn new(config: Arc, exit_evt: EventFd, reset_evt: EventFd) -> Result { + pub fn new( + config: Arc>, + exit_evt: EventFd, + reset_evt: EventFd, + ) -> Result { let kvm = Kvm::new().map_err(Error::KvmNew)?; - let kernel = - File::open(&config.kernel.as_ref().unwrap().path).map_err(Error::KernelFile)?; + let kernel = File::open(&config.lock().unwrap().kernel.as_ref().unwrap().path) + .map_err(Error::KernelFile)?; let fd = kvm.create_vm().map_err(Error::VmCreate)?; let fd = Arc::new(fd); // Init guest memory - let arch_mem_regions = arch::arch_memory_regions(config.memory.size); + let arch_mem_regions = arch::arch_memory_regions(config.lock().unwrap().memory.size); let ram_regions: Vec<(GuestAddress, usize)> = arch_mem_regions .iter() @@ -268,7 +272,7 @@ impl Vm { } } - let guest_memory = match config.memory.file { + let guest_memory = match config.lock().unwrap().memory.file { Some(ref file) => { let mut mem_regions = Vec::<(GuestAddress, usize, Option)>::new(); for region in ram_regions.iter() { @@ -321,7 +325,7 @@ impl Vm { }?; // Mark the pages as mergeable if explicitly asked for. - if config.memory.mergeable { + if config.lock().unwrap().memory.mergeable { // Safe because the address and size are valid since the // mmap succeeded. let ret = unsafe { @@ -448,7 +452,7 @@ impl Vm { let vm_info = VmInfo { memory: &guest_memory, vm_fd: &fd, - vm_cfg: &config, + vm_cfg: config.clone(), }; let device_manager = DeviceManager::new( @@ -464,8 +468,8 @@ impl Vm { let on_tty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0; - let boot_vcpus = config.cpus.boot_vcpus; - let max_vcpus = config.cpus.max_vcpus; + let boot_vcpus = config.lock().unwrap().cpus.boot_vcpus; + let max_vcpus = config.lock().unwrap().cpus.max_vcpus; let cpu_manager = cpu::CpuManager::new( boot_vcpus, max_vcpus, @@ -493,7 +497,7 @@ impl Vm { fn load_kernel(&mut self) -> Result { let mut cmdline = Cmdline::new(arch::CMDLINE_MAX_SIZE); cmdline - .insert_str(self.config.cmdline.args.clone()) + .insert_str(self.config.lock().unwrap().cmdline.args.clone()) .map_err(|_| Error::CmdLine)?; for entry in self.devices.cmdline_additions() { cmdline.insert_str(entry).map_err(|_| Error::CmdLine)?; @@ -549,7 +553,7 @@ impl Vm { &mem, boot_vcpus, _max_vcpus, - self.config.serial.mode != ConsoleOutputMode::Off, + self.config.lock().unwrap().serial.mode != ConsoleOutputMode::Off, start_of_device_area, end_of_range, self.devices.virt_iommu(), @@ -768,7 +772,7 @@ impl Vm { } /// Gets a thread-safe reference counted pointer to the VM configuration. - pub fn get_config(&self) -> Arc { + pub fn get_config(&self) -> Arc> { Arc::clone(&self.config) }