public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [Patch v2 0/4] KVM: Guest page hinting
@ 2017-09-13 16:17 Nitesh Narayan Lal
  2017-09-13 16:17 ` [Patch v2 1/4] KVM: Support for guest " Nitesh Narayan Lal
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Nitesh Narayan Lal @ 2017-09-13 16:17 UTC (permalink / raw)
  To: kvm; +Cc: pbonzini, nilal, pagupta, wei.w.wang, yang.zhang.wz, riel, david,
	mst

Changelog in v2:
        - Addressed comments provided in v1
        - Implementation to pass the global hyperlist (carrying pages which are to be freed) to the host by using existing virtio-balloon infrastructure (deflate_vq).

I am using synchronous virtqueue_kick API for which changes in virtio_ring.c and virtio.h are picked from Wei Wang's patch-set for Virtio-balloon enhancement [2]. ("Wei, How would you like me to credit you in the final patch?"). I am using this API because it doesn't requires any memory allocation in order to pass the list of pfns to the host. Which is required because of the seqlock used in arch_free_page to prevent memory allocations.

Query:
        - So far I don't have any implementation in QEMU. I have added few prints in QEMU balloon code to ensure that the guest page hinting kick is landing in the right location. As per my understanding on using deflate_vq QEMU's "virtio_balloon_handle_output" in hw/virtio/virtio-balloon.c should be invoked after the kick. But in my case for some reason that is not getting invoked. Any suggestions where am I going wrong?

[1] http://www.spinics.net/lists/kvm/msg153666.html
[2] http://www.spinics.net/lists/kvm/msg152734.html;

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Patch v2 1/4] KVM: Support for guest page hinting
  2017-09-13 16:17 [Patch v2 0/4] KVM: Guest page hinting Nitesh Narayan Lal
@ 2017-09-13 16:17 ` Nitesh Narayan Lal
  2017-09-14 19:26   ` kbuild test robot
  2017-09-14 20:56   ` kbuild test robot
  2017-09-13 16:17 ` [Patch v2 2/4] KVM: Guest page hinting functionality Nitesh Narayan Lal
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 11+ messages in thread
From: Nitesh Narayan Lal @ 2017-09-13 16:17 UTC (permalink / raw)
  To: kvm
  Cc: pbonzini, nilal, pagupta, wei.w.wang, yang.zhang.wz, riel, david,
	mst, Nitesh Narayan Lal

From: Nitesh Narayan Lal <nilal@redhat.com>

This patch includes the following:
1. Basic skeleton for the support
2. Enablement of x86 platform to use the same

Signed-off-by: Nitesh Narayan Lal <nilal@redhat.com>
Signed-off-by: Nitesh Narayan Lal <niteshnarayanlalleo@gmail.com>
---
 arch/x86/kvm/Makefile   |  1 +
 include/linux/gfp.h     |  7 +++++++
 virt/kvm/Kconfig        |  4 ++++
 virt/kvm/page_hinting.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 58 insertions(+)
 create mode 100644 virt/kvm/page_hinting.c

diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index 09d4b17..6f7c382 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -10,6 +10,7 @@ KVM := ../../../virt/kvm
 kvm-y			+= $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
 				$(KVM)/eventfd.o $(KVM)/irqchip.o $(KVM)/vfio.o
 kvm-$(CONFIG_KVM_ASYNC_PF)	+= $(KVM)/async_pf.o
+kvm-$(CONFIG_KVM_FREE_PAGE_HINTING)	+= $(KVM)/page_hinting.o
 
 kvm-y			+= x86.o mmu.o emulate.o i8259.o irq.o lapic.o \
 			   i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index bcfb9f7..c1ce87a1 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -454,6 +454,13 @@ static inline struct zonelist *node_zonelist(int nid, gfp_t flags)
 	return NODE_DATA(nid)->node_zonelists + gfp_zonelist(flags);
 }
 
+#ifdef	CONFIG_KVM_FREE_PAGE_HINTING
+#define HAVE_ARCH_ALLOC_PAGE
+#define HAVE_ARCH_FREE_PAGE
+void arch_free_page(struct page *page, int order);
+void arch_alloc_page(struct page *page, int order);
+#endif
+
 #ifndef HAVE_ARCH_FREE_PAGE
 static inline void arch_free_page(struct page *page, int order) { }
 #endif
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index b0cc1a3..57f1c7b 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -50,3 +50,7 @@ config KVM_COMPAT
 
 config HAVE_KVM_IRQ_BYPASS
        bool
+
+config KVM_FREE_PAGE_HINTING
+       def_bool m
+       depends on KVM
diff --git a/virt/kvm/page_hinting.c b/virt/kvm/page_hinting.c
new file mode 100644
index 0000000..39d2b1d
--- /dev/null
+++ b/virt/kvm/page_hinting.c
@@ -0,0 +1,46 @@
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/page_ref.h>
+#include <linux/kvm_host.h>
+#include <linux/sort.h>
+
+#include <trace/events/kvm.h>
+
+#define MAX_FGPT_ENTRIES	1000
+#define HYPERLIST_THRESHOLD	500
+/*
+ * struct kvm_free_pages - Tracks the pages which are freed by the guest.
+ * @pfn	- page frame number for the page which is to be freed
+ * @pages - number of pages which are supposed to be freed.
+ * A global array object is used to hold the list of pfn and number of pages
+ * which are freed by the guest. This list may also have fragmentated pages so
+ * defragmentation is a must prior to the hypercall.
+ */
+struct kvm_free_pages {
+	unsigned long pfn;
+	unsigned int pages;
+};
+
+/*
+ * hypervisor_pages - It is a dummy structure passed with the hypercall.
+ * @pfn - page frame number for the page which is to be freed.
+ * @pages - number of pages which are supposed to be freed.
+ * A global array object is used to to hold the list of pfn and pages and is
+ * passed as part of the hypercall.
+ */
+struct hypervisor_pages {
+	unsigned long pfn;
+	unsigned int pages;
+};
+
+DEFINE_PER_CPU(struct kvm_free_pages [MAX_FGPT_ENTRIES], kvm_pt);
+DEFINE_PER_CPU(int, kvm_pt_idx);
+struct hypervisor_pages hypervisor_pagelist[MAX_FGPT_ENTRIES];
+
+void arch_alloc_page(struct page *page, int order)
+{
+}
+
+void arch_free_page(struct page *page, int order)
+{
+}
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Patch v2 2/4] KVM: Guest page hinting functionality
  2017-09-13 16:17 [Patch v2 0/4] KVM: Guest page hinting Nitesh Narayan Lal
  2017-09-13 16:17 ` [Patch v2 1/4] KVM: Support for guest " Nitesh Narayan Lal
@ 2017-09-13 16:17 ` Nitesh Narayan Lal
  2017-09-13 16:17 ` [Patch v2 3/4] KVM: Adding tracepoints for guest page hinting Nitesh Narayan Lal
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Nitesh Narayan Lal @ 2017-09-13 16:17 UTC (permalink / raw)
  To: kvm
  Cc: pbonzini, nilal, pagupta, wei.w.wang, yang.zhang.wz, riel, david,
	mst, Nitesh Narayan Lal

This patch adds the guest implementation in order to maintain the list of
pages which are freed by the guest and are not reused. To avoid any
reallocation it includes seqlock once the list is completely filled.
Though it doesn't carries the hypercall related changes.

Signed-off-by: Nitesh Narayan Lal <niteshnarayanlalleo@gmail.com>
---
 virt/kvm/page_hinting.c | 245 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 243 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/page_hinting.c b/virt/kvm/page_hinting.c
index 39d2b1d..658856d 100644
--- a/virt/kvm/page_hinting.c
+++ b/virt/kvm/page_hinting.c
@@ -3,8 +3,7 @@
 #include <linux/page_ref.h>
 #include <linux/kvm_host.h>
 #include <linux/sort.h>
