mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
arch, vmm: Add CPUID check to the 'Config' step of live migration
We now send not only the 'VmConfig' at the 'Command::Config' step of live migration, but also send the 'common CPUID'. In this way, we can check the compatibility of CPUID features between the source and destination VMs, and abort live migration early if needed. Signed-off-by: Bo Chen <chen.bo@intel.com>
This commit is contained in:
+83
-4
@@ -284,6 +284,13 @@ pub fn start_vmm_thread(
|
||||
Ok(thread)
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
struct VmMigrationConfig {
|
||||
vm_config: Arc<Mutex<VmConfig>>,
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
common_cpuid: hypervisor::CpuId,
|
||||
}
|
||||
|
||||
pub struct Vmm {
|
||||
epoll: EpollContext,
|
||||
exit_evt: EventFd,
|
||||
@@ -743,8 +750,47 @@ impl Vmm {
|
||||
socket
|
||||
.read_exact(&mut data)
|
||||
.map_err(MigratableError::MigrateSocket)?;
|
||||
let config: VmConfig = serde_json::from_slice(&data).map_err(|e| {
|
||||
MigratableError::MigrateReceive(anyhow!("Error deserialising config: {}", e))
|
||||
|
||||
let vm_migration_config: VmMigrationConfig =
|
||||
serde_json::from_slice(&data).map_err(|e| {
|
||||
MigratableError::MigrateReceive(anyhow!("Error deserialising config: {}", e))
|
||||
})?;
|
||||
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
// We check the `CPUID` compatibility of between the source vm and destination, which is
|
||||
// mostly about feature compatibility and "topology/sgx" leaves are not relevant.
|
||||
let dest_cpuid = {
|
||||
let vm_config = &vm_migration_config.vm_config.lock().unwrap();
|
||||
#[cfg(feature = "tdx")]
|
||||
let tdx_enabled = vm_config.tdx.is_some();
|
||||
let phys_bits = vm::physical_bits(
|
||||
vm_config.cpus.max_phys_bits,
|
||||
#[cfg(feature = "tdx")]
|
||||
tdx_enabled,
|
||||
);
|
||||
arch::generate_common_cpuid(
|
||||
self.hypervisor.clone(),
|
||||
None,
|
||||
None,
|
||||
phys_bits,
|
||||
vm_config.cpus.kvm_hyperv,
|
||||
#[cfg(feature = "tdx")]
|
||||
tdx_enabled,
|
||||
)
|
||||
.map_err(|e| {
|
||||
MigratableError::MigrateReceive(anyhow!("Error generating common cpuid': {:?}", e))
|
||||
})?
|
||||
};
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
arch::CpuidFeatureEntry::check_cpuid_compatibility(
|
||||
&vm_migration_config.common_cpuid,
|
||||
&dest_cpuid,
|
||||
)
|
||||
.map_err(|e| {
|
||||
MigratableError::MigrateReceive(anyhow!(
|
||||
"Error checking cpu feature compatibility': {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
||||
let exit_evt = self.exit_evt.try_clone().map_err(|e| {
|
||||
@@ -757,7 +803,7 @@ impl Vmm {
|
||||
MigratableError::MigrateReceive(anyhow!("Error cloning activate EventFd: {}", e))
|
||||
})?;
|
||||
|
||||
self.vm_config = Some(Arc::new(Mutex::new(config)));
|
||||
self.vm_config = Some(vm_migration_config.vm_config);
|
||||
let vm = Vm::new_from_migration(
|
||||
self.vm_config.clone().unwrap(),
|
||||
exit_evt,
|
||||
@@ -998,7 +1044,40 @@ impl Vmm {
|
||||
}
|
||||
|
||||
// Send config
|
||||
let config_data = serde_json::to_vec(&vm.get_config()).unwrap();
|
||||
let vm_config = vm.get_config();
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
let common_cpuid = {
|
||||
#[cfg(feature = "tdx")]
|
||||
let tdx_enabled = vm_config.lock().unwrap().tdx.is_some();
|
||||
let phys_bits = vm::physical_bits(
|
||||
vm_config.lock().unwrap().cpus.max_phys_bits,
|
||||
#[cfg(feature = "tdx")]
|
||||
tdx_enabled,
|
||||
);
|
||||
arch::generate_common_cpuid(
|
||||
self.hypervisor.clone(),
|
||||
None,
|
||||
None,
|
||||
phys_bits,
|
||||
vm_config.lock().unwrap().cpus.kvm_hyperv,
|
||||
#[cfg(feature = "tdx")]
|
||||
tdx_enabled,
|
||||
)
|
||||
.map_err(|e| {
|
||||
MigratableError::MigrateReceive(anyhow!(
|
||||
"Error generating common cpuid': {:?}",
|
||||
e
|
||||
))
|
||||
})?
|
||||
};
|
||||
|
||||
let vm_migration_config = VmMigrationConfig {
|
||||
vm_config,
|
||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||
common_cpuid,
|
||||
};
|
||||
|
||||
let config_data = serde_json::to_vec(&vm_migration_config).unwrap();
|
||||
Request::config(config_data.len() as u64).write_to(&mut socket)?;
|
||||
socket
|
||||
.write_all(&config_data)
|
||||
|
||||
Reference in New Issue
Block a user