vmm, hypervisor: Fix snapshot/restore for Windows guest

The snasphot/restore feature is not working because some CPU states are
not properly saved, which means they can't be restored later on.

First thing, we ensure the CPUID is stored so that it can be properly
restored later. The code is simplified and pushed down to the hypervisor
crate.

Second thing, we identify for each vCPU if the Hyper-V SynIC device is
emulated or not. In case it is, that means some specific MSRs will be
set by the guest. These MSRs must be saved in order to properly restore
the VM.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf
2020-10-16 18:12:46 +02:00
committed by Rob Bradford
parent 700f63fad8
commit 28e12e9f3a
4 changed files with 41 additions and 16 deletions

View File

@@ -26,9 +26,9 @@ use anyhow::anyhow;
use arch::layout;
#[cfg(target_arch = "x86_64")]
use arch::x86_64::SgxEpcSection;
use arch::EntryPoint;
#[cfg(target_arch = "x86_64")]
use arch::{CpuidPatch, CpuidReg};
use arch::CpuidPatch;
use arch::EntryPoint;
use devices::interrupt_controller::InterruptController;
#[cfg(target_arch = "aarch64")]
use hypervisor::kvm::kvm_bindings;
@@ -688,19 +688,6 @@ impl CpuManager {
let vcpu = Vcpu::new(cpu_id, &self.vm, interrupt_controller)?;
if let Some(snapshot) = snapshot {
#[cfg(target_arch = "x86_64")]
{
let mut cpuid = self.cpuid.clone();
CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(cpu_id));
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1f, None, CpuidReg::EDX, u32::from(cpu_id));
vcpu.lock()
.unwrap()
.vcpu
.set_cpuid2(&cpuid)
.map_err(|e| Error::SetSupportedCpusFailed(e.into()))?;
}
// AArch64 vCPUs should be initialized after created.
#[cfg(target_arch = "aarch64")]
vcpu.lock().unwrap().init(&self.vm)?;

View File

@@ -183,6 +183,7 @@ fn create_vmm_ioctl_seccomp_rule_common() -> Result<Vec<SeccompRule>, Error> {
fn create_vmm_ioctl_seccomp_rule() -> Result<Vec<SeccompRule>, Error> {
const KVM_CREATE_PIT2: u64 = 0x4040_ae77;
const KVM_GET_CLOCK: u64 = 0x8030_ae7c;
const KVM_GET_CPUID2: u64 = 0xc008_ae91;
const KVM_GET_FPU: u64 = 0x81a0_ae8c;
const KVM_GET_LAPIC: u64 = 0x8400_ae8e;
const KVM_GET_MSR_INDEX_LIST: u64 = 0xc004_ae02;
@@ -205,6 +206,7 @@ fn create_vmm_ioctl_seccomp_rule() -> Result<Vec<SeccompRule>, Error> {
let mut arch_rules = or![
and![Cond::new(1, ArgLen::DWORD, Eq, KVM_CREATE_PIT2)?],
and![Cond::new(1, ArgLen::DWORD, Eq, KVM_GET_CLOCK,)?],
and![Cond::new(1, ArgLen::DWORD, Eq, KVM_GET_CPUID2,)?],
and![Cond::new(1, ArgLen::DWORD, Eq, KVM_GET_FPU)?],
and![Cond::new(1, ArgLen::DWORD, Eq, KVM_GET_LAPIC)?],
and![Cond::new(1, ArgLen::DWORD, Eq, KVM_GET_MSR_INDEX_LIST)?],