-
-#include <trace/events/kvm.h>
+#include <linux/kernel.h>
 
 #define MAX_FGPT_ENTRIES	1000
 #define HYPERLIST_THRESHOLD	500
@@ -33,14 +32,256 @@ struct hypervisor_pages {
 	unsigned int pages;
 };
 
+static __cacheline_aligned_in_smp DEFINE_SEQLOCK(guest_page_lock);
 DEFINE_PER_CPU(struct kvm_free_pages [MAX_FGPT_ENTRIES], kvm_pt);
 DEFINE_PER_CPU(int, kvm_pt_idx);
 struct hypervisor_pages hypervisor_pagelist[MAX_FGPT_ENTRIES];
 
+static void empty_hyperlist(void)
+{
+	int i = 0;
+
+	while (i < MAX_FGPT_ENTRIES) {
+		hypervisor_pagelist[i].pfn = 0;
+		hypervisor_pagelist[i].pages = 0;
+		i++;
+	}
+}
+
+static void make_hypercall(void)
+{
+	/*
+	 * Dummy function: Tobe filled later.
+	 */
+	empty_hyperlist();
+}
+
+static int sort_pfn(const void *a1, const void *b1)
+{
+	const struct hypervisor_pages *a = a1;
+	const struct hypervisor_pages *b = b1;
+
+	if (a->pfn > b->pfn)
+		return 1;
+
+	if (a->pfn < b->pfn)
+		return -1;
+
+	return 0;
+}
+
+static int pack_hyperlist(void)
+{
+	int i = 0, j = 0;
+
+	while (i < MAX_FGPT_ENTRIES) {
+		if (hypervisor_pagelist[i].pfn != 0) {
+			if (i != j) {
+				hypervisor_pagelist[j].pfn =
+						hypervisor_pagelist[i].pfn;
+				hypervisor_pagelist[j].pages =
+						hypervisor_pagelist[i].pages;
+			}
+			j++;
+		}
+		i++;
+	}
+	i = j;
+	while (j < MAX_FGPT_ENTRIES) {
+		hypervisor_pagelist[j].pfn = 0;
+		hypervisor_pagelist[j].pages = 0;
+		j++;
+	}
+	return i;
+}
+
+int compress_hyperlist(void)
+{
+	int i = 0, j = 1, merge_counter = 0, ret = 0;
+
+	sort(hypervisor_pagelist, MAX_FGPT_ENTRIES,
+	     sizeof(struct hypervisor_pages), sort_pfn, NULL);
+	while (i < MAX_FGPT_ENTRIES && j < MAX_FGPT_ENTRIES) {
+		unsigned long pfni = hypervisor_pagelist[i].pfn;
+		unsigned int pagesi = hypervisor_pagelist[i].pages;
+		unsigned long pfnj = hypervisor_pagelist[j].pfn;
+		unsigned int pagesj = hypervisor_pagelist[j].pages;
+
+		if (pfnj <= pfni) {
+			if (((pfnj + pagesj - 1) <= (pfni + pagesi - 1)) &&
+			    ((pfnj + pagesj - 1) >= (pfni - 1))) {
+				hypervisor_pagelist[i].pfn = pfnj;
+				hypervisor_pagelist[i].pages += pfni - pfnj;
+				hypervisor_pagelist[j].pfn = 0;
+				hypervisor_pagelist[j].pages = 0;
+				j++;
+				merge_counter++;
+				continue;
+			} else if ((pfnj + pagesj - 1) > (pfni + pagesi - 1)) {
+				hypervisor_pagelist[i].pfn = pfnj;
+				hypervisor_pagelist[i].pages = pagesj;
+				hypervisor_pagelist[j].pfn = 0;
+				hypervisor_pagelist[j].pages = 0;
+				j++;
+				merge_counter++;
+				continue;
+			}
+		} else if (pfnj > pfni) {
+			if ((pfnj + pagesj - 1) > (pfni + pagesi - 1) &&
+			    (pfnj <= pfni + pagesi)) {
+				hypervisor_pagelist[i].pages +=
+						(pfnj + pagesj - 1) -
+						(pfni + pagesi - 1);
+				hypervisor_pagelist[j].pfn = 0;
+				hypervisor_pagelist[j].pages = 0;
+				j++;
+				merge_counter++;
+				continue;
+			} else if ((pfnj + pagesj - 1) <= (pfni + pagesi - 1)) {
+				hypervisor_pagelist[j].pfn = 0;
+				hypervisor_pagelist[j].pages = 0;
+				j++;
+				merge_counter++;
+				continue;
+			}
+		}
+		i = j;
+		j++;
+	}
+	if (merge_counter != 0)
+		ret = pack_hyperlist() - 1;
+	else
+		ret = MAX_FGPT_ENTRIES - 1;
+	return ret;
+}
+
+void copy_hyperlist(int hyper_idx)
+{
+	int *idx = &get_cpu_var(kvm_pt_idx);
+	struct kvm_free_pages *free_page_obj;
+	int i = 0;
+
+	free_page_obj = &get_cpu_var(kvm_pt)[0];
+	while (i < hyper_idx) {
+		free_page_obj[*idx].pfn = hypervisor_pagelist[i].pfn;
+		free_page_obj[*idx].pages = hypervisor_pagelist[i].pages;
+		*idx += 1;
+		i++;
+	}
+	empty_hyperlist();
+	put_cpu_var(kvm_pt);
+	put_cpu_var(kvm_pt_idx);
+}
+
+/*
+ * arch_free_page_slowpath() - This function adds the guest free page entries
+ * to hypervisor_pages list and also ensures defragmentation prior to addition
+ * if it is present with any entry of the kvm_free_pages list.
+ */
+void arch_free_page_slowpath(void)
+{
+	int idx = 0;
+	int hyper_idx = -1;
+	int *kvm_idx = &get_cpu_var(kvm_pt_idx);
+	struct kvm_free_pages *free_page_obj = &get_cpu_var(kvm_pt)[0];
+
+	write_seqlock(&guest_page_lock);
+	while (idx < MAX_FGPT_ENTRIES) {
+		unsigned long pfn = free_page_obj[idx].pfn;
+		unsigned long pfn_end = free_page_obj[idx].pfn +
+					free_page_obj[idx].pages - 1;
+		bool prev_free = false;
+
+		while (pfn <= pfn_end) {
+			struct page *p = pfn_to_page(pfn);
+
+			if (PageCompound(p)) {
+				struct page *head_page = compound_head(p);
+				unsigned long head_pfn = page_to_pfn(head_page);
+				unsigned int alloc_pages =
+					1 << compound_order(head_page);
+
+				pfn = head_pfn + alloc_pages;
+				prev_free = false;
+				continue;
+			}
+			if (page_ref_count(p)) {
+				pfn++;
+				prev_free = false;
+				continue;
+			}
+			/*
+			 * The page is free so add it to the list and free the
+			 * hypervisor_pagelist if required.
+			 */
+			if (!prev_free) {
+				hyper_idx++;
+				hypervisor_pagelist[hyper_idx].pfn = pfn;
+				hypervisor_pagelist[hyper_idx].pages = 1;
+				if (hyper_idx == MAX_FGPT_ENTRIES - 1) {
+					hyper_idx =  compress_hyperlist();
+					if (hyper_idx >=
+					    HYPERLIST_THRESHOLD) {
+						make_hypercall();
+						hyper_idx = 0;
+					}
+				}
+				/*
+				 * If the next contiguous page is free, it can
+				 * be added to this same entry.
+				 */
+				prev_free = true;
+			} else {
+				/*
+				 * Multiple adjacent free pages
+				 */
+				hypervisor_pagelist[hyper_idx].pages++;
+			}
+			pfn++;
+		}
+		free_page_obj[idx].pfn = 0;
+		free_page_obj[idx].pages = 0;
+		idx++;
+	}
+	*kvm_idx = 0;
+	put_cpu_var(kvm_pt);
+	put_cpu_var(kvm_pt_idx);
+	write_sequnlock(&guest_page_lock);
+}
+
 void arch_alloc_page(struct page *page, int order)
 {
+	unsigned int seq;
+
+	/*
+	 * arch_free_page will acquire the lock once the list carrying guest
+	 * free pages is full and a hypercall will be made. Until complete free
+	 * page list is traversed no further allocaiton will be allowed.
+	 */
+	do {
+		seq = read_seqbegin(&guest_page_lock);
+	} while (read_seqretry(&guest_page_lock, seq));
 }
 
 void arch_free_page(struct page *page, int order)
 {
+	int *free_page_idx = &get_cpu_var(kvm_pt_idx);
+	struct kvm_free_pages *free_page_obj;
+	unsigned long flags;
+
+	/*
+	 * use of global variables may trigger a race condition between irq and
+	 * process context causing unwanted overwrites. This will be replaced
+	 * with a better solution to prevent such race conditions.
+	 */
+	local_irq_save(flags);
+	free_page_obj = &get_cpu_var(kvm_pt)[0];
+	free_page_obj[*free_page_idx].pfn = page_to_pfn(page);
+	free_page_obj[*free_page_idx].pages = 1 << order;
+	*free_page_idx += 1;
+	if (*free_page_idx == MAX_FGPT_ENTRIES)
+		arch_free_page_slowpath();
+	put_cpu_var(kvm_pt);
+	put_cpu_var(kvm_pt_idx);
+	local_irq_restore(flags);
 }
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Patch v2 3/4] KVM: Adding tracepoints for guest page hinting
  2017-09-13 16:17 [Patch v2 0/4] KVM: Guest page hinting Nitesh Narayan Lal
  2017-09-13 16:17 ` [Patch v2 1/4] KVM: Support for guest " Nitesh Narayan Lal
  2017-09-13 16:17 ` [Patch v2 2/4] KVM: Guest page hinting functionality Nitesh Narayan Lal
