mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 11:05:46 +00:00
memory: Allow memory to be backed by a file
In the context of vhost-user, we need the guest RAM to be backed by a file in order to be accessed by an external process. This patch adds the new flag "file=" to the "--memory" option so that we can specify from the command line if the memory needs to be backed, and by which specific file. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
2ede30b6d3
commit
53085c7ccc
19
src/main.rs
19
src/main.rs
@ -26,7 +26,10 @@ fn main() {
|
|||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("memory")
|
Arg::with_name("memory")
|
||||||
.long("memory")
|
.long("memory")
|
||||||
.help("Amount of RAM (in MiB)")
|
.help(
|
||||||
|
"Memory parameters \"size=<guest_memory_size>,\
|
||||||
|
file=<backing_file_path>\"",
|
||||||
|
)
|
||||||
.default_value(config::DEFAULT_MEMORY),
|
.default_value(config::DEFAULT_MEMORY),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@ -118,7 +121,7 @@ fn main() {
|
|||||||
"Cloud Hypervisor Guest\n\tvCPUs: {}\n\tMemory: {} MB\
|
"Cloud Hypervisor Guest\n\tvCPUs: {}\n\tMemory: {} MB\
|
||||||
\n\tKernel: {:?}\n\tKernel cmdline: {}\n\tDisk(s): {:?}",
|
\n\tKernel: {:?}\n\tKernel cmdline: {}\n\tDisk(s): {:?}",
|
||||||
u8::from(&vm_config.cpus),
|
u8::from(&vm_config.cpus),
|
||||||
u64::from(&vm_config.memory),
|
vm_config.memory.size,
|
||||||
vm_config.kernel.path,
|
vm_config.kernel.path,
|
||||||
vm_config.cmdline.args.as_str(),
|
vm_config.cmdline.args.as_str(),
|
||||||
vm_config.disks,
|
vm_config.disks,
|
||||||
@ -242,7 +245,7 @@ mod tests {
|
|||||||
let (disks, fw_path) = prepare_files();
|
let (disks, fw_path) = prepare_files();
|
||||||
let mut child = Command::new("target/debug/cloud-hypervisor")
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
||||||
.args(&["--cpus", "1"])
|
.args(&["--cpus", "1"])
|
||||||
.args(&["--memory", "512"])
|
.args(&["--memory", "size=512"])
|
||||||
.args(&["--kernel", fw_path.as_str()])
|
.args(&["--kernel", fw_path.as_str()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
||||||
@ -270,7 +273,7 @@ mod tests {
|
|||||||
let (disks, fw_path) = prepare_files();
|
let (disks, fw_path) = prepare_files();
|
||||||
let mut child = Command::new("target/debug/cloud-hypervisor")
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
||||||
.args(&["--cpus", "2"])
|
.args(&["--cpus", "2"])
|
||||||
.args(&["--memory", "512"])
|
.args(&["--memory", "size=512"])
|
||||||
.args(&["--kernel", fw_path.as_str()])
|
.args(&["--kernel", fw_path.as_str()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
||||||
@ -295,7 +298,7 @@ mod tests {
|
|||||||
let (disks, fw_path) = prepare_files();
|
let (disks, fw_path) = prepare_files();
|
||||||
let mut child = Command::new("target/debug/cloud-hypervisor")
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
||||||
.args(&["--cpus", "1"])
|
.args(&["--cpus", "1"])
|
||||||
.args(&["--memory", "5120"])
|
.args(&["--memory", "size=5120"])
|
||||||
.args(&["--kernel", fw_path.as_str()])
|
.args(&["--kernel", fw_path.as_str()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
||||||
@ -320,7 +323,7 @@ mod tests {
|
|||||||
let (disks, fw_path) = prepare_files();
|
let (disks, fw_path) = prepare_files();
|
||||||
let mut child = Command::new("target/debug/cloud-hypervisor")
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
||||||
.args(&["--cpus", "1"])
|
.args(&["--cpus", "1"])
|
||||||
.args(&["--memory", "512"])
|
.args(&["--memory", "size=512"])
|
||||||
.args(&["--kernel", fw_path.as_str()])
|
.args(&["--kernel", fw_path.as_str()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
||||||
@ -358,7 +361,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut child = Command::new("target/debug/cloud-hypervisor")
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
||||||
.args(&["--cpus", "1"])
|
.args(&["--cpus", "1"])
|
||||||
.args(&["--memory", "512"])
|
.args(&["--memory", "size=512"])
|
||||||
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
||||||
@ -400,7 +403,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut child = Command::new("target/debug/cloud-hypervisor")
|
let mut child = Command::new("target/debug/cloud-hypervisor")
|
||||||
.args(&["--cpus", "1"])
|
.args(&["--cpus", "1"])
|
||||||
.args(&["--memory", "512"])
|
.args(&["--memory", "size=512"])
|
||||||
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
.args(&["--kernel", kernel_path.to_str().unwrap()])
|
||||||
.args(&["--disk", disks[0], disks[1]])
|
.args(&["--disk", disks[0], disks[1]])
|
||||||
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
.args(&["--net", "tap=,mac=,ip=192.168.2.1,mask=255.255.255.0"])
|
||||||
|
@ -13,7 +13,7 @@ use std::result;
|
|||||||
use vm_memory::GuestAddress;
|
use vm_memory::GuestAddress;
|
||||||
|
|
||||||
pub const DEFAULT_VCPUS: &str = "1";
|
pub const DEFAULT_VCPUS: &str = "1";
|
||||||
pub const DEFAULT_MEMORY: &str = "512";
|
pub const DEFAULT_MEMORY: &str = "size=512";
|
||||||
pub const DEFAULT_RNG_SOURCE: &str = "/dev/urandom";
|
pub const DEFAULT_RNG_SOURCE: &str = "/dev/urandom";
|
||||||
const CMDLINE_OFFSET: GuestAddress = GuestAddress(0x20000);
|
const CMDLINE_OFFSET: GuestAddress = GuestAddress(0x20000);
|
||||||
|
|
||||||
@ -22,8 +22,10 @@ const CMDLINE_OFFSET: GuestAddress = GuestAddress(0x20000);
|
|||||||
pub enum Error<'a> {
|
pub enum Error<'a> {
|
||||||
/// Failed parsing cpus parameters.
|
/// Failed parsing cpus parameters.
|
||||||
ParseCpusParams(std::num::ParseIntError),
|
ParseCpusParams(std::num::ParseIntError),
|
||||||
/// Failed parsing memory parameters.
|
/// Failed parsing memory size parameter.
|
||||||
ParseMemoryParams(std::num::ParseIntError),
|
ParseMemorySizeParam(std::num::ParseIntError),
|
||||||
|
/// Failed parsing memory file parameter.
|
||||||
|
ParseMemoryFileParam,
|
||||||
/// Failed parsing kernel parameters.
|
/// Failed parsing kernel parameters.
|
||||||
ParseKernelParams,
|
ParseKernelParams,
|
||||||
/// Failed parsing kernel command line parameters.
|
/// Failed parsing kernel command line parameters.
|
||||||
@ -76,19 +78,45 @@ impl From<&CpusConfig> for u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MemoryConfig(pub u64);
|
pub struct MemoryConfig<'a> {
|
||||||
|
pub size: u64,
|
||||||
impl MemoryConfig {
|
pub file: Option<&'a Path>,
|
||||||
pub fn parse(memory: &str) -> Result<Self> {
|
|
||||||
Ok(MemoryConfig(
|
|
||||||
memory.parse::<u64>().map_err(Error::ParseMemoryParams)?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&MemoryConfig> for u64 {
|
impl<'a> MemoryConfig<'a> {
|
||||||
fn from(val: &MemoryConfig) -> Self {
|
pub fn parse(memory: &'a str) -> Result<Self> {
|
||||||
val.0
|
// Split the parameters based on the comma delimiter
|
||||||
|
let params_list: Vec<&str> = memory.split(',').collect();
|
||||||
|
|
||||||
|
let mut size_str: &str = "";
|
||||||
|
let mut file_str: &str = "";
|
||||||
|
let mut backed = false;
|
||||||
|
|
||||||
|
for param in params_list.iter() {
|
||||||
|
if param.starts_with("size=") {
|
||||||
|
size_str = ¶m[5..];
|
||||||
|
} else if param.starts_with("file=") {
|
||||||
|
backed = true;
|
||||||
|
file_str = ¶m[5..];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let file = if backed {
|
||||||
|
if file_str.is_empty() {
|
||||||
|
return Err(Error::ParseMemoryFileParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Path::new(file_str))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(MemoryConfig {
|
||||||
|
size: size_str
|
||||||
|
.parse::<u64>()
|
||||||
|
.map_err(Error::ParseMemorySizeParam)?,
|
||||||
|
file,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +296,7 @@ impl<'a> FsConfig<'a> {
|
|||||||
|
|
||||||
pub struct VmConfig<'a> {
|
pub struct VmConfig<'a> {
|
||||||
pub cpus: CpusConfig,
|
pub cpus: CpusConfig,
|
||||||
pub memory: MemoryConfig,
|
pub memory: MemoryConfig<'a>,
|
||||||
pub kernel: KernelConfig<'a>,
|
pub kernel: KernelConfig<'a>,
|
||||||
pub cmdline: CmdlineConfig,
|
pub cmdline: CmdlineConfig,
|
||||||
pub disks: Vec<DiskConfig<'a>>,
|
pub disks: Vec<DiskConfig<'a>>,
|
||||||
|
@ -843,15 +843,17 @@ impl<'a> Vm<'a> {
|
|||||||
let fd = Arc::new(fd);
|
let fd = Arc::new(fd);
|
||||||
|
|
||||||
// Init guest memory
|
// Init guest memory
|
||||||
let arch_mem_regions = arch::arch_memory_regions(u64::from(&config.memory) << 20);
|
let arch_mem_regions = arch::arch_memory_regions(config.memory.size << 20);
|
||||||
|
|
||||||
|
let guest_memory = match config.memory.file {
|
||||||
|
Some(file) => {
|
||||||
let mut mem_regions = Vec::<(GuestAddress, usize, Option<FileOffset>)>::new();
|
let mut mem_regions = Vec::<(GuestAddress, usize, Option<FileOffset>)>::new();
|
||||||
for region in arch_mem_regions.iter() {
|
for region in arch_mem_regions.iter() {
|
||||||
let file = OpenOptions::new()
|
let file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.custom_flags(O_TMPFILE)
|
.custom_flags(O_TMPFILE)
|
||||||
.open("/dev/shm")
|
.open(file)
|
||||||
.map_err(Error::SharedFileCreate)?;
|
.map_err(Error::SharedFileCreate)?;
|
||||||
|
|
||||||
file.set_len(region.1 as u64)
|
file.set_len(region.1 as u64)
|
||||||
@ -860,7 +862,10 @@ impl<'a> Vm<'a> {
|
|||||||
mem_regions.push((region.0, region.1, Some(FileOffset::new(file, 0))));
|
mem_regions.push((region.0, region.1, Some(FileOffset::new(file, 0))));
|
||||||
}
|
}
|
||||||
|
|
||||||
let guest_memory = GuestMemoryMmap::with_files(&mem_regions).map_err(Error::GuestMemory)?;
|
GuestMemoryMmap::with_files(&mem_regions).map_err(Error::GuestMemory)?
|
||||||
|
}
|
||||||
|
None => GuestMemoryMmap::new(&arch_mem_regions).map_err(Error::GuestMemory)?,
|
||||||
|
};
|
||||||
|
|
||||||
guest_memory
|
guest_memory
|
||||||
.with_regions(|index, region| {
|
.with_regions(|index, region| {
|
||||||
|
Loading…
Reference in New Issue
Block a user