diff --git a/0002-snapshot-bugfix-VM-run-failed-from-memory-snapshot.patch b/0002-snapshot-bugfix-VM-run-failed-from-memory-snapshot.patch
new file mode 100644
index 0000000000000000000000000000000000000000..e1445ecda2f2cca672ef669f1642b16744b2edc6
--- /dev/null
+++ b/0002-snapshot-bugfix-VM-run-failed-from-memory-snapshot.patch
@@ -0,0 +1,302 @@
+From 3a5ef152b5e803998e6ec5a1e7172c01fcce8bcf Mon Sep 17 00:00:00 2001
+From: l00484210
+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
+---
+ 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,
+ 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,
+ 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,
+ #[cfg(target_arch = "aarch64")] vcpu_cfg: &CPUFeatures,
+ ) -> Result>>
+ 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(::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
+
diff --git a/stratovirt.spec b/stratovirt.spec
index 66b063d3eed111a1861a823174ae2906a823f92a..59d37e08cc610dff23299f0f3e4a1d99eeac18c5 100644
--- a/stratovirt.spec
+++ b/stratovirt.spec
@@ -6,7 +6,7 @@
Name: stratovirt
Version: 2.4.0
-Release: 2
+Release: 3
Summary: StratoVirt is an opensource VMM(Virtual Machine Manager) which aims to perform next generation virtualization.
License: MulanPSL-2.0
@@ -14,6 +14,7 @@ URL: https://gitee.com/openeuler/stratovirt
Source0: https://gitee.com/openeuler/stratovirt/releases/download/v%{version}/%{name}-%{version}.tar.gz
Patch001:0001-Micro-fix-the-ioctl-allow-for-aarch64.patch
+Patch002:0002-snapshot-bugfix-VM-run-failed-from-memory-snapshot.patch
ExclusiveArch: x86_64 aarch64
@@ -101,6 +102,9 @@ install -d %{buildroot}%{_libdir}/stratovirt/static
install -D -m555 ./target/%{rust_musl_target}/release/stratovirt %{buildroot}%{_libdir}/stratovirt/static
%changelog
+* Wed Dec 11 2024 Mingwang Li - 2.4.0-3
+- bugfix VM run failed from memory snapshot
+
* Thu Nov 21 2024 jinyihua - 2.4.0-2
- Micro fix the ioctl allow for aarch64