@ 2017-09-13 16:17 ` Nitesh Narayan Lal
  2017-09-13 16:17 ` [Patch v2 4/4] KVM: Sending hyperlist to the host via deflate_vq Nitesh Narayan Lal
  2017-09-15  2:07 ` [Patch v2 0/4] KVM: Guest page hinting Wei Wang
  4 siblings, 0 replies; 11+ messages in thread
From: Nitesh Narayan Lal @ 2017-09-13 16:17 UTC (permalink / raw)
  To: kvm
  Cc: pbonzini, nilal, pagupta, wei.w.wang, yang.zhang.wz, riel, david,
	mst, Nitesh Narayan Lal

Signed-off-by: Nitesh Narayan Lal <niteshnarayanlalleo@gmail.com>
---
 include/trace/events/kvm.h | 101 +++++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/page_hinting.c    |  16 +++++++
 2 files changed, 117 insertions(+)

diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h
index 8ade3eb..96d29a4 100644
--- a/include/trace/events/kvm.h
+++ b/include/trace/events/kvm.h
@@ -393,6 +393,107 @@ TRACE_EVENT(kvm_halt_poll_ns,
 #define trace_kvm_halt_poll_ns_shrink(vcpu_id, new, old) \
 	trace_kvm_halt_poll_ns(false, vcpu_id, new, old)
 
+TRACE_EVENT(guest_free_page,
+	    TP_PROTO(struct page *page, unsigned int order),
+
+	TP_ARGS(page, order),
+
+	TP_STRUCT__entry(
+		__field(unsigned long, pfn)
+		__field(unsigned int, order)
+	),
+
+	TP_fast_assign(
+		__entry->pfn            = page_to_pfn(page);
+		__entry->order          = order;
+	),
+
+	TP_printk("page=%p pfn=%lu number of pages=%d",
+		  pfn_to_page(__entry->pfn),
+		  __entry->pfn,
+		  (1 << __entry->order))
+);
+
+TRACE_EVENT(guest_alloc_page,
+	    TP_PROTO(struct page *page, unsigned int order),
+
+	TP_ARGS(page, order),
+
+	TP_STRUCT__entry(
+		__field(unsigned long,  pfn)
+		__field(unsigned int,   order)
+	),
+
+	TP_fast_assign(
+		__entry->pfn            = page_to_pfn(page);
+		__entry->order          = order;
+		),
+
+	TP_printk("page=%p pfn=%lu number of pages=%d",
+		  pfn_to_page(__entry->pfn),
+		  __entry->pfn,
+		  (1 << __entry->order))
+);
+
+TRACE_EVENT(guest_free_page_slowpath,
+	    TP_PROTO(unsigned long pfn, unsigned int pages),
+
+	TP_ARGS(pfn, pages),
+
+	TP_STRUCT__entry(
+		__field(unsigned long, pfn)
+		__field(unsigned int, pages)
+	),
+
+	TP_fast_assign(
+		__entry->pfn            = pfn;
+		__entry->pages          = pages;
+	),
+
+	TP_printk("pfn=%lu number of pages=%u",
+		  __entry->pfn,
+		  __entry->pages)
+);
+
+TRACE_EVENT(guest_pfn_dump,
+	    TP_PROTO(char *type, unsigned long pfn, unsigned int pages),
+
+	TP_ARGS(type, pfn, pages),
+
+	TP_STRUCT__entry(
+		__field(char *, type)
+		__field(unsigned long, pfn)
+		__field(unsigned int, pages)
+	),
+
+	TP_fast_assign(
+		__entry->type		= type;
+		__entry->pfn            = pfn;
+		__entry->pages          = pages;
+		),
+
+	TP_printk("Type=%s pfn=%lu number of pages=%d",
+		  __entry->type,
+		  __entry->pfn,
+		  __entry->pages)
+);
+
+TRACE_EVENT(guest_str_dump,
+	    TP_PROTO(char *str),
+
+	TP_ARGS(str),
+
+	TP_STRUCT__entry(
+		__field(char *, str)
+	),
+
+	TP_fast_assign(
+		__entry->str		= str;
+		),
+
+	TP_printk("Debug=%s",
+		  __entry->str)
+);
 #endif /* _TRACE_KVM_MAIN_H */
 
 /* This part must be outside protection */
diff --git a/virt/kvm/page_hinting.c b/virt/kvm/page_hinting.c
index 658856d..090b363 100644
--- a/virt/kvm/page_hinting.c
+++ b/virt/kvm/page_hinting.c
@@ -4,6 +4,7 @@
 #include <linux/kvm_host.h>
 #include <linux/sort.h>
 #include <linux/kernel.h>
+#include <trace/events/kvm.h>
 
 #define MAX_FGPT_ENTRIES	1000
 #define HYPERLIST_THRESHOLD	500
@@ -54,6 +55,7 @@ static void make_hypercall(void)
 	 * Dummy function: Tobe filled later.
 	 */
 	empty_hyperlist();
+	trace_guest_str_dump("Hypercall to host...:");
 }
 
 static int sort_pfn(const void *a1, const void *b1)
@@ -77,6 +79,9 @@ static int pack_hyperlist(void)
 	while (i < MAX_FGPT_ENTRIES) {
 		if (hypervisor_pagelist[i].pfn != 0) {
 			if (i != j) {
+				trace_guest_pfn_dump("Packing Hyperlist",
+						hypervisor_pagelist[i].pfn,
+						hypervisor_pagelist[i].pages);
 				hypervisor_pagelist[j].pfn =
 						hypervisor_pagelist[i].pfn;
 				hypervisor_pagelist[j].pages =
@@ -163,6 +168,9 @@ void copy_hyperlist(int hyper_idx)
 
 	free_page_obj = &get_cpu_var(kvm_pt)[0];
 	while (i < hyper_idx) {
+		trace_guest_pfn_dump("HyperList entry copied",
+				     hypervisor_pagelist[i].pfn,
+				     hypervisor_pagelist[i].pages);
 		free_page_obj[*idx].pfn = hypervisor_pagelist[i].pfn;
 		free_page_obj[*idx].pages = hypervisor_pagelist[i].pages;
 		*idx += 1;
@@ -203,11 +211,14 @@ void arch_free_page_slowpath(void)
 
 				pfn = head_pfn + alloc_pages;
 				prev_free = false;
+				trace_guest_pfn_dump("Compound",
+						     head_pfn, alloc_pages);
 				continue;
 			}
 			if (page_ref_count(p)) {
 				pfn++;
 				prev_free = false;
+				trace_guest_pfn_dump("Single", pfn, 1);
 				continue;
 			}
 			/*
@@ -218,6 +229,9 @@ void arch_free_page_slowpath(void)
 				hyper_idx++;
 				hypervisor_pagelist[hyper_idx].pfn = pfn;
 				hypervisor_pagelist[hyper_idx].pages = 1;
+				trace_guest_free_page_slowpath(
+				hypervisor_pagelist[hyper_idx].pfn,
+				hypervisor_pagelist[hyper_idx].pages);
 				if (hyper_idx == MAX_FGPT_ENTRIES - 1) {
 					hyper_idx =  compress_hyperlist();
 					if (hyper_idx >=
@@ -261,6 +275,7 @@ void arch_alloc_page(struct page *page, int order)
 	do {
 		seq = read_seqbegin(&guest_page_lock);
 	} while (read_seqretry(&guest_page_lock, seq));
+	trace_guest_alloc_page(page, order);
 }
 
 void arch_free_page(struct page *page, int order)
@@ -276,6 +291,7 @@ void arch_free_page(struct page *page, int order)
 	 */
 	local_irq_save(flags);
 	free_page_obj = &get_cpu_var(kvm_pt)[0];
+	trace_guest_free_page(page, order);
 	free_page_obj[*free_page_idx].pfn = page_to_pfn(page);
 	free_page_obj[*free_page_idx].pages = 1 << order;
 	*free_page_idx += 1;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Patch v2 4/4] KVM: Sending hyperlist to the host via deflate_vq
  2017-09-13 16:17 [Patch v2 0/4] KVM: Guest page hinting Nitesh Narayan Lal
                   ` (2 preceding siblings ...)
  2017-09-13 16:17 ` [Patch v2 3/4] KVM: Adding tracepoints for guest page hinting Nitesh Narayan Lal
@ 2017-09-13 16:17 ` Nitesh Narayan Lal
  2017-09-14 20:26   ` kbuild test robot
  2017-09-14 20:29   ` kbuild test robot
  2017-09-15  2:07 ` [Patch v2 0/4] KVM: Guest page hinting Wei Wang
  4 siblings, 2 replies; 11+ messages in thread
From: Nitesh Narayan Lal @ 2017-09-13 16:17 UTC (permalink / raw)
  To: kvm
  Cc: pbonzini, nilal, pagupta, wei.w.wang, yang.zhang.wz, riel, david,
	mst, Nitesh Narayan Lal

This patch adds support in the existing virtio balloon
infrastructure so that the hyper list created could be send
to the host (QEMU) for processing by using deflate_vq.

Signed-off-by: Nitesh Narayan Lal <niteshnarayanlalleo@gmail.com>
---
 drivers/virtio/virtio_balloon.c |  48 +++++++++++
 drivers/virtio/virtio_ring.c    | 178 ++++++++++++++++++++++++++++++++++++++++
 include/linux/page_hinting.h    |  16 ++++
 include/linux/virtio.h          |  19 +++++
 virt/kvm/page_hinting.c         |  30 +++----
 5 files changed, 272 insertions(+), 19 deletions(-)
 create mode 100644 include/linux/page_hinting.h

diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index f0b3a0b..8828bc0 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -32,6 +32,7 @@
 #include <linux/mm.h>
 #include <linux/mount.h>
 #include <linux/magic.h>
+#include <linux/page_hinting.h>
 
 /*
  * Balloon device works in 4K page units.  So each page is pointed to by
@@ -95,6 +96,48 @@ static struct virtio_device_id id_table[] = {
 	{ 0 },
 };
 
+#ifdef CONFIG_KVM_FREE_PAGE_HINTING
+
+static void tell_host_one_page(struct virtio_balloon *vb, struct virtqueue *vq,
+			       unsigned int pfn)
+{
+	unsigned int id = VIRTQUEUE_DESC_ID_INIT;
+	u64 addr = pfn << VIRTIO_BALLOON_PFN_SHIFT;
+
+	virtqueue_add_chain_desc(vq, addr, PAGE_SIZE, &id, &id, 0);
+	virtqueue_add_chain(vq, id, 0, NULL, (void *)addr, NULL);
+	virtqueue_kick_sync(vq);
+}
+
+void virtballoon_page_hinting(struct virtio_balloon *vb, int hyper_entries)
+{
+	int i = 0, j = 0;
+	int pfn_cnt = 0;
+
+	for (i = 0; i < hyper_entries; i++) {
+		unsigned long pfn = hypervisor_pagelist[i].pfn;
+		unsigned long pfn_end = hypervisor_pagelist[i].pfn +
+					hypervisor_pagelist[i].pages - 1;
+		while (pfn <= pfn_end) {
+			if (pfn_cnt == VIRTIO_BALLOON_ARRAY_PFNS_MAX) {
+				j = 0;
+				while (j < pfn_cnt) {
+					tell_host_one_page(vb, vb->deflate_vq,
+							   vb->pfns[j]);
+					vb->pfns[j] = 0;
+					j++;
+				}
+				vb->num_pfns = 0;
+				pfn_cnt = 0;
+			}
+			vb->pfns[pfn_cnt++] = pfn;
+			vb->num_pfns++;
+			pfn++;
+		}
+	}
+}
+#endif
+
 static u32 page_to_balloon_pfn(struct page *page)
 {
 	unsigned long pfn = page_to_pfn(page);
@@ -581,6 +624,11 @@ static int virtballoon_probe(struct virtio_device *vdev)
 
 	virtio_device_ready(vdev);
 
+#ifdef CONFIG_KVM_FREE_PAGE_HINTING
+	request_hypercall = (void *)&virtballoon_page_hinting;
+	balloon_ptr = vb;
+#endif
+
 	if (towards_target(vb))
 		virtballoon_changed(vdev);
 	return 0;
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 5e1b548..65306d5 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -283,6 +283,8 @@ static inline int virtqueue_add(struct virtqueue *_vq,
 		return -EIO;
 	}
 
+	if (gfp == GFP_ATOMIC)
+		vq->indirect = false;
 #ifdef DEBUG
 	{
 		ktime_t now = ktime_get();
@@ -437,6 +439,131 @@ static inline int virtqueue_add(struct virtqueue *_vq,
 }
 
 /**
+ * virtqueue_add_chain - expose a chain of buffers to the other end
+ * @_vq: the struct virtqueue we're talking about.
+ * @head: desc id of the chain head.
+ * @indirect: set if the chain of descs are indrect descs.
+ * @indir_desc: the first indirect desc.
+ * @data: the token identifying the chain.
+ * @ctx: extra context for the token.
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).
+ */
+int virtqueue_add_chain(struct virtqueue *_vq,
+			unsigned int head,
+			bool indirect,
+			struct vring_desc *indir_desc,
+			void *data,
+			void *ctx)
+{
+	struct vring_virtqueue *vq = to_vvq(_vq);
+
+	/* The desc chain is empty. */
+	if (head == VIRTQUEUE_DESC_ID_INIT)
+		return 0;
+
+	START_USE(vq);
+
+	if (unlikely(vq->broken)) {
+		END_USE(vq);
+		return -EIO;
+	}
+
+	vq->desc_state[head].data = data;
+	if (indirect)
+		vq->desc_state[head].indir_desc = indir_desc;
+	if (ctx)
+		vq->desc_state[head].indir_desc = ctx;
+
+	virtqueue_kick(_vq);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(virtqueue_add_chain);
+
+/**
+ * virtqueue_add_chain_desc - add a buffer to a chain using a vring desc
+ * @vq: the struct virtqueue we're talking about.
+ * @addr: address of the buffer to add.
+ * @len: length of the buffer.
+ * @head_id: desc id of the chain head.
+ * @prev_id: desc id of the previous buffer.
+ * @in: set if the buffer is for the device to write.
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).
+ */
+int virtqueue_add_chain_desc(struct virtqueue *_vq,
+			     u64 addr,
+			     u32 len,
+			     unsigned int *head_id,
+			     unsigned int *prev_id,
+			     bool in)
+{
+	struct vring_virtqueue *vq = to_vvq(_vq);
+	struct vring_desc *desc = vq->vring.desc;
+	u16 flags = in ? VRING_DESC_F_WRITE : 0;
+	unsigned int i;
+
+	/* Sanity check */
+	if (!_vq || !head_id || !prev_id)
+		return -EINVAL;
+retry:
+	START_USE(vq);
+	if (unlikely(vq->broken)) {
+		END_USE(vq);
+		return -EIO;
+	}
+
+	if (vq->vq.num_free < 1) {
+		/*
+		 * If there is no desc avail in the vq, so kick what is
+		 * already added, and re-start to build a new chain for
+		 * the passed sg.
+		 */
+		if (likely(*head_id != VIRTQUEUE_DESC_ID_INIT)) {
+			END_USE(vq);
+			virtqueue_add_chain(_vq, *head_id, 0, NULL, vq, NULL);
+			virtqueue_kick_sync(_vq);
+			*head_id = VIRTQUEUE_DESC_ID_INIT;
+			*prev_id = VIRTQUEUE_DESC_ID_INIT;
+			goto retry;
+		} else {
+			END_USE(vq);
+			return -ENOSPC;
+		}
+	}
+
+	i = vq->free_head;
+	flags &= ~VRING_DESC_F_NEXT;
+	desc[i].flags = cpu_to_virtio16(_vq->vdev, flags);
+	desc[i].addr = cpu_to_virtio64(_vq->vdev, addr);
+	desc[i].len = cpu_to_virtio32(_vq->vdev, len);
+
+	/* Add the desc to the end of the chain */
+	if (*prev_id != VIRTQUEUE_DESC_ID_INIT) {
+		desc[*prev_id].next = cpu_to_virtio16(_vq->vdev, i);
+		desc[*prev_id].flags |= cpu_to_virtio16(_vq->vdev,
+							VRING_DESC_F_NEXT);
+	}
+	*prev_id = i;
+	if (*head_id == VIRTQUEUE_DESC_ID_INIT)
+		*head_id = *prev_id;
+
+	vq->vq.num_free--;
+	vq->free_head = virtio16_to_cpu(_vq->vdev, desc[i].next);
+	END_USE(vq);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(virtqueue_add_chain_desc);
+
+/**
  * virtqueue_add_sgs - expose buffers to other end
  * @vq: the struct virtqueue we're talking about.
  * @sgs: array of terminated scatterlists.
@@ -608,6 +735,56 @@ bool virtqueue_notify(struct virtqueue *_vq)
 EXPORT_SYMBOL_GPL(virtqueue_notify);
 
 /**
+ * virtqueue_kick_async - update after add_buf and blocking till update is done
+ * @vq: the struct virtqueue
+ *
+ * After one or more virtqueue_add_* calls, invoke this to kick
+ * the other side. Blocking till the other side is done with the update.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ *
+ * Returns false if kick failed, otherwise true.
+ */
+bool virtqueue_kick_async(struct virtqueue *vq, wait_queue_head_t wq)
+{
+	u32 len;
+
+	if (likely(virtqueue_kick(vq))) {
+		wait_event(wq, virtqueue_get_buf(vq, &len));
+		return true;
+	}
+	return false;
+}
+EXPORT_SYMBOL_GPL(virtqueue_kick_async);
+
+/**
+ * virtqueue_kick_sync - update after add_buf and busy wait till update is done
+ * @vq: the struct virtqueue
+ *
+ * After one or more virtqueue_add_* calls, invoke this to kick
+ * the other side. Busy wait till the other side is done with the update.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ *
+ * Returns false if kick failed, otherwise true.
+ */
+bool virtqueue_kick_sync(struct virtqueue *vq)
+{
+	u32 len;
+
+	if (likely(virtqueue_kick(vq))) {
+		while (!virtqueue_get_buf(vq, &len) &&
+		       !virtqueue_is_broken(vq))
+			cpu_relax();
+		return true;
+	}
+	return false;
+}
+EXPORT_SYMBOL_GPL(virtqueue_kick_sync);
+
+/**
  * virtqueue_kick - update after add_buf
  * @vq: the struct virtqueue
  *
@@ -621,6 +798,7 @@ EXPORT_SYMBOL_GPL(virtqueue_notify);
  */
 bool virtqueue_kick(struct virtqueue *vq)
 {
+	WARN_ON(1);
 	if (virtqueue_kick_prepare(vq))
 		return virtqueue_notify(vq);
 	return true;
diff --git a/include/linux/page_hinting.h b/include/linux/page_hinting.h
new file mode 100644
index 0000000..0bfb646
--- /dev/null
+++ b/include/linux/page_hinting.h
@@ -0,0 +1,16 @@
+#define MAX_FGPT_ENTRIES	1000
+/*
+ * hypervisor_pages - It is a dummy structure passed with the hypercall.
+ * @pfn - page frame number for the page which is to be freed.
+ * @pages - number of pages which are supposed to be freed.
+ * A global array object is used to to hold the list of pfn and pages and is
+ * passed as part of the hypercall.
+ */
+struct hypervisor_pages {
+	unsigned long pfn;
+	unsigned int pages;
+};
+
+extern struct hypervisor_pages hypervisor_pagelist[MAX_FGPT_ENTRIES];
+extern void (*request_hypercall)(void *, int);
+extern void *balloon_ptr;
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 28b0e96..bc95e84 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -56,6 +56,25 @@ int virtqueue_add_sgs(struct virtqueue *vq,
 		      unsigned int in_sgs,
 		      void *data,
 		      gfp_t gfp);
+/* A desc with this init id is treated as an invalid desc */
+#define VIRTQUEUE_DESC_ID_INIT UINT_MAX
+int virtqueue_add_chain_desc(struct virtqueue *_vq,
+			     u64 addr,
+			     u32 len,
+			     unsigned int *head_id,
+			     unsigned int *prev_id,
+			     bool in);
+
+int virtqueue_add_chain(struct virtqueue *_vq,
+			unsigned int head,
+			bool indirect,
+			struct vring_desc *indirect_desc,
+			void *data,
+			void *ctx);
+
+bool virtqueue_kick_sync(struct virtqueue *vq);
+
+bool virtqueue_kick_async(struct virtqueue *vq, wait_queue_head_t wq);
 
 bool virtqueue_kick(struct virtqueue *vq);
 
diff --git a/virt/kvm/page_hinting.c b/virt/kvm/page_hinting.c
index 090b363..ebc2e8b 100644
--- a/virt/kvm/page_hinting.c
+++ b/virt/kvm/page_hinting.c
@@ -5,8 +5,8 @@
 #include <linux/sort.h>
 #include <linux/kernel.h>
 #include <trace/events/kvm.h>
+#include <linux/page_hinting.h>
 
-#define MAX_FGPT_ENTRIES	1000
 #define HYPERLIST_THRESHOLD	500
 /*
  * struct kvm_free_pages - Tracks the pages which are freed by the guest.
@@ -21,22 +21,12 @@ struct kvm_free_pages {
 	unsigned int pages;
 };
 
-/*
- * hypervisor_pages - It is a dummy structure passed with the hypercall.
- * @pfn - page frame number for the page which is to be freed.
- * @pages - number of pages which are supposed to be freed.
- * A global array object is used to to hold the list of pfn and pages and is
- * passed as part of the hypercall.
- */
-struct hypervisor_pages {
-	unsigned long pfn;
-	unsigned int pages;
-};
-
 static __cacheline_aligned_in_smp DEFINE_SEQLOCK(guest_page_lock);
 DEFINE_PER_CPU(struct kvm_free_pages [MAX_FGPT_ENTRIES], kvm_pt);
 DEFINE_PER_CPU(int, kvm_pt_idx);
 struct hypervisor_pages hypervisor_pagelist[MAX_FGPT_ENTRIES];
+void (*request_hypercall)(void *, int);
+void *balloon_ptr;
 
 static void empty_hyperlist(void)
 {
@@ -49,13 +39,14 @@ static void empty_hyperlist(void)
 	}
 }
 
-static void make_hypercall(void)
+static void hyperlist_ready(int entries)
 {
 	/*
 	 * Dummy function: Tobe filled later.
 	 */
-	empty_hyperlist();
 	trace_guest_str_dump("Hypercall to host...:");
+	request_hypercall(balloon_ptr, entries);
+	empty_hyperlist();
 }
 
 static int sort_pfn(const void *a1, const void *b1)
@@ -156,7 +147,7 @@ int compress_hyperlist(void)
 	if (merge_counter != 0)
 		ret = pack_hyperlist() - 1;
 	else
-		ret = MAX_FGPT_ENTRIES - 1;
+		ret = MAX_FGPT_ENTRIES;
 	return ret;
 }
 
@@ -227,16 +218,16 @@ void arch_free_page_slowpath(void)
 			 */
 			if (!prev_free) {
 				hyper_idx++;
-				hypervisor_pagelist[hyper_idx].pfn = pfn;
-				hypervisor_pagelist[hyper_idx].pages = 1;
 				trace_guest_free_page_slowpath(
 				hypervisor_pagelist[hyper_idx].pfn,
 				hypervisor_pagelist[hyper_idx].pages);
+				hypervisor_pagelist[hyper_idx].pfn = pfn;
+				hypervisor_pagelist[hyper_idx].pages = 1;
 				if (hyper_idx == MAX_FGPT_ENTRIES - 1) {
 					hyper_idx =  compress_hyperlist();
 					if (hyper_idx >=
 					    HYPERLIST_THRESHOLD) {
-						make_hypercall();
+						hyperlist_ready(hyper_idx);
 						hyper_idx = 0;
 					}
 				}
@@ -272,6 +263,7 @@ void arch_alloc_page(struct page *page, int order)
 	 * free pages is full and a hypercall will be made. Until complete free
 	 * page list is traversed no further allocaiton will be allowed.
 	 */
+
 	do {
 		seq = read_seqbegin(&guest_page_lock);
 	} while (read_seqretry(&guest_page_lock, seq));
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [Patch v2 1/4] KVM: Support for guest page hinting
  2017-09-13 16:17 ` [Patch v2 1/4] KVM: Support for guest " Nitesh Narayan Lal
