diff mbox

[v4,2/4] KVM: New data type and ioctl for ring-based dirty memory tracking

Message ID CY1PR08MB199239F086270A05AB546A63F05B0@CY1PR08MB1992.namprd08.prod.outlook.com (mailing list archive)
State New, archived
Headers show

Commit Message

Cao, Lei Feb. 15, 2017, 6:27 p.m. UTC
Add new data type, struct kvm_gfn_ring, and support functions for
ring-based dirty memory logging. Add new ioctl, KVM_RESET_DIRTY_PAGES,
for dirty trap reset.

Signed-off-by: Lei Cao <lei.cao@stratus.com>
---
 arch/x86/include/asm/kvm_host.h |  2 --
 include/linux/kvm_gfn_ring.h    | 68 +++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/kvm.h        | 35 +++++++++++++++++++++
 virt/kvm/kvm_main.c             | 16 ++++++++++
 4 files changed, 119 insertions(+), 2 deletions(-)
 create mode 100644 include/linux/kvm_gfn_ring.h

Comments

kernel test robot Feb. 15, 2017, 9:13 p.m. UTC | #1
Hi Lei,

[auto build test WARNING on kvms390/next]
[also build test WARNING on v4.10-rc8]
[cannot apply to kvm/linux-next kvm-ppc/kvm-ppc-next next-20170215]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Cao-Lei/KVM-Add-new-generic-capability-for-ring-based-dirty-memory-logging/20170216-033010
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All warnings (new ones prefixed by >>):

   In file included from include/linux/kvm_host.h:36:0,
                    from arch/arm64/kernel/hibernate.c:19:
>> arch/arm64/include/asm/kvm_host.h:35:0: warning: "KVM_COALESCED_MMIO_PAGE_OFFSET" redefined
    #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
    
   In file included from include/linux/kvm_host.h:31:0,
                    from arch/arm64/kernel/hibernate.c:19:
   include/uapi/linux/kvm.h:218:0: note: this is the location of the previous definition
    #define KVM_COALESCED_MMIO_PAGE_OFFSET 2
    

vim +/KVM_COALESCED_MMIO_PAGE_OFFSET +35 arch/arm64/include/asm/kvm_host.h

4f8d6632 Marc Zyngier      2012-12-10  19   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
4f8d6632 Marc Zyngier      2012-12-10  20   */
4f8d6632 Marc Zyngier      2012-12-10  21  
4f8d6632 Marc Zyngier      2012-12-10  22  #ifndef __ARM64_KVM_HOST_H__
4f8d6632 Marc Zyngier      2012-12-10  23  #define __ARM64_KVM_HOST_H__
4f8d6632 Marc Zyngier      2012-12-10  24  
65647300 Paolo Bonzini     2014-08-29  25  #include <linux/types.h>
65647300 Paolo Bonzini     2014-08-29  26  #include <linux/kvm_types.h>
4f8d6632 Marc Zyngier      2012-12-10  27  #include <asm/kvm.h>
3a3604bc Marc Zyngier      2015-01-29  28  #include <asm/kvm_asm.h>
4f8d6632 Marc Zyngier      2012-12-10  29  #include <asm/kvm_mmio.h>
4f8d6632 Marc Zyngier      2012-12-10  30  
c1426e4c Eric Auger        2015-03-04  31  #define __KVM_HAVE_ARCH_INTC_INITIALIZED
c1426e4c Eric Auger        2015-03-04  32  
4f8d6632 Marc Zyngier      2012-12-10  33  #define KVM_USER_MEM_SLOTS 32
4f8d6632 Marc Zyngier      2012-12-10  34  #define KVM_PRIVATE_MEM_SLOTS 4
4f8d6632 Marc Zyngier      2012-12-10 @35  #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
920552b2 David Hildenbrand 2015-09-18  36  #define KVM_HALT_POLL_NS_DEFAULT 500000
4f8d6632 Marc Zyngier      2012-12-10  37  
4f8d6632 Marc Zyngier      2012-12-10  38  #include <kvm/arm_vgic.h>
4f8d6632 Marc Zyngier      2012-12-10  39  #include <kvm/arm_arch_timer.h>
04fe4726 Shannon Zhao      2015-09-11  40  #include <kvm/arm_pmu.h>
4f8d6632 Marc Zyngier      2012-12-10  41  
ef748917 Ming Lei          2015-09-02  42  #define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS
ef748917 Ming Lei          2015-09-02  43  

