From e35d4c5b2853a00b80dd1ec67df36a6307a08006 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Tue, 30 Jun 2020 13:16:54 +0200 Subject: [PATCH] hypervisor: Store all supported MSRs On x86 architecture, we need to save a list of MSRs as part of the vCPU state. By providing the full list of MSRs supported by KVM, this patch fixes the remaining snapshot/restore issues, as the vCPU is restored with all its previous states. Signed-off-by: Sebastien Boeuf --- hypervisor/src/kvm/mod.rs | 41 +++++++++++++++++++++++++++++--------- vmm/src/seccomp_filters.rs | 2 ++ 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 85c23f82a..9df1b9ce5 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -26,8 +26,7 @@ pub mod x86_64; #[cfg(target_arch = "x86_64")] use x86_64::{ - boot_msr_entries, check_required_kvm_extensions, FpuState, SpecialRegisters, StandardRegisters, - KVM_TSS_ADDRESS, + check_required_kvm_extensions, FpuState, SpecialRegisters, StandardRegisters, KVM_TSS_ADDRESS, }; #[cfg(target_arch = "x86_64")] @@ -67,6 +66,8 @@ pub use { /// Wrapper over KVM VM ioctls. pub struct KvmVm { fd: Arc, + #[cfg(target_arch = "x86_64")] + msrs: MsrEntries, } /// /// Implementation of Vm trait for KVM @@ -120,7 +121,11 @@ impl vm::Vm for KvmVm { .fd .create_vcpu(id) .map_err(|e| vm::HypervisorVmError::CreateVcpu(e.into()))?; - let vcpu = KvmVcpu { fd: vc }; + let vcpu = KvmVcpu { + fd: vc, + #[cfg(target_arch = "x86_64")] + msrs: self.msrs.clone(), + }; Ok(Arc::new(vcpu)) } /// @@ -262,11 +267,9 @@ impl hypervisor::Hypervisor for KvmHypervisor { /// let vm = hypervisor.create_vm().unwrap() /// fn create_vm(&self) -> hypervisor::Result> { - let kvm = Kvm::new().map_err(|e| hypervisor::HypervisorError::VmCreate(e.into()))?; - let fd: VmFd; loop { - match kvm.create_vm() { + match self.kvm.create_vm() { Ok(res) => fd = res, Err(e) => { if e.errno() == libc::EINTR { @@ -281,9 +284,27 @@ impl hypervisor::Hypervisor for KvmHypervisor { } break; } + let vm_fd = Arc::new(fd); - let kvm_fd = KvmVm { fd: vm_fd }; - Ok(Arc::new(kvm_fd)) + + #[cfg(target_arch = "x86_64")] + { + let msr_list = self.get_msr_list()?; + let num_msrs = msr_list.as_fam_struct_ref().nmsrs as usize; + let mut msrs = MsrEntries::new(num_msrs); + let indices = msr_list.as_slice(); + let msr_entries = msrs.as_mut_slice(); + for (pos, index) in indices.iter().enumerate() { + msr_entries[pos].index = *index; + } + + Ok(Arc::new(KvmVm { fd: vm_fd, msrs })) + } + + #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] + { + Ok(Arc::new(KvmVm { fd: vm_fd })) + } } fn check_required_extensions(&self) -> hypervisor::Result<()> { @@ -346,6 +367,8 @@ impl hypervisor::Hypervisor for KvmHypervisor { /// Vcpu struct for KVM pub struct KvmVcpu { fd: VcpuFd, + #[cfg(target_arch = "x86_64")] + msrs: MsrEntries, } /// Implementation of Vcpu trait for KVM /// Example: @@ -625,7 +648,7 @@ impl cpu::Vcpu for KvmVcpu { let xcrs = self.get_xcrs()?; let lapic_state = self.get_lapic()?; let fpu = self.get_fpu()?; - let mut msrs = boot_msr_entries(); + let mut msrs = self.msrs.clone(); self.get_msrs(&mut msrs)?; let vcpu_events = self.get_vcpu_events()?; diff --git a/vmm/src/seccomp_filters.rs b/vmm/src/seccomp_filters.rs index 427a311c7..c32dce099 100644 --- a/vmm/src/seccomp_filters.rs +++ b/vmm/src/seccomp_filters.rs @@ -80,6 +80,7 @@ const KVM_GET_XCRS: u64 = 0x8188_aea6; const KVM_GET_FPU: u64 = 0x81a0_ae8c; const KVM_GET_LAPIC: u64 = 0x8400_ae8e; const KVM_GET_XSAVE: u64 = 0x9000_aea4; +const KVM_GET_MSR_INDEX_LIST: u64 = 0xc004_ae02; const KVM_GET_SUPPORTED_CPUID: u64 = 0xc008_ae05; const KVM_GET_MSRS: u64 = 0xc008_ae88; const KVM_CREATE_DEVICE: u64 = 0xc00c_aee0; @@ -131,6 +132,7 @@ fn create_vmm_ioctl_seccomp_rule() -> Result, Error> { 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_MP_STATE)?], + and![Cond::new(1, ArgLen::DWORD, Eq, KVM_GET_MSR_INDEX_LIST)?], and![Cond::new(1, ArgLen::DWORD, Eq, KVM_GET_MSRS)?], and![Cond::new(1, ArgLen::DWORD, Eq, KVM_GET_REGS)?], and![Cond::new(1, ArgLen::DWORD, Eq, KVM_GET_SREGS)?],