From 34e09923a5a9e168c27e92330a37abc68c1deaef Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Fri, 28 Jun 2019 01:45:58 -0700 Subject: [PATCH] vmm: Add support for multiple virtio-pmem devices Until now, the VMM was only accepting a single instance of virtio-pmem device. This commit extend the virtio-pmem support by allowing several devices to be created for a single VM. Signed-off-by: Sebastien Boeuf --- src/main.rs | 5 ++- vmm/src/config.rs | 27 +++++++----- vmm/src/vm.rs | 110 +++++++++++++++++++++++----------------------- 3 files changed, 75 insertions(+), 67 deletions(-) diff --git a/src/main.rs b/src/main.rs index f6f59d27c..f546d1f74 100755 --- a/src/main.rs +++ b/src/main.rs @@ -84,7 +84,8 @@ fn main() { "Persistent memory parameters \"file=,\ size=\"", ) - .takes_value(true), + .takes_value(true) + .min_values(1), ) .get_matches(); @@ -110,7 +111,7 @@ fn main() { let fs: Option> = cmd_arguments.values_of("fs").map(|x| x.collect()); - let pmem = cmd_arguments.value_of("pmem"); + let pmem: Option> = cmd_arguments.values_of("pmem").map(|x| x.collect()); let vm_config = match config::VmConfig::parse(config::VmParams { cpus, diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 6a2095705..d207cde19 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -64,7 +64,7 @@ pub struct VmParams<'a> { pub net: Option<&'a str>, pub rng: &'a str, pub fs: Option>, - pub pmem: Option<&'a str>, + pub pmem: Option>, } pub struct CpusConfig(pub u8); @@ -302,13 +302,9 @@ pub struct PmemConfig<'a> { } impl<'a> PmemConfig<'a> { - pub fn parse(pmem: Option<&'a str>) -> Result> { - if pmem.is_none() { - return Ok(None); - } - + pub fn parse(pmem: &'a str) -> Result { // Split the parameters based on the comma delimiter - let params_list: Vec<&str> = pmem.unwrap().split(',').collect(); + let params_list: Vec<&str> = pmem.split(',').collect(); let mut file_str: &str = ""; let mut size_str: &str = ""; @@ -325,10 +321,10 @@ impl<'a> PmemConfig<'a> { return Err(Error::ParsePmemFileParam); } - Ok(Some(PmemConfig { + Ok(PmemConfig { file: Path::new(file_str), size: size_str.parse::().map_err(Error::ParsePmemSizeParam)?, - })) + }) } } @@ -341,7 +337,7 @@ pub struct VmConfig<'a> { pub net: Option>, pub rng: RngConfig<'a>, pub fs: Option>>, - pub pmem: Option>, + pub pmem: Option>>, } impl<'a> VmConfig<'a> { @@ -360,6 +356,15 @@ impl<'a> VmConfig<'a> { fs = Some(fs_config_list); } + let mut pmem: Option> = None; + if let Some(pmem_list) = &vm_params.pmem { + let mut pmem_config_list = Vec::new(); + for item in pmem_list.iter() { + pmem_config_list.push(PmemConfig::parse(item)?); + } + pmem = Some(pmem_config_list); + } + Ok(VmConfig { cpus: CpusConfig::parse(vm_params.cpus)?, memory: MemoryConfig::parse(vm_params.memory)?, @@ -369,7 +374,7 @@ impl<'a> VmConfig<'a> { net: NetConfig::parse(vm_params.net)?, rng: RngConfig::parse(vm_params.rng)?, fs, - pmem: PmemConfig::parse(vm_params.pmem)?, + pmem, }) } } diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 1ffa1685f..b222cf872 100755 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -633,65 +633,67 @@ impl DeviceManager { } // Add virtio-pmem if required - if let Some(pmem_cfg) = &vm_cfg.pmem { - let size = pmem_cfg.size; + if let Some(pmem_list_cfg) = &vm_cfg.pmem { + for pmem_cfg in pmem_list_cfg.iter() { + let size = pmem_cfg.size; - let pmem_guest_addr = allocator - .allocate_mmio_addresses(None, size as GuestUsize) - .ok_or(DeviceManagerError::PmemRangeAllocation)?; + let pmem_guest_addr = allocator + .allocate_mmio_addresses(None, size as GuestUsize) + .ok_or(DeviceManagerError::PmemRangeAllocation)?; - let (custom_flags, set_len) = if pmem_cfg.file.is_dir() { - (O_TMPFILE, true) - } else { - (0, false) - }; + let (custom_flags, set_len) = if pmem_cfg.file.is_dir() { + (O_TMPFILE, true) + } else { + (0, false) + }; - let file = OpenOptions::new() - .read(true) - .write(true) - .custom_flags(custom_flags) - .open(pmem_cfg.file) - .map_err(DeviceManagerError::PmemFileOpen)?; + let file = OpenOptions::new() + .read(true) + .write(true) + .custom_flags(custom_flags) + .open(pmem_cfg.file) + .map_err(DeviceManagerError::PmemFileOpen)?; - if set_len { - file.set_len(size) - .map_err(DeviceManagerError::PmemFileSetLen)?; + if set_len { + file.set_len(size) + .map_err(DeviceManagerError::PmemFileSetLen)?; + } + + let addr = unsafe { + libc::mmap( + null_mut(), + size as usize, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_NORESERVE | libc::MAP_SHARED, + file.as_raw_fd(), + 0 as libc::off_t, + ) as *mut u8 + }; + + let mem_region = kvm_userspace_memory_region { + slot: memory.num_regions() as u32, + guest_phys_addr: pmem_guest_addr.raw_value(), + memory_size: size, + userspace_addr: addr as u64, + flags: 0, + }; + // Safe because the guest regions are guaranteed not to overlap. + let _ = unsafe { vm_fd.set_user_memory_region(mem_region) }; + + let virtio_pmem_device = + vm_virtio::Pmem::new(file, pmem_guest_addr, size as GuestUsize) + .map_err(DeviceManagerError::CreateVirtioPmem)?; + + DeviceManager::add_virtio_pci_device( + Box::new(virtio_pmem_device), + memory.clone(), + allocator, + vm_fd, + &mut pci_root, + &mut mmio_bus, + &interrupt_info, + )?; } - - let addr = unsafe { - libc::mmap( - null_mut(), - size as usize, - libc::PROT_READ | libc::PROT_WRITE, - libc::MAP_NORESERVE | libc::MAP_SHARED, - file.as_raw_fd(), - 0 as libc::off_t, - ) as *mut u8 - }; - - let mem_region = kvm_userspace_memory_region { - slot: memory.num_regions() as u32, - guest_phys_addr: pmem_guest_addr.raw_value(), - memory_size: size, - userspace_addr: addr as u64, - flags: 0, - }; - // Safe because the guest regions are guaranteed not to overlap. - let _ = unsafe { vm_fd.set_user_memory_region(mem_region) }; - - let virtio_pmem_device = - vm_virtio::Pmem::new(file, pmem_guest_addr, size as GuestUsize) - .map_err(DeviceManagerError::CreateVirtioPmem)?; - - DeviceManager::add_virtio_pci_device( - Box::new(virtio_pmem_device), - memory.clone(), - allocator, - vm_fd, - &mut pci_root, - &mut mmio_bus, - &interrupt_info, - )?; } let pci = Arc::new(Mutex::new(PciConfigIo::new(pci_root)));