:::::: The code at line 35 was first introduced by commit
:::::: 4f8d6632ec71372a3b8dbb4775662c2c9025d173 arm64: KVM: kvm_arch and kvm_vcpu_arch definitions

:::::: TO: Marc Zyngier <marc.zyngier@arm.com>
:::::: CC: Marc Zyngier <marc.zyngier@arm.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot Feb. 15, 2017, 9:51 p.m. UTC | #2
Hi Lei,

[auto build test WARNING on kvms390/next]
[also build test WARNING on v4.10-rc8]
[cannot apply to kvm/linux-next kvm-ppc/kvm-ppc-next next-20170215]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Cao-Lei/KVM-Add-new-generic-capability-for-ring-based-dirty-memory-logging/20170216-033010
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git next
config: powerpc-allmodconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=powerpc 

All warnings (new ones prefixed by >>):

   In file included from include/linux/kvm_host.h:36:0,
                    from arch/powerpc/kernel/asm-offsets.c:54:
>> arch/powerpc/include/asm/kvm_host.h:49:0: warning: "KVM_COALESCED_MMIO_PAGE_OFFSET" redefined
    #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
    
   In file included from include/linux/kvm_host.h:31:0,
                    from arch/powerpc/kernel/asm-offsets.c:54:
   include/uapi/linux/kvm.h:218:0: note: this is the location of the previous definition
    #define KVM_COALESCED_MMIO_PAGE_OFFSET 2
    

vim +/KVM_COALESCED_MMIO_PAGE_OFFSET +49 arch/powerpc/include/asm/kvm_host.h

bbf45ba5 include/asm-powerpc/kvm_host.h      Hollis Blanchard     2008-04-16  33  #include <asm/kvm_asm.h>
371fefd6 arch/powerpc/include/asm/kvm_host.h Paul Mackerras       2011-06-29  34  #include <asm/processor.h>
342d3db7 arch/powerpc/include/asm/kvm_host.h Paul Mackerras       2011-12-12  35  #include <asm/page.h>
249ba1ee arch/powerpc/include/asm/kvm_host.h Alexander Graf       2012-08-03  36  #include <asm/cacheflush.h>
699a0ea0 arch/powerpc/include/asm/kvm_host.h Paul Mackerras       2014-06-02  37  #include <asm/hvcall.h>
bbf45ba5 include/asm-powerpc/kvm_host.h      Hollis Blanchard     2008-04-16  38  
371fefd6 arch/powerpc/include/asm/kvm_host.h Paul Mackerras       2011-06-29  39  #define KVM_MAX_VCPUS		NR_CPUS
371fefd6 arch/powerpc/include/asm/kvm_host.h Paul Mackerras       2011-06-29  40  #define KVM_MAX_VCORES		NR_CPUS
696066f8 arch/powerpc/include/asm/kvm_host.h Thomas Huth          2015-12-09  41  #define KVM_USER_MEM_SLOTS	512
bbf45ba5 include/asm-powerpc/kvm_host.h      Hollis Blanchard     2008-04-16  42  
0b1b1dfd arch/powerpc/include/asm/kvm_host.h Greg Kurz            2016-05-09  43  #include <asm/cputhreads.h>
0b1b1dfd arch/powerpc/include/asm/kvm_host.h Greg Kurz            2016-05-09  44  #define KVM_MAX_VCPU_ID                (threads_per_subcore * KVM_MAX_VCORES)
0b1b1dfd arch/powerpc/include/asm/kvm_host.h Greg Kurz            2016-05-09  45  
34a75b0f arch/powerpc/include/asm/kvm_host.h Paul Mackerras       2016-08-10  46  #define __KVM_HAVE_ARCH_INTC_INITIALIZED
34a75b0f arch/powerpc/include/asm/kvm_host.h Paul Mackerras       2016-08-10  47  
de56a948 arch/powerpc/include/asm/kvm_host.h Paul Mackerras       2011-06-29  48  #ifdef CONFIG_KVM_MMIO
588968b6 include/asm-powerpc/kvm_host.h      Laurent Vivier       2008-05-30 @49  #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
de56a948 arch/powerpc/include/asm/kvm_host.h Paul Mackerras       2011-06-29  50  #endif
f4944613 arch/powerpc/include/asm/kvm_host.h Suraj Jitindar Singh 2016-10-14  51  #define KVM_HALT_POLL_NS_DEFAULT 10000	/* 10 us */
588968b6 include/asm-powerpc/kvm_host.h      Laurent Vivier       2008-05-30  52  
de9ba2f3 arch/powerpc/include/asm/kvm_host.h Alexander Graf       2013-04-16  53  /* These values are internal and can be increased later */
de9ba2f3 arch/powerpc/include/asm/kvm_host.h Alexander Graf       2013-04-16  54  #define KVM_NR_IRQCHIPS          1
de9ba2f3 arch/powerpc/include/asm/kvm_host.h Alexander Graf       2013-04-16  55  #define KVM_IRQCHIP_NUM_PINS     256
de9ba2f3 arch/powerpc/include/asm/kvm_host.h Alexander Graf       2013-04-16  56  
2860c4b1 arch/powerpc/include/asm/kvm_host.h Paolo Bonzini        2016-01-07  57  /* PPC-specific vcpu->requests bit members */

