From 3a5ef152b5e803998e6ec5a1e7172c01fcce8bcf Mon Sep 17 00:00:00 2001
From: l00484210 <l00484210@notesmail.huawei.com/>
Date: Wed, 11 Dec 2024 20:23:47 +0800
Subject: [PATCH] snapshot: bugfix VM run failed from memory snapshot

The kernel does not need to be loaded for snapshot restoration.

Signed-off-by: Mingwang Li <limingwang@huawei.com>
---
 cpu/src/lib.rs                     | 22 ++++++++-------
 cpu/src/x86_64/mod.rs              |  2 +-
 devices/src/acpi/cpu_controller.rs |  4 +--
 machine/src/aarch64/micro.rs       | 40 +++++++++++++++------------
 machine/src/aarch64/standard.rs    | 44 ++++++++++++++++++------------
 machine/src/lib.rs                 |  2 +-
 machine/src/x86_64/micro.rs        |  9 ++++--
 machine/src/x86_64/standard.rs     | 13 +++++++--
 8 files changed, 83 insertions(+), 53 deletions(-)

diff --git a/cpu/src/lib.rs b/cpu/src/lib.rs
index 7a11629..7698132 100644
--- a/cpu/src/lib.rs
+++ b/cpu/src/lib.rs
@@ -118,7 +118,7 @@ pub trait CPUInterface {
     /// Realize `CPU` structure, set registers value for `CPU`.
     fn realize(
         &self,
-        boot: &CPUBootConfig,
+        boot: &Option<CPUBootConfig>,
         topology: &CPUTopology,
         #[cfg(target_arch = "aarch64")] features: &CPUFeatures,
     ) -> Result<()>;
@@ -310,7 +310,7 @@ impl CPU {
 impl CPUInterface for CPU {
     fn realize(
         &self,
-        boot: &CPUBootConfig,
+        boot: &Option<CPUBootConfig>,
         topology: &CPUTopology,
         #[cfg(target_arch = "aarch64")] config: &CPUFeatures,
     ) -> Result<()> {
@@ -323,14 +323,16 @@ impl CPUInterface for CPU {
             ))));
         }

-        self.hypervisor_cpu
-            .set_boot_config(
-                self.arch_cpu.clone(),
-                boot,
-                #[cfg(target_arch = "aarch64")]
-                config,
-            )
-            .with_context(|| "Failed to realize arch cpu")?;
+        if let Some(boot) = boot {
+            self.hypervisor_cpu
+                .set_boot_config(
+                    self.arch_cpu.clone(),
+                    boot,
+                    #[cfg(target_arch = "aarch64")]
+                    config,
+                )
+                .with_context(|| "Failed to realize arch cpu")?;
+        }

         self.arch_cpu
             .lock()
