mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-07-05 01:12:36 +00:00
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 <sebastien.boeuf@intel.com>
This commit is contained in:
parent
785db6295e
commit
34e09923a5
@ -84,7 +84,8 @@ fn main() {
|
|||||||
"Persistent memory parameters \"file=<backing_file_path>,\
|
"Persistent memory parameters \"file=<backing_file_path>,\
|
||||||
size=<persistent_memory_size>\"",
|
size=<persistent_memory_size>\"",
|
||||||
)
|
)
|
||||||
.takes_value(true),
|
.takes_value(true)
|
||||||
|
.min_values(1),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
@ -110,7 +111,7 @@ fn main() {
|
|||||||
|
|
||||||
let fs: Option<Vec<&str>> = cmd_arguments.values_of("fs").map(|x| x.collect());
|
let fs: Option<Vec<&str>> = cmd_arguments.values_of("fs").map(|x| x.collect());
|
||||||
|
|
||||||
let pmem = cmd_arguments.value_of("pmem");
|
let pmem: Option<Vec<&str>> = cmd_arguments.values_of("pmem").map(|x| x.collect());
|
||||||
|
|
||||||
let vm_config = match config::VmConfig::parse(config::VmParams {
|
let vm_config = match config::VmConfig::parse(config::VmParams {
|
||||||
cpus,
|
cpus,
|
||||||
|
@ -64,7 +64,7 @@ pub struct VmParams<'a> {
|
|||||||
pub net: Option<&'a str>,
|
pub net: Option<&'a str>,
|
||||||
pub rng: &'a str,
|
pub rng: &'a str,
|
||||||
pub fs: Option<Vec<&'a str>>,
|
pub fs: Option<Vec<&'a str>>,
|
||||||
pub pmem: Option<&'a str>,
|
pub pmem: Option<Vec<&'a str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CpusConfig(pub u8);
|
pub struct CpusConfig(pub u8);
|
||||||
@ -302,13 +302,9 @@ pub struct PmemConfig<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PmemConfig<'a> {
|
impl<'a> PmemConfig<'a> {
|
||||||
pub fn parse(pmem: Option<&'a str>) -> Result<Option<Self>> {
|
pub fn parse(pmem: &'a str) -> Result<Self> {
|
||||||
if pmem.is_none() {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split the parameters based on the comma delimiter
|
// 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 file_str: &str = "";
|
||||||
let mut size_str: &str = "";
|
let mut size_str: &str = "";
|
||||||
@ -325,10 +321,10 @@ impl<'a> PmemConfig<'a> {
|
|||||||
return Err(Error::ParsePmemFileParam);
|
return Err(Error::ParsePmemFileParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(PmemConfig {
|
Ok(PmemConfig {
|
||||||
file: Path::new(file_str),
|
file: Path::new(file_str),
|
||||||
size: size_str.parse::<u64>().map_err(Error::ParsePmemSizeParam)?,
|
size: size_str.parse::<u64>().map_err(Error::ParsePmemSizeParam)?,
|
||||||
}))
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,7 +337,7 @@ pub struct VmConfig<'a> {
|
|||||||
pub net: Option<NetConfig<'a>>,
|
pub net: Option<NetConfig<'a>>,
|
||||||
pub rng: RngConfig<'a>,
|
pub rng: RngConfig<'a>,
|
||||||
pub fs: Option<Vec<FsConfig<'a>>>,
|
pub fs: Option<Vec<FsConfig<'a>>>,
|
||||||
pub pmem: Option<PmemConfig<'a>>,
|
pub pmem: Option<Vec<PmemConfig<'a>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VmConfig<'a> {
|
impl<'a> VmConfig<'a> {
|
||||||
@ -360,6 +356,15 @@ impl<'a> VmConfig<'a> {
|
|||||||
fs = Some(fs_config_list);
|
fs = Some(fs_config_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut pmem: Option<Vec<PmemConfig>> = 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 {
|
Ok(VmConfig {
|
||||||
cpus: CpusConfig::parse(vm_params.cpus)?,
|
cpus: CpusConfig::parse(vm_params.cpus)?,
|
||||||
memory: MemoryConfig::parse(vm_params.memory)?,
|
memory: MemoryConfig::parse(vm_params.memory)?,
|
||||||
@ -369,7 +374,7 @@ impl<'a> VmConfig<'a> {
|
|||||||
net: NetConfig::parse(vm_params.net)?,
|
net: NetConfig::parse(vm_params.net)?,
|
||||||
rng: RngConfig::parse(vm_params.rng)?,
|
rng: RngConfig::parse(vm_params.rng)?,
|
||||||
fs,
|
fs,
|
||||||
pmem: PmemConfig::parse(vm_params.pmem)?,
|
pmem,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
110
vmm/src/vm.rs
110
vmm/src/vm.rs
@ -633,65 +633,67 @@ impl DeviceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add virtio-pmem if required
|
// Add virtio-pmem if required
|
||||||
if let Some(pmem_cfg) = &vm_cfg.pmem {
|
if let Some(pmem_list_cfg) = &vm_cfg.pmem {
|
||||||
let size = pmem_cfg.size;
|
for pmem_cfg in pmem_list_cfg.iter() {
|
||||||
|
let size = pmem_cfg.size;
|
||||||
|
|
||||||
let pmem_guest_addr = allocator
|
let pmem_guest_addr = allocator
|
||||||
.allocate_mmio_addresses(None, size as GuestUsize)
|
.allocate_mmio_addresses(None, size as GuestUsize)
|
||||||
.ok_or(DeviceManagerError::PmemRangeAllocation)?;
|
.ok_or(DeviceManagerError::PmemRangeAllocation)?;
|
||||||
|
|
||||||
let (custom_flags, set_len) = if pmem_cfg.file.is_dir() {
|
let (custom_flags, set_len) = if pmem_cfg.file.is_dir() {
|
||||||
(O_TMPFILE, true)
|
(O_TMPFILE, true)
|
||||||
} else {
|
} else {
|
||||||
(0, false)
|
(0, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
let file = OpenOptions::new()
|
let file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.custom_flags(custom_flags)
|
.custom_flags(custom_flags)
|
||||||
.open(pmem_cfg.file)
|
.open(pmem_cfg.file)
|
||||||
.map_err(DeviceManagerError::PmemFileOpen)?;
|
.map_err(DeviceManagerError::PmemFileOpen)?;
|
||||||
|
|
||||||
if set_len {
|
if set_len {
|
||||||
file.set_len(size)
|
file.set_len(size)
|
||||||
.map_err(DeviceManagerError::PmemFileSetLen)?;
|
.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)));
|
let pci = Arc::new(Mutex::new(PciConfigIo::new(pci_root)));
|
||||||
|
Loading…
Reference in New Issue
Block a user