:::::: The code at line 49 was first introduced by commit
:::::: 588968b6b7d34e6a88f538d1db9aca47b203623e KVM: Add coalesced MMIO support (powerpc part)

:::::: TO: Laurent Vivier <Laurent.Vivier@bull.net>
:::::: CC: Avi Kivity <avi@qumranet.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index a7066dc..6646aa5 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -43,8 +43,6 @@ 
 #define KVM_PRIVATE_MEM_SLOTS 3
 #define KVM_MEM_SLOTS_NUM (KVM_USER_MEM_SLOTS + KVM_PRIVATE_MEM_SLOTS)
 
-#define KVM_PIO_PAGE_OFFSET 1
-#define KVM_COALESCED_MMIO_PAGE_OFFSET 2
 #define KVM_HALT_POLL_NS_DEFAULT 400000
 
 #define KVM_IRQCHIP_NUM_PINS  KVM_IOAPIC_NUM_PINS
diff --git a/include/linux/kvm_gfn_ring.h b/include/linux/kvm_gfn_ring.h
new file mode 100644
index 0000000..9d5ca99
--- /dev/null
+++ b/include/linux/kvm_gfn_ring.h
@@ -0,0 +1,68 @@ 
+#ifndef KVM_GFN_RING_H
+#define KVM_GFN_RING_H
+
+/*
+ * struct kvm_dirty_ring is defined in include/uapi/linux/kvm.h.
+ *
+ * dirty_ring:  shared with userspace via mmap. dirty_ring->dirty_gfns
+ *              is the compact list that holds the dirty pages.
+ * dirty_index: free running counter that points to the next slot in
+ *              dirty_ring->dirty_gfns  where a new dirty page should go.
+ * reset_index: free running counter that points to the next dirty page
+ *              in dirty_ring->dirty_gfns for which dirty trap needs to
+ *              be reenabled
+ * size:        size of the compact list, dirty_ring->dirty_gfns
+ * soft_limit:  when the number of dirty pages in the list reaches this
+ *              limit, vcpu that owns this ring should exit to userspace
+ *              to allow userspace to harvest all the dirty pages
+ * lock:        protects dirty_ring, only in use if this is the global
+ *              ring
+ *
+ * The number of dirty pages in the ring is calculated by,
+ * dirty_index - reset_index
+ *
+ * kernel increments dirty_ring->indices.avail_index after dirty index
+ * is incremented. When userspace harvests the dirty pages, it increments
+ * dirty_ring->indices.fetch_index up to dirty_ring->indices.avail_index.
+ * When kernel reenables dirty traps for the dirty pages, it increments
+ * reset_index up to dirty_ring->indices.fetch_index.
+ *
+ */
+struct kvm_gfn_ring {
+	u16 dirty_index;
+	u16 reset_index;
+	u32 size;
+	u32 soft_limit;
+	spinlock_t lock;
+	struct kvm_dirty_ring *dirty_ring;
+};
+
+int kvm_gfn_ring_alloc(struct kvm_gfn_ring *gfnring,
+		       u32 size,
+		       u32 limit);
+
+/*
+ * called with kvm->slots_lock held, returns the number of
+ * processed pages.
+ */
+int kvm_gfn_ring_reset(struct kvm *kvm,
+		       struct kvm_gfn_ring *gfnring);
+
+/*
+ * returns 0: successfully pushed
+ *         1: successfully pushed, soft limit reached,
+ *            vcpu should exit to userspace
+ *         -EBUSY: unable to push, dirty ring full.
+ */
+int kvm_gfn_ring_push(struct kvm_gfn_ring *gfnring,
+		      u32 slot,
+		      u64 offset,
+		      bool locked);
+
+/* for use in vm_operations_struct */
+struct page *kvm_gfn_ring_get_page(struct kvm_gfn_ring *ring,
+				   u32 i);
+
+void kvm_gfn_ring_free(struct kvm_gfn_ring *ring);
+
+#endif
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 117f1f9..1a1ba4d 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -214,6 +214,10 @@  struct kvm_hyperv_exit {
 /* Encounter unexpected vm-exit due to delivery event. */
 #define KVM_INTERNAL_ERROR_DELIVERY_EV	3
 
+#define KVM_PIO_PAGE_OFFSET 1
+#define KVM_COALESCED_MMIO_PAGE_OFFSET 2
+#define KVM_DIRTY_LOG_PAGE_OFFSET 64
+
 /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
 struct kvm_run {
 	/* in */
@@ -1283,6 +1287,8 @@  struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_X86_SMM */
 #define KVM_SMI                   _IO(KVMIO,   0xb7)
 
+#define KVM_RESET_DIRTY_PAGES     _IO(KVMIO, 0xe0)
+
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
 #define KVM_DEV_ASSIGN_PCI_2_3		(1 << 1)
 #define KVM_DEV_ASSIGN_MASK_INTX	(1 << 2)
@@ -1336,4 +1342,33 @@  struct kvm_assigned_msix_entry {
 #define KVM_X2APIC_API_USE_32BIT_IDS            (1ULL << 0)
 #define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
 
+/*
+ * The following are the requirements for supporting dirty log ring
+ * (by enabling KVM_DIRTY_LOG_PAGE_OFFSET).
+ *
+ * 1. Memory accesses by KVM should call kvm_vcpu_write_* instead
+ *    of kvm_write_* so that the global dirty ring is not filled up
+ *    too quickly.
+ * 2. kvm_arch_mmu_enable_log_dirty_pt_masked should be defined for
+ *    enabling dirty logging.
+ * 3. There should not be a separate step to synchronize hardware
+ *    dirty bitmap with KVM's.
+ */
+
+struct kvm_dirty_gfn {
+	__u32 pad;
+	__u32 slot;
+	__u64 offset;
+};
+
+struct kvm_dirty_ring {
+	union {
+		struct {
+			__u16 avail_index; /* set by kernel */
+			__u16 fetch_index; /* set by userspace */
+		} indices;
+		struct kvm_dirty_gfn dirty_gfns[0];
+	};
+};
+
 #endif /* __LINUX_KVM_H */
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index f2744ce..016be4d 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2945,11 +2945,18 @@  static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
 	return kvm_vm_ioctl_check_extension(kvm, arg);
 }
 
+#ifdef KVM_DIRTY_LOG_PAGE_OFFSET
 static int kvm_vm_ioctl_enable_dirty_log_ring(struct kvm *kvm, __u32 size)
 {
 	return -EINVAL;
 }
 
+static int kvm_vm_ioctl_reset_dirty_pages(struct kvm *kvm)
+{
+	return -EINVAL;
+}
+#endif
+
 int __attribute__((weak)) kvm_vm_ioctl_enable_cap(struct kvm *kvm,
 						  struct kvm_enable_cap *cap)
 {
@@ -2961,7 +2968,11 @@  static int kvm_vm_ioctl_enable_cap_generic(struct kvm *kvm,
 {
 	switch (cap->cap) {
 	case KVM_CAP_DIRTY_LOG_RING:
+#ifdef KVM_DIRTY_LOG_PAGE_OFFSET
 		return kvm_vm_ioctl_enable_dirty_log_ring(kvm, cap->args[0]);
+#else
+		break;
+#endif
 	default:
 		return kvm_vm_ioctl_enable_cap(kvm, cap);
 	}
@@ -3135,6 +3146,11 @@  static long kvm_vm_ioctl(struct file *filp,
 	case KVM_CHECK_EXTENSION:
 		r = kvm_vm_ioctl_check_extension_generic(kvm, arg);
 		break;
+#ifdef KVM_DIRTY_LOG_PAGE_OFFSET
+	case KVM_RESET_DIRTY_PAGES:
+		r = kvm_vm_ioctl_reset_dirty_pages(kvm);
+		break;
+#endif /* KVM_DIRTY_LOG_PAGE_OFFSET */
 	default:
 		r = kvm_arch_vm_ioctl(filp, ioctl, arg);
 	}