From 438d15e7a7c0edf9f15a3201b87a43887d85caa4 Mon Sep 17 00:00:00 2001 From: Mingwang Li Date: Wed, 11 Dec 2024 19:21:40 +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 --- ...x-VM-run-failed-from-memory-snapshot.patch | 302 ++++++++++++++++++ stratovirt.spec | 6 +- 2 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 0002-snapshot-bugfix-VM-run-failed-from-memory-snapshot.patch 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 0000000..e1445ec --- /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 6a94585..c20ed18 100644 --- a/stratovirt.spec +++ b/stratovirt.spec @@ -6,7 +6,7 @@ Name: stratovirt Version: 2.4.0 -Release: 3 +Release: 4 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 @@ -104,6 +105,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-4 +- bugfix VM run failed from memory snapshot + * Thu Nov 21 2024 jinyihua - 2.4.0-3 - Micro fix the ioctl allow for aarch64 -- Gitee