@ 2017-09-14 19:26   ` kbuild test robot
  2017-09-14 20:56   ` kbuild test robot
  1 sibling, 0 replies; 11+ messages in thread
From: kbuild test robot @ 2017-09-14 19:26 UTC (permalink / raw)
  To: Nitesh Narayan Lal
  Cc: kbuild-all, kvm, pbonzini, nilal, pagupta, wei.w.wang,
	yang.zhang.wz, riel, david, mst, Nitesh Narayan Lal

[-- Attachment #1: Type: text/plain, Size: 1272 bytes --]

Hi Nitesh,

[auto build test ERROR on kvm/linux-next]
[also build test ERROR on v4.13 next-20170914]
[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/Nitesh-Narayan-Lal/KVM-Guest-page-hinting/20170915-021634
base:   https://git.kernel.org/pub/scm/virt/kvm/kvm.git linux-next
config: x86_64-randconfig-i0-201737 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   mm/page_alloc.o: In function `__free_pages_ok':
>> page_alloc.c:(.text+0x15a0): undefined reference to `arch_free_page'
   mm/page_alloc.o: In function `post_alloc_hook':
>> page_alloc.c:(.text+0x295d): undefined reference to `arch_alloc_page'
   mm/page_alloc.o: In function `free_hot_cold_page':
   page_alloc.c:(.text+0x3bb4): undefined reference to `arch_free_page'
   mm/page_alloc.o: In function `get_page_from_freelist':
   page_alloc.c:(.text+0x4b26): undefined reference to `arch_alloc_page'

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

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 30035 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Patch v2 4/4] KVM: Sending hyperlist to the host via deflate_vq
  2017-09-13 16:17 ` [Patch v2 4/4] KVM: Sending hyperlist to the host via deflate_vq Nitesh Narayan Lal
@ 2017-09-14 20:26   ` kbuild test robot
  2017-09-14 20:29   ` kbuild test robot
  1 sibling, 0 replies; 11+ messages in thread
From: kbuild test robot @ 2017-09-14 20:26 UTC (permalink / raw)
  To: Nitesh Narayan Lal
  Cc: kbuild-all, kvm, pbonzini, nilal, pagupta, wei.w.wang,
	yang.zhang.wz, riel, david, mst, Nitesh Narayan Lal

[-- Attachment #1: Type: text/plain, Size: 1152 bytes --]

Hi Nitesh,

[auto build test ERROR on kvm/linux-next]
[also build test ERROR on v4.13 next-20170914]
[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/Nitesh-Narayan-Lal/KVM-Guest-page-hinting/20170915-021634
base:   https://git.kernel.org/pub/scm/virt/kvm/kvm.git linux-next
config: s390-default_defconfig (attached as .config)
compiler: s390x-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=s390 

All errors (new ones prefixed by >>):

>> ERROR: "balloon_ptr" [drivers/virtio/virtio_balloon.ko] undefined!
>> ERROR: "request_hypercall" [drivers/virtio/virtio_balloon.ko] undefined!
>> ERROR: "hypervisor_pagelist" [drivers/virtio/virtio_balloon.ko] undefined!

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

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 17324 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Patch v2 4/4] KVM: Sending hyperlist to the host via deflate_vq
  2017-09-13 16:17 ` [Patch v2 4/4] KVM: Sending hyperlist to the host via deflate_vq Nitesh Narayan Lal
  2017-09-14 20:26   ` kbuild test robot
@ 2017-09-14 20:29   ` kbuild test robot
  1 sibling, 0 replies; 11+ messages in thread
From: kbuild test robot @ 2017-09-14 20:29 UTC (permalink / raw)
  To: Nitesh Narayan Lal
  Cc: kbuild-all, kvm, pbonzini, nilal, pagupta, wei.w.wang,
	yang.zhang.wz, riel, david, mst, Nitesh Narayan Lal

[-- Attachment #1: Type: text/plain, Size: 1791 bytes --]

Hi Nitesh,

[auto build test ERROR on kvm/linux-next]
[also build test ERROR on v4.13 next-20170914]
[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/Nitesh-Narayan-Lal/KVM-Guest-page-hinting/20170915-021634
base:   https://git.kernel.org/pub/scm/virt/kvm/kvm.git linux-next
config: x86_64-rhel (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   mm/page_alloc.o: In function `__free_pages_ok':
   page_alloc.c:(.text+0x16e9): undefined reference to `arch_free_page'
   mm/page_alloc.o: In function `post_alloc_hook':
   page_alloc.c:(.text+0x2424): undefined reference to `arch_alloc_page'
   mm/page_alloc.o: In function `free_hot_cold_page':
   page_alloc.c:(.text+0x3307): undefined reference to `arch_free_page'
   mm/page_alloc.o: In function `get_page_from_freelist':
   page_alloc.c:(.text+0x3fdd): undefined reference to `arch_alloc_page'
   page_alloc.c:(.text+0x45e3): undefined reference to `arch_alloc_page'
   drivers/virtio/virtio_balloon.o: In function `virtballoon_page_hinting':
>> virtio_balloon.c:(.text+0x242): undefined reference to `hypervisor_pagelist'
   virtio_balloon.c:(.text+0x265): undefined reference to `hypervisor_pagelist'
   drivers/virtio/virtio_balloon.o: In function `virtballoon_probe':
>> virtio_balloon.c:(.text+0x98f): undefined reference to `request_hypercall'
>> virtio_balloon.c:(.text+0x99a): undefined reference to `balloon_ptr'

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

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 39621 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Patch v2 1/4] KVM: Support for guest page hinting
  2017-09-13 16:17 ` [Patch v2 1/4] KVM: Support for guest " Nitesh Narayan Lal
  2017-09-14 19:26   ` kbuild test robot
@ 2017-09-14 20:56   ` kbuild test robot
  1 sibling, 0 replies; 11+ messages in thread
From: kbuild test robot @ 2017-09-14 20:56 UTC (permalink / raw)
  To: Nitesh Narayan Lal
  Cc: kbuild-all, kvm, pbonzini, nilal, pagupta, wei.w.wang,
	yang.zhang.wz, riel, david, mst, Nitesh Narayan Lal

[-- Attachment #1: Type: text/plain, Size: 6625 bytes --]

Hi Nitesh,

[auto build test ERROR on kvm/linux-next]
[also build test ERROR on v4.13 next-20170914]
[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/Nitesh-Narayan-Lal/KVM-Guest-page-hinting/20170915-021634
base:   https://git.kernel.org/pub/scm/virt/kvm/kvm.git linux-next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/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 errors (new ones prefixed by >>):

   mm/page_alloc.o: In function `free_pages_prepare':
>> mm/page_alloc.c:1057: undefined reference to `arch_free_page'
   mm/page_alloc.c:1057:(.text+0x16a4): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `arch_free_page'
   mm/page_alloc.o: In function `post_alloc_hook':
>> mm/page_alloc.c:1752: undefined reference to `arch_alloc_page'
   mm/page_alloc.c:1752:(.text+0x2324): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `arch_alloc_page'
   mm/page_alloc.o: In function `free_pages_prepare':
>> mm/page_alloc.c:1057: undefined reference to `arch_free_page'
   mm/page_alloc.c:1057:(.text+0x30e8): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `arch_free_page'
   mm/page_alloc.o: In function `post_alloc_hook':
>> mm/page_alloc.c:1752: undefined reference to `arch_alloc_page'
   mm/page_alloc.c:1752:(.text+0x3c1c): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `arch_alloc_page'
>> mm/page_alloc.c:1752: undefined reference to `arch_alloc_page'
   mm/page_alloc.c:1752:(.text+0x430c): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `arch_alloc_page'

vim +1057 mm/page_alloc.c

4db7548c Mel Gorman         2016-05-19  1005  
e2769dbd Mel Gorman         2016-05-19  1006  static __always_inline bool free_pages_prepare(struct page *page,
e2769dbd Mel Gorman         2016-05-19  1007  					unsigned int order, bool check_free)
4db7548c Mel Gorman         2016-05-19  1008  {
e2769dbd Mel Gorman         2016-05-19  1009  	int bad = 0;
4db7548c Mel Gorman         2016-05-19  1010  
4db7548c Mel Gorman         2016-05-19  1011  	VM_BUG_ON_PAGE(PageTail(page), page);
4db7548c Mel Gorman         2016-05-19  1012  
e2769dbd Mel Gorman         2016-05-19  1013  	trace_mm_page_free(page, order);
e2769dbd Mel Gorman         2016-05-19  1014  	kmemcheck_free_shadow(page, order);
4db7548c Mel Gorman         2016-05-19  1015  
e2769dbd Mel Gorman         2016-05-19  1016  	/*
e2769dbd Mel Gorman         2016-05-19  1017  	 * Check tail pages before head page information is cleared to
e2769dbd Mel Gorman         2016-05-19  1018  	 * avoid checking PageCompound for order-0 pages.
e2769dbd Mel Gorman         2016-05-19  1019  	 */
e2769dbd Mel Gorman         2016-05-19  1020  	if (unlikely(order)) {
e2769dbd Mel Gorman         2016-05-19  1021  		bool compound = PageCompound(page);
e2769dbd Mel Gorman         2016-05-19  1022  		int i;
e2769dbd Mel Gorman         2016-05-19  1023  
e2769dbd Mel Gorman         2016-05-19  1024  		VM_BUG_ON_PAGE(compound && compound_order(page) != order, page);
e2769dbd Mel Gorman         2016-05-19  1025  
9a73f61b Kirill A. Shutemov 2016-07-26  1026  		if (compound)
9a73f61b Kirill A. Shutemov 2016-07-26  1027  			ClearPageDoubleMap(page);
e2769dbd Mel Gorman         2016-05-19  1028  		for (i = 1; i < (1 << order); i++) {
e2769dbd Mel Gorman         2016-05-19  1029  			if (compound)
e2769dbd Mel Gorman         2016-05-19  1030  				bad += free_tail_pages_check(page, page + i);
e2769dbd Mel Gorman         2016-05-19  1031  			if (unlikely(free_pages_check(page + i))) {
e2769dbd Mel Gorman         2016-05-19  1032  				bad++;
e2769dbd Mel Gorman         2016-05-19  1033  				continue;
e2769dbd Mel Gorman         2016-05-19  1034  			}
e2769dbd Mel Gorman         2016-05-19  1035  			(page + i)->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
e2769dbd Mel Gorman         2016-05-19  1036  		}
e2769dbd Mel Gorman         2016-05-19  1037  	}
bda807d4 Minchan Kim        2016-07-26  1038  	if (PageMappingFlags(page))
4db7548c Mel Gorman         2016-05-19  1039  		page->mapping = NULL;
c4159a75 Vladimir Davydov   2016-08-08  1040  	if (memcg_kmem_enabled() && PageKmemcg(page))
4949148a Vladimir Davydov   2016-07-26  1041  		memcg_kmem_uncharge(page, order);
e2769dbd Mel Gorman         2016-05-19  1042  	if (check_free)
e2769dbd Mel Gorman         2016-05-19  1043  		bad += free_pages_check(page);
e2769dbd Mel Gorman         2016-05-19  1044  	if (bad)
e2769dbd Mel Gorman         2016-05-19  1045  		return false;
4db7548c Mel Gorman         2016-05-19  1046  
e2769dbd Mel Gorman         2016-05-19  1047  	page_cpupid_reset_last(page);
e2769dbd Mel Gorman         2016-05-19  1048  	page->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
e2769dbd Mel Gorman         2016-05-19  1049  	reset_page_owner(page, order);
4db7548c Mel Gorman         2016-05-19  1050  
4db7548c Mel Gorman         2016-05-19  1051  	if (!PageHighMem(page)) {
4db7548c Mel Gorman         2016-05-19  1052  		debug_check_no_locks_freed(page_address(page),
e2769dbd Mel Gorman         2016-05-19  1053  					   PAGE_SIZE << order);
4db7548c Mel Gorman         2016-05-19  1054  		debug_check_no_obj_freed(page_address(page),
e2769dbd Mel Gorman         2016-05-19  1055  					   PAGE_SIZE << order);
4db7548c Mel Gorman         2016-05-19  1056  	}
e2769dbd Mel Gorman         2016-05-19 @1057  	arch_free_page(page, order);
e2769dbd Mel Gorman         2016-05-19  1058  	kernel_poison_pages(page, 1 << order, 0);
e2769dbd Mel Gorman         2016-05-19  1059  	kernel_map_pages(page, 1 << order, 0);
29b52de1 seokhoon.yoon      2016-05-20  1060  	kasan_free_pages(page, order);
4db7548c Mel Gorman         2016-05-19  1061  
4db7548c Mel Gorman         2016-05-19  1062  	return true;
4db7548c Mel Gorman         2016-05-19  1063  }
4db7548c Mel Gorman         2016-05-19  1064  

:::::: The code at line 1057 was first introduced by commit
:::::: e2769dbdc51f1baa1908ecf6c84d50f19577e1db mm, page_alloc: don't duplicate code in free_pcp_prepare

:::::: TO: Mel Gorman <mgorman@techsingularity.net>
:::::: CC: Linus Torvalds <torvalds@linux-foundation.org>

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

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 36331 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Patch v2 0/4] KVM: Guest page hinting
  2017-09-13 16:17 [Patch v2 0/4] KVM: Guest page hinting Nitesh Narayan Lal
                   ` (3 preceding siblings ...)
  2017-09-13 16:17 ` [Patch v2 4/4] KVM: Sending hyperlist to the host via deflate_vq Nitesh Narayan Lal
@ 2017-09-15  2:07 ` Wei Wang
  2017-09-15 20:16   ` Nitesh Narayan Lal
  4 siblings, 1 reply; 11+ messages in thread
From: Wei Wang @ 2017-09-15  2:07 UTC (permalink / raw)
  To: Nitesh Narayan Lal, kvm
  Cc: pbonzini, nilal, pagupta, yang.zhang.wz, riel, david, mst

On 09/14/2017 12:17 AM, Nitesh Narayan Lal wrote:
> Changelog in v2:
>          - Addressed comments provided in v1
>          - Implementation to pass the global hyperlist (carrying pages which are to be freed) to the host by using existing virtio-balloon infrastructure (deflate_vq).
>
> I am using synchronous virtqueue_kick API for which changes in virtio_ring.c and virtio.h are picked from Wei Wang's patch-set for Virtio-balloon enhancement [2]. ("Wei, How would you like me to credit you in the final patch?"). I am using this API because it doesn't requires any memory allocation in order to pass the list of pfns to the host. Which is required because of the seqlock used in arch_free_page to prevent memory allocations.
>
> Query:
>          - So far I don't have any implementation in QEMU. I have added few prints in QEMU balloon code to ensure that the guest page hinting kick is landing in the right location. As per my understanding on using deflate_vq QEMU's "virtio_balloon_handle_output" in hw/virtio/virtio-balloon.c should be invoked after the kick. But in my case for some reason that is not getting invoked. Any suggestions where am I going wrong?
>
> [1] http://www.spinics.net/lists/kvm/msg153666.html
> [2] http://www.spinics.net/lists/kvm/msg152734.html;
>

Hi Nitesh,

I had a quick look of this approach, and have some high-level questions:

1) What's the usage of the feature, in addition to accelerating live 
migration?

2) Are the free page hints continuously added to and removed from the 
per CPU arrays during the whole lifecycle of the guest whenever 
alloc/free is invoked?

3) The per-CPU arrays are sync-ed to a hypervisor page array under a 
lock. If all the CPUs happen to do the sync at the same time, the later 
ones may be possible to spin too long?


Best,
Wei

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Patch v2 0/4] KVM: Guest page hinting
  2017-09-15  2:07 ` [Patch v2 0/4] KVM: Guest page hinting Wei Wang
@ 2017-09-15 20:16   ` Nitesh Narayan Lal
  0 siblings, 0 replies; 11+ messages in thread
From: Nitesh Narayan Lal @ 2017-09-15 20:16 UTC (permalink / raw)
  To: Wei Wang, kvm; +Cc: pbonzini, pagupta, yang.zhang.wz, riel, david, mst


[-- Attachment #1.1: Type: text/plain, Size: 2596 bytes --]

Hi Wei,

On 09/14/2017 10:07 PM, Wei Wang wrote:
> On 09/14/2017 12:17 AM, Nitesh Narayan Lal wrote:
>> Changelog in v2:
>>          - Addressed comments provided in v1
>>          - Implementation to pass the global hyperlist (carrying
>> pages which are to be freed) to the host by using existing
>> virtio-balloon infrastructure (deflate_vq).
>>
>> I am using synchronous virtqueue_kick API for which changes in
>> virtio_ring.c and virtio.h are picked from Wei Wang's patch-set for
>> Virtio-balloon enhancement [2]. ("Wei, How would you like me to
>> credit you in the final patch?"). I am using this API because it
>> doesn't requires any memory allocation in order to pass the list of
>> pfns to the host. Which is required because of the seqlock used in
>> arch_free_page to prevent memory allocations.
>>
>> Query:
>>          - So far I don't have any implementation in QEMU. I have
>> added few prints in QEMU balloon code to ensure that the guest page
>> hinting kick is landing in the right location. As per my
>> understanding on using deflate_vq QEMU's
>> "virtio_balloon_handle_output" in hw/virtio/virtio-balloon.c should
>> be invoked after the kick. But in my case for some reason that is not
>> getting invoked. Any suggestions where am I going wrong?
>>
>> [1] http://www.spinics.net/lists/kvm/msg153666.html
>> [2] http://www.spinics.net/lists/kvm/msg152734.html;
>>
>
> Hi Nitesh,
>
> I had a quick look of this approach, and have some high-level questions:
>
> 1) What's the usage of the feature, in addition to accelerating live
> migration?
I believe this solution will be useful in every use case where we do not
want to manually intervene in order to reclaim/allocate memory via
virtio-balloon and would like it to be done in an automated manner.
>
> 2) Are the free page hints continuously added to and removed from the
> per CPU arrays during the whole lifecycle of the guest whenever
> alloc/free is invoked?
Yes they are added continuously but whether they are required to be
removed from the list or not is decided only when the list is full.
>
> 3) The per-CPU arrays are sync-ed to a hypervisor page array under a
> lock. If all the CPUs happen to do the sync at the same time, the
> later ones may be possible to spin too long?
Yes, it may. Although this interface is the first version, and you are
looking at a batched and/or lockless interface. For instance instead of
doing one hypercall per page, I could pass the hypervisor a page full of
pfn/length tuples.
>
> Best,
> Wei
-- 
Regards
Nitesh


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2017-09-15 20:16 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-09-13 16:17 [Patch v2 0/4] KVM: Guest page hinting Nitesh Narayan Lal
2017-09-13 16:17 ` [Patch v2 1/4] KVM: Support for guest " Nitesh Narayan Lal
2017-09-14 19:26   ` kbuild test robot
2017-09-14 20:56   ` kbuild test robot
2017-09-13 16:17 ` [Patch v2 2/4] KVM: Guest page hinting functionality Nitesh Narayan Lal
2017-09-13 16:17 ` [Patch v2 3/4] KVM: Adding tracepoints for guest page hinting Nitesh Narayan Lal
2017-09-13 16:17 ` [Patch v2 4/4] KVM: Sending hyperlist to the host via deflate_vq Nitesh Narayan Lal
2017-09-14 20:26   ` kbuild test robot
2017-09-14 20:29   ` kbuild test robot
2017-09-15  2:07 ` [Patch v2 0/4] KVM: Guest page hinting Wei Wang
2017-09-15 20:16   ` Nitesh Narayan Lal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox