From 7882dadac2ba5188f6cb416fb6ec38980451c9f2 Mon Sep 17 00:00:00 2001
From: Yang Xiaohe <yangxiaohe2@huawei.com>
Date: Wed, 2 Dec 2020 11:19:37 +0800
Subject: [PATCH 2/2] memory: add 'mem-share' config and implementation in
 address_space module.

1. Add 'mem-share' config in MachineConfig.
2. If set mem-share, use `memfd_create` syscall to create memfd
   for memory sharing between processes, and update flags for `mmap`.

Signed-off-by: Yang Xiaohe <yangxiaohe2@huawei.com>
---
 Cargo.lock                                   |  1 +
 address_space/Cargo.toml                     |  1 +
 address_space/src/address_space.rs           |  9 ++-
 address_space/src/host_mmap.rs               | 84 ++++++++++++--------
 address_space/src/lib.rs                     |  3 +-
 address_space/src/listener.rs                |  2 +-
 address_space/src/region.rs                  |  4 +-
 boot_loader/src/x86_64/bootparam.rs          |  5 +-
 boot_loader/src/x86_64/mod.rs                |  5 +-
 device_model/src/micro_vm/cmdline.rs         | 10 ++-
 device_model/src/micro_vm/mod.rs             |  5 +-
 device_model/src/mmio/virtio_mmio.rs         |  2 +-
 device_model/src/virtio/queue.rs             |  2 +-
 docs/config_guidebook.md                     |  4 +-
 machine_manager/src/config/machine_config.rs | 66 +++++++++++----
 15 files changed, 137 insertions(+), 66 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 00197ee..289be29 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -29,6 +29,7 @@ dependencies = [
  "kvm-ioctls 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "machine_manager 0.1.0",
  "util 0.1.0",
  "vmm-sys-util 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
diff --git a/address_space/Cargo.toml b/address_space/Cargo.toml
index d4003b0..9324871 100644
--- a/address_space/Cargo.toml
+++ b/address_space/Cargo.toml
@@ -7,6 +7,7 @@ description = "provide memory management for VM"
 
 [dependencies]
 util = {path = "../util"}
+machine_manager = {path = "../machine_manager"}
 
 kvm-ioctls = "0.5.0"
 libc = "0.2.71"
diff --git a/address_space/src/address_space.rs b/address_space/src/address_space.rs
index 4f567bb..ea10cad 100644
--- a/address_space/src/address_space.rs
+++ b/address_space/src/address_space.rs
@@ -655,8 +655,10 @@ mod test {
             write: Arc::new(|_: &[u8], _: GuestAddress, _: u64| -> bool { true }),
         };
 
-        let ram1 = Arc::new(HostMemMapping::new(GuestAddress(0), 1000, -1, 0, false).unwrap());
-        let ram2 = Arc::new(HostMemMapping::new(GuestAddress(2000), 1000, -1, 0, false).unwrap());
+        let ram1 =
+            Arc::new(HostMemMapping::new(GuestAddress(0), 1000, -1, 0, false, false).unwrap());
+        let ram2 =
+            Arc::new(HostMemMapping::new(GuestAddress(2000), 1000, -1, 0, false, false).unwrap());
         let region_a = Region::init_ram_region(ram1.clone());
         let region_b = Region::init_ram_region(ram2.clone());
         root.add_subregion(region_a, ram1.start_address().raw_value())
@@ -719,7 +721,8 @@ mod test {
     fn test_write_and_read_object() {
         let root = Region::init_container_region(8000);
         let space = AddressSpace::new(root.clone()).unwrap();
-        let ram1 = Arc::new(HostMemMapping::new(GuestAddress(0), 1000, -1, 0, false).unwrap());
+        let ram1 =
+            Arc::new(HostMemMapping::new(GuestAddress(0), 1000, -1, 0, false, false).unwrap());
         let region_a = Region::init_ram_region(ram1.clone());
         root.add_subregion(region_a, ram1.start_address().raw_value())
             .unwrap();
diff --git a/address_space/src/host_mmap.rs b/address_space/src/host_mmap.rs
index f172f46..1a8269b 100644
--- a/address_space/src/host_mmap.rs
+++ b/address_space/src/host_mmap.rs
@@ -14,6 +14,8 @@ use std::fs::File;
 use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
 use std::sync::Arc;
 
+use machine_manager::config::MachineMemConfig;
+
 use crate::errors::{ErrorKind, Result, ResultExt};
 use crate::{AddressRange, GuestAddress};
 
@@ -81,42 +83,49 @@ impl FileBackend {
 /// # Arguments
 ///
 /// * `ranges` - The guest address range that will be mapped.
-/// * `file_path` - The path of backend-file.
-/// * `dump_guest_core` - Include guest memory in core file or not.
+/// * `mem_config` - Machine memory config.
 pub fn create_host_mmaps(
     ranges: &[(u64, u64)],
-    file_path: Option<&str>,
-    dump_guest_core: bool,
+    mem_config: &MachineMemConfig,
 ) -> Result<Vec<Arc<HostMemMapping>>> {
-    let mut mappings = Vec::new();
+    let mut f_back: Option<FileBackend> = None;
 
-    match file_path {
-        Some(path) => {
-            // create file-backend
-            let file_len = ranges.iter().fold(0, |acc, x| acc + x.1);
-            let mut f_back = FileBackend::new(path, file_len)?;
-            for range in ranges.iter() {
-                mappings.push(Arc::new(HostMemMapping::new(
-                    GuestAddress(range.0),
-                    range.1,
-                    f_back.file.as_raw_fd(),
-                    f_back.offset,
-                    dump_guest_core,
-                )?));
+    if let Some(path) = &mem_config.mem_path {
+        let file_len = ranges.iter().fold(0, |acc, x| acc + x.1);
+        f_back = Some(FileBackend::new(&path, file_len)?);
+    } else if mem_config.mem_share {
+        let file_len = ranges.iter().fold(0, |acc, x| acc + x.1);
 
-                f_back.offset += range.1;
-            }
-        }
-        None => {
-            for range in ranges.iter() {
-                mappings.push(Arc::new(HostMemMapping::new(
-                    GuestAddress(range.0),
-                    range.1,
-                    -1,
-                    0,
-                    dump_guest_core,
-                )?));
-            }
+        let anon_mem_name = String::from("stratovirt_anon_mem");
+        let anon_fd =
+            unsafe { libc::syscall(libc::SYS_memfd_create, anon_mem_name.as_ptr(), 0) } as RawFd;
+        let anon_file = unsafe { File::from_raw_fd(anon_fd) };
+
+        anon_file.set_len(file_len)?;
+        f_back = Some(FileBackend {
+            file: anon_file,
+            offset: 0,
+        });
+    }
+
+    let mut mappings = Vec::new();
+    for range in ranges.iter() {
+        let (fd, offset) = if let Some(fb) = f_back.as_ref() {
+            (fb.file.as_raw_fd(), fb.offset)
+        } else {
+            (-1, 0)
+        };
+        mappings.push(Arc::new(HostMemMapping::new(
+            GuestAddress(range.0),
+            range.1,
+            fd,
+            offset,
+            mem_config.dump_guest_core,
+            mem_config.mem_share,
+        )?));
+
+        if let Some(mut fb) = f_back.as_mut() {
+            fb.offset += range.1
         }
     }
 
@@ -147,6 +156,7 @@ impl HostMemMapping {
     /// * `file_back` - The file's raw fd that backs memory,
     /// * `file_offset` - Offset in the file that backs memory.
     /// * `dump_guest_core` - Include guest memory in core file or not.
+    /// * `is_share` - This mapping is sharable or not.
     ///
     /// # Errors
     ///
@@ -157,11 +167,17 @@ impl HostMemMapping {
         file_back: RawFd,
         file_offset: u64,
         dump_guest_core: bool,
+        is_share: bool,
     ) -> Result<HostMemMapping> {
-        let mut flags = libc::MAP_PRIVATE | libc::MAP_NORESERVE;
+        let mut flags = libc::MAP_NORESERVE;
         if file_back == -1 {
             flags |= libc::MAP_ANONYMOUS;
         }
+        if is_share {
+            flags |= libc::MAP_SHARED;
+        } else {
+            flags |= libc::MAP_PRIVATE;
+        }
 
         let host_addr = unsafe {
             let hva = libc::mmap(
@@ -240,8 +256,8 @@ mod test {
 
     #[test]
     fn test_ramblock_creation() {
-        let ram1 = HostMemMapping::new(GuestAddress(0), 100u64, -1, 0, false).unwrap();
-        let ram2 = HostMemMapping::new(GuestAddress(0), 100u64, -1, 0, false).unwrap();
+        let ram1 = HostMemMapping::new(GuestAddress(0), 100u64, -1, 0, false, false).unwrap();
+        let ram2 = HostMemMapping::new(GuestAddress(0), 100u64, -1, 0, false, false).unwrap();
         identify(ram1, 0, 100);
         identify(ram2, 0, 100);
     }
diff --git a/address_space/src/lib.rs b/address_space/src/lib.rs
index 98f4380..b187ce8 100644
--- a/address_space/src/lib.rs
+++ b/address_space/src/lib.rs
@@ -37,7 +37,7 @@
 //!     let space = AddressSpace::new(Region::init_container_region(u64::max_value())).unwrap();
 //!
 //!     // 2. create an Ram-type Region, and set it's priority
-//!     let mem_mapping = Arc::new(HostMemMapping::new(GuestAddress(0), 0x1000, -1, 0, false).unwrap());
+//!     let mem_mapping = Arc::new(HostMemMapping::new(GuestAddress(0), 0x1000, -1, 0, false, false).unwrap());
 //!     let ram_region = Region::init_ram_region(mem_mapping.clone());
 //!     ram_region.set_priority(10);
 //!
@@ -72,6 +72,7 @@
 extern crate kvm_bindings;
 extern crate kvm_ioctls;
 extern crate libc;
+extern crate machine_manager;
 extern crate util;
 extern crate vmm_sys_util;
 #[macro_use]
diff --git a/address_space/src/listener.rs b/address_space/src/listener.rs
index c7aca78..b2eb227 100644
--- a/address_space/src/listener.rs
+++ b/address_space/src/listener.rs
@@ -520,7 +520,7 @@ mod test {
 
     fn create_ram_range(addr: u64, size: u64, offset_in_region: u64) -> FlatRange {
         let mem_mapping =
-            Arc::new(HostMemMapping::new(GuestAddress(addr), size, -1, 0, false).unwrap());
+            Arc::new(HostMemMapping::new(GuestAddress(addr), size, -1, 0, false, false).unwrap());
         FlatRange {
             addr_range: AddressRange::new(
                 mem_mapping.start_address().unchecked_add(offset_in_region),
diff --git a/address_space/src/region.rs b/address_space/src/region.rs
index b270ac4..733546e 100644
--- a/address_space/src/region.rs
+++ b/address_space/src/region.rs
@@ -662,7 +662,7 @@ mod test {
     #[test]
     fn test_ram_region() {
         let mem_mapping =
-            Arc::new(HostMemMapping::new(GuestAddress(0), 1024u64, -1, 0, false).unwrap());
+            Arc::new(HostMemMapping::new(GuestAddress(0), 1024u64, -1, 0, false, false).unwrap());
         let ram_region = Region::init_ram_region(mem_mapping.clone());
         let data: [u8; 10] = [10; 10];
         let mut res_data: [u8; 10] = [0; 10];
@@ -696,7 +696,7 @@ mod test {
     fn test_ram_region_access() {
         // the target guest address is 0~1024 (1024 not included)
         let rgn_start = GuestAddress(0);
-        let host_mmap = HostMemMapping::new(GuestAddress(0), 1024u64, -1, 0, false).unwrap();
+        let host_mmap = HostMemMapping::new(GuestAddress(0), 1024u64, -1, 0, false, false).unwrap();
         let ram_region = Region::init_ram_region(Arc::new(host_mmap));
         let mut file = std::fs::File::create("/tmp/test_read_write_buffer.tmp").unwrap();
         let mut file_read = std::fs::File::open("/tmp/test_read_write_buffer.tmp").unwrap();
diff --git a/boot_loader/src/x86_64/bootparam.rs b/boot_loader/src/x86_64/bootparam.rs
index 34a4f73..8ca6dfd 100644
--- a/boot_loader/src/x86_64/bootparam.rs
+++ b/boot_loader/src/x86_64/bootparam.rs
@@ -179,8 +179,9 @@ mod test {
         // test setup_boot_params function
         let root = Region::init_container_region(0x2000_0000);
         let space = AddressSpace::new(root.clone()).unwrap();
-        let ram1 =
-            Arc::new(HostMemMapping::new(GuestAddress(0), 0x1000_0000, -1, 0, false).unwrap());
+        let ram1 = Arc::new(
+            HostMemMapping::new(GuestAddress(0), 0x1000_0000, -1, 0, false, false).unwrap(),
+        );
         let region_a = Region::init_ram_region(ram1.clone());
         root.add_subregion(region_a, ram1.start_address().raw_value())
             .unwrap();
diff --git a/boot_loader/src/x86_64/mod.rs b/boot_loader/src/x86_64/mod.rs
index c309a00..fab1d6b 100644
--- a/boot_loader/src/x86_64/mod.rs
+++ b/boot_loader/src/x86_64/mod.rs
@@ -499,8 +499,9 @@ mod test {
     fn test_x86_bootloader_and_kernel_cmdline() {
         let root = Region::init_container_region(0x2000_0000);
         let space = AddressSpace::new(root.clone()).unwrap();
-        let ram1 =
-            Arc::new(HostMemMapping::new(GuestAddress(0), 0x1000_0000, -1, 0, false).unwrap());
+        let ram1 = Arc::new(
+            HostMemMapping::new(GuestAddress(0), 0x1000_0000, -1, 0, false, false).unwrap(),
+        );
         let region_a = Region::init_ram_region(ram1.clone());
         root.add_subregion(region_a, ram1.start_address().raw_value())
             .unwrap();
diff --git a/device_model/src/micro_vm/cmdline.rs b/device_model/src/micro_vm/cmdline.rs
index cbea6fc..f2de7d0 100644
--- a/device_model/src/micro_vm/cmdline.rs
+++ b/device_model/src/micro_vm/cmdline.rs
@@ -85,7 +85,7 @@ pub fn create_args_parser<'a>() -> ArgParser<'a> {
         .arg(
             Arg::with_name("machine")
                 .long("machine")
-                .value_name("[type=]name[,dump_guest_core=on|off]")
+                .value_name("[type=]name[,dump_guest_core=on|off][,mem-share=on|off]")
                 .help("selects emulated machine")
                 .takes_value(true),
         )
@@ -103,6 +103,13 @@ pub fn create_args_parser<'a>() -> ArgParser<'a> {
                 .help("configure guest RAM")
                 .takes_value(true),
         )
+        .arg(
+            Arg::with_name("mem-path")
+                .long("mem-path")
+                .value_name("file backend file of memory")
+                .help("configure file path that backs guest memory.")
+                .takes_value(true),
+        )
         .arg(
             Arg::with_name("config-file")
                 .long("config")
@@ -341,6 +348,7 @@ pub fn create_vmconfig(args: &ArgMatches) -> Result<VmConfig> {
     update_args_to_config!((args.value_of("name")), vm_cfg, update_name);
     update_args_to_config!((args.value_of("machine")), vm_cfg, update_machine);
     update_args_to_config!((args.value_of("memory")), vm_cfg, update_memory);
+    update_args_to_config!((args.value_of("mem-path")), vm_cfg, update_mem_path);
     update_args_to_config!((args.value_of("smp")), vm_cfg, update_cpu);
     update_args_to_config!((args.value_of("kernel")), vm_cfg, update_kernel);
     update_args_to_config!((args.value_of("initrd-file")), vm_cfg, update_initrd);
diff --git a/device_model/src/micro_vm/mod.rs b/device_model/src/micro_vm/mod.rs
index eb0df3a..4f06d6c 100644
--- a/device_model/src/micro_vm/mod.rs
+++ b/device_model/src/micro_vm/mod.rs
@@ -227,9 +227,8 @@ impl LightMachine {
 
         // Init guest-memory
         // Define ram-region ranges according to architectures
-        let ram_ranges = Self::arch_ram_ranges(vm_config.machine_config.mem_size);
-        let mem_mappings =
-            create_host_mmaps(&ram_ranges, None, vm_config.machine_config.dump_guest_core)?;
+        let ram_ranges = Self::arch_ram_ranges(vm_config.machine_config.mem_config.mem_size);
+        let mem_mappings = create_host_mmaps(&ram_ranges, &vm_config.machine_config.mem_config)?;
         for mmap in mem_mappings.iter() {
             sys_mem.root().add_subregion(
                 Region::init_ram_region(mmap.clone()),
diff --git a/device_model/src/mmio/virtio_mmio.rs b/device_model/src/mmio/virtio_mmio.rs
index de30cbc..f61217a 100644
--- a/device_model/src/mmio/virtio_mmio.rs
+++ b/device_model/src/mmio/virtio_mmio.rs
@@ -527,7 +527,7 @@ mod tests {
         let root = Region::init_container_region(1 << 36);
         let sys_space = AddressSpace::new(root).unwrap();
         let host_mmap = Arc::new(
-            HostMemMapping::new(GuestAddress(0), SYSTEM_SPACE_SIZE, -1, 0, false).unwrap(),
+            HostMemMapping::new(GuestAddress(0), SYSTEM_SPACE_SIZE, -1, 0, false, false).unwrap(),
         );
         sys_space
             .root()
diff --git a/device_model/src/virtio/queue.rs b/device_model/src/virtio/queue.rs
index a6ee9cd..136986e 100644
--- a/device_model/src/virtio/queue.rs
+++ b/device_model/src/virtio/queue.rs
@@ -746,7 +746,7 @@ mod tests {
         let root = Region::init_container_region(1 << 36);
         let sys_space = AddressSpace::new(root).unwrap();
         let host_mmap = Arc::new(
-            HostMemMapping::new(GuestAddress(0), SYSTEM_SPACE_SIZE, -1, 0, false).unwrap(),
+            HostMemMapping::new(GuestAddress(0), SYSTEM_SPACE_SIZE, -1, 0, false, false).unwrap(),
         );
         sys_space
             .root()
diff --git a/docs/config_guidebook.md b/docs/config_guidebook.md
index 665a7f5..a309018 100644
--- a/docs/config_guidebook.md
+++ b/docs/config_guidebook.md
@@ -11,18 +11,20 @@ StratoVirt supports json configuration file and cmdline arguments. If you set th
 General configuration of machine, including
 * type: The machine type of machine, StratoVirt only support MicroVm yet.
 * dump-guest-core: Including guest memory in coredump file or not, default value is true.
+* mem-share: Guest memory is sharable with other processes or not.
 
 This feature is closed by default. There are two ways to open it:
 
 ```shell
 # cmdline
--machine [type=]name[,dump-guest-core=on|off]
+-machine [type=]name[,dump-guest-core=on|off][,mem-share=on|off]
 
 # json
 {
     "machine-config": {
         "type": "MicroVm",
         "dump_guest_core": false,
+        "mem-share": false,
         ...
     },
     ...
diff --git a/machine_manager/src/config/machine_config.rs b/machine_manager/src/config/machine_config.rs
index f9c8675..fbe4e15 100644
--- a/machine_manager/src/config/machine_config.rs
+++ b/machine_manager/src/config/machine_config.rs
@@ -27,14 +27,33 @@ const MIN_MEMSIZE: u64 = 134_217_728;
 const M: u64 = 1024 * 1024;
 const G: u64 = 1024 * 1024 * 1024;
 
+/// Config that contains machine's memory information config.
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct MachineMemConfig {
+    pub mem_size: u64,
+    pub mem_path: Option<String>,
+    pub dump_guest_core: bool,
+    pub mem_share: bool,
+}
+
+impl Default for MachineMemConfig {
+    fn default() -> Self {
+        MachineMemConfig {
+            mem_size: DEFAULT_MEMSIZE * M,
+            mem_path: None,
+            dump_guest_core: true,
+            mem_share: false,
+        }
+    }
+}
+
 /// Config struct for machine-config.
 /// Contains some basic Vm config about cpu, memory, name.
 #[derive(Clone, Debug, Serialize, Deserialize)]
 pub struct MachineConfig {
     pub mach_type: String,
     pub nr_cpus: u8,
-    pub mem_size: u64,
-    pub dump_guest_core: bool,
+    pub mem_config: MachineMemConfig,
 }
 
 impl Default for MachineConfig {
@@ -43,8 +62,7 @@ impl Default for MachineConfig {
         MachineConfig {
             mach_type: "MicroVm".to_string(),
             nr_cpus: DEFAULT_CPUS,
-            mem_size: DEFAULT_MEMSIZE * M,
-            dump_guest_core: true,
+            mem_config: MachineMemConfig::default(),
         }
     }
 }
@@ -64,10 +82,19 @@ impl MachineConfig {
             machine_config.nr_cpus = value["vcpu_count"].to_string().parse::<u8>().unwrap();
         }
         if value.get("mem_size") != None {
-            machine_config.mem_size = value["mem_size"].to_string().parse::<u64>().unwrap();
+            machine_config.mem_config.mem_size =
+                value["mem_size"].to_string().parse::<u64>().unwrap();
+        }
+        if value.get("mem_path") != None {
+            machine_config.mem_config.mem_path =
+                Some(value["mem_path"].to_string().replace("\"", ""));
+        }
+        if value.get("mem_share") != None {
+            machine_config.mem_config.mem_share =
+                value["mem_share"].to_string().parse::<bool>().unwrap();
         }
         if value.get("dump_guest_core") != None {
-            machine_config.dump_guest_core = value["dump_guest_core"]
+            machine_config.mem_config.dump_guest_core = value["dump_guest_core"]
                 .to_string()
                 .parse::<bool>()
                 .unwrap();
@@ -82,7 +109,7 @@ impl ConfigCheck for MachineConfig {
             return Err(ErrorKind::NrcpusError.into());
         }
 
-        if self.mem_size < MIN_MEMSIZE || self.mem_size > MAX_MEMSIZE {
+        if self.mem_config.mem_size < MIN_MEMSIZE || self.mem_config.mem_size > MAX_MEMSIZE {
             return Err(ErrorKind::MemsizeError.into());
         }
 
@@ -102,7 +129,10 @@ impl VmConfig {
             self.machine_config.mach_type = mach_type.value;
         }
         if let Some(dump_guest) = cmd_params.get("dump-guest-core") {
-            self.machine_config.dump_guest_core = dump_guest.to_bool();
+            self.machine_config.mem_config.dump_guest_core = dump_guest.to_bool();
+        }
+        if let Some(mem_share) = cmd_params.get("mem-share") {
+            self.machine_config.mem_config.mem_share = mem_share.to_bool();
         }
     }
     /// Update '-m' memory config to `VmConfig`.
@@ -110,19 +140,23 @@ impl VmConfig {
         let cmd_params: CmdParams = CmdParams::from_str(mem_config);
         if let Some(mut mem_size) = cmd_params.get("") {
             if mem_size.value_replace_blank("M") || mem_size.value_replace_blank("m") {
-                self.machine_config.mem_size = get_inner(mem_size.value_to_u64().checked_mul(M));
+                self.machine_config.mem_config.mem_size =
+                    get_inner(mem_size.value_to_u64().checked_mul(M));
             } else if mem_size.value_replace_blank("G") || mem_size.value_replace_blank("g") {
-                self.machine_config.mem_size = get_inner(mem_size.value_to_u64().checked_mul(G));
+                self.machine_config.mem_config.mem_size =
+                    get_inner(mem_size.value_to_u64().checked_mul(G));
             } else {
-                self.machine_config.mem_size = mem_size.value_to_u64();
+                self.machine_config.mem_config.mem_size = mem_size.value_to_u64();
             }
         } else if let Some(mut mem_size) = cmd_params.get("size") {
             if mem_size.value_replace_blank("M") || mem_size.value_replace_blank("m") {
-                self.machine_config.mem_size = get_inner(mem_size.value_to_u64().checked_mul(M));
+                self.machine_config.mem_config.mem_size =
+                    get_inner(mem_size.value_to_u64().checked_mul(M));
             } else if mem_size.value_replace_blank("G") || mem_size.value_replace_blank("g") {
-                self.machine_config.mem_size = get_inner(mem_size.value_to_u64().checked_mul(G));
+                self.machine_config.mem_config.mem_size =
+                    get_inner(mem_size.value_to_u64().checked_mul(G));
             } else {
-                self.machine_config.mem_size = mem_size.value_to_u64();
+                self.machine_config.mem_config.mem_size = mem_size.value_to_u64();
             }
         }
     }
@@ -136,6 +170,10 @@ impl VmConfig {
             self.machine_config.nr_cpus = cpu_num.value_to_u8();
         }
     }
+
+    pub fn update_mem_path(&mut self, mem_path: String) {
+        self.machine_config.mem_config.mem_path = Some(mem_path.replace("\"", ""));
+    }
 }
 
 fn get_inner<T>(outer: Option<T>) -> T {
-- 
2.27.0