diff --git a/cpu/src/x86_64/mod.rs b/cpu/src/x86_64/mod.rs
index 0a8ad16..acb6fb2 100644
--- a/cpu/src/x86_64/mod.rs
+++ b/cpu/src/x86_64/mod.rs
@@ -75,7 +75,7 @@ pub enum X86RegsIndex {

 /// X86 CPU booting configure information
 #[allow(clippy::upper_case_acronyms)]
-#[derive(Default, Clone, Debug)]
+#[derive(Default, Clone, Debug, Copy)]
 pub struct X86CPUBootConfig {
     pub prot64_mode: bool,
     /// Register %rip value
diff --git a/devices/src/acpi/cpu_controller.rs b/devices/src/acpi/cpu_controller.rs
index 1259e8d..73f2601 100644
--- a/devices/src/acpi/cpu_controller.rs
+++ b/devices/src/acpi/cpu_controller.rs
@@ -157,8 +157,8 @@ impl CpuController {
         None
     }

-    pub fn get_boot_config(&self) -> &CPUBootConfig {
-        &self.cpu_config.as_ref().unwrap().boot_config
+    pub fn get_boot_config(&self) -> CPUBootConfig {
+        self.cpu_config.as_ref().unwrap().boot_config
     }

     pub fn get_hotplug_cpu_info(&self) -> (String, u8) {
diff --git a/machine/src/aarch64/micro.rs b/machine/src/aarch64/micro.rs
index 42e9171..3e7cf38 100644
--- a/machine/src/aarch64/micro.rs
+++ b/machine/src/aarch64/micro.rs
@@ -20,7 +20,7 @@ use address_space::{AddressSpace, GuestAddress, Region};
 use cpu::CPUTopology;
 use devices::{legacy::PL031, ICGICConfig, ICGICv2Config, ICGICv3Config, GIC_IRQ_MAX};
 use hypervisor::kvm::aarch64::*;
-use machine_manager::config::{SerialConfig, VmConfig};
+use machine_manager::config::{MigrateMode, SerialConfig, VmConfig};
 use migration::{MigrationManager, MigrationStatus};
 use util::{
     device_tree::{self, CompileFDT, FdtBuilder},
@@ -160,8 +160,12 @@ impl MachineOps for LightMachine {
             vm_config.machine_config.nr_cpus,
         )?;

-        let boot_config =
-            locked_vm.load_boot_source(None, MEM_LAYOUT[LayoutEntryType::Mem as usize].0)?;
+        let migrate_info = locked_vm.get_migrate_info();
+        let boot_config = if migrate_info.0 == MigrateMode::Unknown {
+            Some(locked_vm.load_boot_source(None, MEM_LAYOUT[LayoutEntryType::Mem as usize].0)?)
+        } else {
+            None
+        };
         let cpu_config = locked_vm.load_cpu_features(vm_config)?;

         let hypervisor = locked_vm.base.hypervisor.clone();
@@ -186,20 +190,22 @@ impl MachineOps for LightMachine {
         locked_vm.add_devices(vm_config)?;
         trace::replaceable_info(&locked_vm.replaceable_info);

-        let mut fdt_helper = FdtBuilder::new();
-        locked_vm
-            .generate_fdt_node(&mut fdt_helper)
-            .with_context(|| MachineError::GenFdtErr)?;
-        let fdt_vec = fdt_helper.finish()?;
-        locked_vm
-            .base
-            .sys_mem
-            .write(
-                &mut fdt_vec.as_slice(),
-                GuestAddress(boot_config.fdt_addr),
-                fdt_vec.len() as u64,
-            )
-            .with_context(|| MachineError::WrtFdtErr(boot_config.fdt_addr, fdt_vec.len()))?;
+        if let Some(boot_cfg) = boot_config {
+            let mut fdt_helper = FdtBuilder::new();
+            locked_vm
+                .generate_fdt_node(&mut fdt_helper)
+                .with_context(|| MachineError::GenFdtErr)?;
+            let fdt_vec = fdt_helper.finish()?;
+            locked_vm
+                .base
+                .sys_mem
+                .write(
+                    &mut fdt_vec.as_slice(),
+                    GuestAddress(boot_cfg.fdt_addr),
+                    fdt_vec.len() as u64,
+                )
+                .with_context(|| MachineError::WrtFdtErr(boot_cfg.fdt_addr, fdt_vec.len()))?;
+        }

         MigrationManager::register_vm_instance(vm.clone());
         MigrationManager::register_migration_instance(locked_vm.base.migration_hypervisor.clone());
diff --git a/machine/src/aarch64/standard.rs b/machine/src/aarch64/standard.rs
index 8544a2b..416298a 100644
--- a/machine/src/aarch64/standard.rs
+++ b/machine/src/aarch64/standard.rs
@@ -606,8 +606,16 @@ impl MachineOps for StdMachine {
             .with_context(|| MachineError::InitPCIeHostErr)?;
         let fwcfg = locked_vm.add_fwcfg_device(nr_cpus)?;

-        let boot_config = locked_vm
-            .load_boot_source(fwcfg.as_ref(), MEM_LAYOUT[LayoutEntryType::Mem as usize].0)?;
+        let migrate = locked_vm.get_migrate_info();
+        let boot_config =
+            if migrate.0 == MigrateMode::Unknown {
+                Some(locked_vm.load_boot_source(
+                    fwcfg.as_ref(),
+                    MEM_LAYOUT[LayoutEntryType::Mem as usize].0,
+                )?)
+            } else {
+                None
+            };
         let cpu_config = locked_vm.load_cpu_features(vm_config)?;

         let hypervisor = locked_vm.base.hypervisor.clone();
@@ -632,21 +640,23 @@ impl MachineOps for StdMachine {
             .add_devices(vm_config)
             .with_context(|| "Failed to add devices")?;

-        let mut fdt_helper = FdtBuilder::new();
-        locked_vm
-            .generate_fdt_node(&mut fdt_helper)
-            .with_context(|| MachineError::GenFdtErr)?;
-        let fdt_vec = fdt_helper.finish()?;
-        locked_vm.dtb_vec = fdt_vec.clone();
-        locked_vm
-            .base
-            .sys_mem
-            .write(
-                &mut fdt_vec.as_slice(),
-                GuestAddress(boot_config.fdt_addr),
-                fdt_vec.len() as u64,
-            )
-            .with_context(|| MachineError::WrtFdtErr(boot_config.fdt_addr, fdt_vec.len()))?;
+        if let Some(boot_cfg) = boot_config {
+            let mut fdt_helper = FdtBuilder::new();
+            locked_vm
+                .generate_fdt_node(&mut fdt_helper)
+                .with_context(|| MachineError::GenFdtErr)?;
+            let fdt_vec = fdt_helper.finish()?;
+            locked_vm.dtb_vec = fdt_vec.clone();
+            locked_vm
+                .base
+                .sys_mem
+                .write(
+                    &mut fdt_vec.as_slice(),
+                    GuestAddress(boot_cfg.fdt_addr),
+                    fdt_vec.len() as u64,
+                )
+                .with_context(|| MachineError::WrtFdtErr(boot_cfg.fdt_addr, fdt_vec.len()))?;
+        }

         // If it is direct kernel boot mode, the ACPI can not be enabled.
         if let Some(fw_cfg) = fwcfg {
diff --git a/machine/src/lib.rs b/machine/src/lib.rs
index 6c13c03..c1c0c22 100644
--- a/machine/src/lib.rs
+++ b/machine/src/lib.rs
@@ -465,7 +465,7 @@ pub trait MachineOps {
         nr_cpus: u8,
         #[cfg(target_arch = "x86_64")] max_cpus: u8,
         topology: &CPUTopology,
-        boot_cfg: &CPUBootConfig,
+        boot_cfg: &Option<CPUBootConfig>,
         #[cfg(target_arch = "aarch64")] vcpu_cfg: &CPUFeatures,
     ) -> Result<Vec<Arc<CPU>>>
     where
diff --git a/machine/src/x86_64/micro.rs b/machine/src/x86_64/micro.rs
index 7b4e08e..77ea440 100644
--- a/machine/src/x86_64/micro.rs
+++ b/machine/src/x86_64/micro.rs
@@ -22,7 +22,7 @@ use cpu::{CPUBootConfig, CPUTopology};
 use devices::legacy::FwCfgOps;
 use hypervisor::kvm::x86_64::*;
 use hypervisor::kvm::*;
-use machine_manager::config::{SerialConfig, VmConfig};
+use machine_manager::config::{MigrateMode, SerialConfig, VmConfig};
 use migration::{MigrationManager, MigrationStatus};
 use util::seccomp::{BpfRule, SeccompCmpOpt};
 use virtio::VirtioMmioDevice;
@@ -174,7 +174,12 @@ impl MachineOps for LightMachine {
         locked_vm.add_devices(vm_config)?;
         trace::replaceable_info(&locked_vm.replaceable_info);

-        let boot_config = locked_vm.load_boot_source(None)?;
+        let migrate_info = locked_vm.get_migrate_info();
+        let boot_config = if migrate_info.0 == MigrateMode::Unknown {
+            Some(locked_vm.load_boot_source(None)?)
+        } else {
+            None
+        };
         let hypervisor = locked_vm.base.hypervisor.clone();
         locked_vm.base.cpus.extend(<Self as MachineOps>::init_vcpu(
             vm.clone(),
diff --git a/machine/src/x86_64/standard.rs b/machine/src/x86_64/standard.rs
index 790e542..3aac836 100644
--- a/machine/src/x86_64/standard.rs
+++ b/machine/src/x86_64/standard.rs
@@ -371,7 +371,7 @@ impl StdMachineOps for StdMachine {
                 hypervisor,
                 self.base.cpu_topo.max_cpus,
             )?;
-            vcpu.realize(boot_cfg, topology).with_context(|| {
+            vcpu.realize(&Some(boot_cfg), topology).with_context(|| {
                 format!(
                     "Failed to realize arch cpu register/features for CPU {}",
                     vcpu_id
@@ -559,7 +559,12 @@ impl MachineOps for StdMachine {
         locked_vm.add_devices(vm_config)?;

         let fwcfg = locked_vm.add_fwcfg_device(nr_cpus, max_cpus)?;
-        let boot_config = locked_vm.load_boot_source(fwcfg.as_ref())?;
+        let migrate = locked_vm.get_migrate_info();
+        let boot_config = if migrate.0 == MigrateMode::Unknown {
+            Some(locked_vm.load_boot_source(fwcfg.as_ref())?)
+        } else {
+            None
+        };
         let topology = CPUTopology::new().set_topology((
             vm_config.machine_config.nr_threads,
             vm_config.machine_config.nr_cores,
@@ -575,7 +580,9 @@ impl MachineOps for StdMachine {
             &boot_config,
         )?);

-        locked_vm.init_cpu_controller(boot_config, topology, vm.clone())?;
+        if migrate.0 == MigrateMode::Unknown {
+            locked_vm.init_cpu_controller(boot_config.unwrap(), topology, vm.clone())?;
+        }

         if let Some(fw_cfg) = fwcfg {
             locked_vm
--
2.33.0

