From 81895b9b40c591ff45a769fcefa70d1c73dc0e67 Mon Sep 17 00:00:00 2001 From: Muminul Islam Date: Thu, 8 Jul 2021 10:07:18 -0700 Subject: [PATCH] hypervisor: Implement start/stop_dirty_log for MSHV This patch modify the existing live migration code to support MSHV. Adds couple of new functions to enable and disable dirty page tracking. Add missing IOCTL to the seccomp rules for live migration. Adds necessary flags for MSHV. This changes don't affect KVM functionality at all. In order to get better performance it is good to enable dirty page tracking when we start live migration and disable it when the migration is done. Signed-off-by: Muminul Islam --- hypervisor/src/mshv/mod.rs | 23 +++++++++++++++++------ vmm/src/seccomp_filters.rs | 9 +++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index e377663db..b365e4e77 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -34,6 +34,7 @@ use std::fs::File; use std::os::unix::io::AsRawFd; const DIRTY_BITMAP_CLEAR_DIRTY: u64 = 0x4; +const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8; pub const PAGE_SHIFT: usize = 12; #[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)] @@ -905,17 +906,27 @@ impl vm::Vm for MshvVm { /// Start logging dirty pages /// fn start_dirty_log(&self) -> vm::Result<()> { - Err(vm::HypervisorVmError::StartDirtyLog(anyhow!( - "functionality not implemented" - ))) + self.fd + .enable_dirty_page_tracking() + .map_err(|e| vm::HypervisorVmError::StartDirtyLog(e.into())) } /// /// Stop logging dirty pages /// fn stop_dirty_log(&self) -> vm::Result<()> { - Err(vm::HypervisorVmError::StopDirtyLog(anyhow!( - "functionality not implemented" - ))) + let dirty_log_slots = self.dirty_log_slots.read().unwrap(); + // Before disabling the dirty page tracking we need + // to set the dirty bits in the Hypervisor + // This is a requirement from Microsoft Hypervisor + for (_, s) in dirty_log_slots.iter() { + self.fd + .get_dirty_log(s.guest_pfn, s.memory_size as usize, DIRTY_BITMAP_SET_DIRTY) + .map_err(|e| vm::HypervisorVmError::StartDirtyLog(e.into()))?; + } + self.fd + .disable_dirty_page_tracking() + .map_err(|e| vm::HypervisorVmError::StartDirtyLog(e.into()))?; + Ok(()) } /// /// Get dirty pages bitmap (one bit per page) diff --git a/vmm/src/seccomp_filters.rs b/vmm/src/seccomp_filters.rs index 67fdbc4a3..ce7b328b8 100644 --- a/vmm/src/seccomp_filters.rs +++ b/vmm/src/seccomp_filters.rs @@ -141,6 +141,8 @@ mod mshv { pub const MSHV_RUN_VP: u64 = 0x8100_b807; pub const MSHV_GET_VP_STATE: u64 = 0xc028_b80a; pub const MSHV_SET_VP_STATE: u64 = 0xc028_b80b; + pub const MSHV_SET_PARTITION_PROPERTY: u64 = 0x4010_b80c; + pub const MSHV_GET_GPA_ACCESS_STATES: u64 = 0xc01c_b812; } #[cfg(feature = "mshv")] use mshv::*; @@ -161,6 +163,13 @@ fn create_vmm_ioctl_seccomp_rule_common_mshv() -> Result, Error and![Cond::new(1, ArgLen::DWORD, Eq, MSHV_RUN_VP)?], and![Cond::new(1, ArgLen::DWORD, Eq, MSHV_GET_VP_STATE)?], and![Cond::new(1, ArgLen::DWORD, Eq, MSHV_SET_VP_STATE)?], + and![Cond::new( + 1, + ArgLen::DWORD, + Eq, + MSHV_SET_PARTITION_PROPERTY + )?], + and![Cond::new(1, ArgLen::DWORD, Eq, MSHV_GET_GPA_ACCESS_STATES)?], ]) }