diff mbox

[v6,6/7] KVM: Enabling guest page hinting via static key

Message ID 20171201173136.849-7-nilal@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Nitesh Lal Dec. 1, 2017, 5:31 p.m. UTC
From: Nitesh Narayan Lal <nilal@redhat.com>

This patch enables the guest page hinting support
to enable or disable based on the STATIC key which
could be set via sysctl.

Signed-off-by: Nitesh Narayan Lal <nilal@redhat.com>
---
 drivers/virtio/virtio_balloon.c | 16 +++++++++++-----
 include/linux/gfp.h             | 16 ++++++++++++++--
 include/linux/page_hinting.h    |  7 +++++++
 kernel/sysctl.c                 |  9 +++++++++
 virt/kvm/page_hinting.c         | 29 +++++++++++++++++++++++++----
 5 files changed, 66 insertions(+), 11 deletions(-)
diff mbox

Patch

diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 7aef032..e6457de 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -32,7 +32,6 @@ 
 #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
@@ -124,6 +123,14 @@  static void hinting_ack(struct virtqueue *vq)
 
 	wake_up(&vb->acked);
 }
+
+static void enable_hinting(struct virtio_balloon *vb)
+{
+	guest_page_hinting_flag = 1;
+	static_branch_enable(&guest_page_hinting_key);
+	request_hypercall = (void *)&virtballoon_page_hinting;
+	balloon_ptr = vb;
+}
 #endif
 
 static u32 page_to_balloon_pfn(struct page *page)
@@ -524,6 +531,7 @@  static int init_vqs(struct virtio_balloon *vb)
 	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) {
 		struct scatterlist sg;
 		unsigned int num_stats;
+
 		vb->stats_vq = vqs[2];
 
 		/*
@@ -685,10 +693,8 @@  static int virtballoon_probe(struct virtio_device *vdev)
 	virtio_device_ready(vdev);
 
 #ifdef CONFIG_KVM_FREE_PAGE_HINTING
-	if (virtio_has_feature(vb->vdev, VIRTIO_GUEST_PAGE_HINTING_VQ)) {
-		request_hypercall = (void *)&virtballoon_page_hinting;
-		balloon_ptr = vb;
-	}
+	if (virtio_has_feature(vb->vdev, VIRTIO_GUEST_PAGE_HINTING_VQ))
+		enable_hinting(vb);
 #endif
 
 	if (towards_target(vb))
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index e02369b..2212e08 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -7,6 +7,7 @@ 
 #include <linux/stddef.h>
 #include <linux/linkage.h>
 #include <linux/topology.h>
+#include <linux/page_hinting.h>
 
 struct vm_area_struct;
 
@@ -442,8 +443,19 @@  static inline struct zonelist *node_zonelist(int nid, gfp_t 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);
+static inline void arch_alloc_page(struct page *page, int order)
+{
+	if (!static_branch_unlikely(&guest_page_hinting_key))
+		return;
+	guest_alloc_page(page, order);
+}
+
+static inline void arch_free_page(struct page *page, int order)
+{
+	if (!static_branch_unlikely(&guest_page_hinting_key))
+		return;
+	guest_free_page(page, order);
+}
 #endif
 
 #ifndef HAVE_ARCH_FREE_PAGE
diff --git a/include/linux/page_hinting.h b/include/linux/page_hinting.h
index 0bfb646..dd30644 100644
--- a/include/linux/page_hinting.h
+++ b/include/linux/page_hinting.h
@@ -14,3 +14,10 @@  struct hypervisor_pages {
 extern struct hypervisor_pages hypervisor_pagelist[MAX_FGPT_ENTRIES];
 extern void (*request_hypercall)(void *, int);
 extern void *balloon_ptr;
+
+extern struct static_key_false guest_page_hinting_key;
+int guest_page_hinting_sysctl(struct ctl_table *table, int write,
+			      void __user *buffer, size_t *lenp, loff_t *ppos);
+extern int guest_page_hinting_flag;
+void guest_alloc_page(struct page *page, int order);
+void guest_free_page(struct page *page, int order);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 557d467..2717ceb 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1655,6 +1655,15 @@  static struct ctl_table vm_table[] = {
 		.extra2		= (void *)&mmap_rnd_compat_bits_max,
 	},
 #endif
+#ifdef CONFIG_KVM_FREE_PAGE_HINTING
+	{
+		.procname	= "guest-page-hinting",
+		.data		= &guest_page_hinting_flag,
+		.maxlen		= sizeof(guest_page_hinting_flag),
+		.mode		= 0644,
+		.proc_handler   = guest_page_hinting_sysctl,
+	},
+#endif
 	{ }
 };
 
diff --git a/virt/kvm/page_hinting.c b/virt/kvm/page_hinting.c
index 22c892b..f66ad63 100644
--- a/virt/kvm/page_hinting.c
+++ b/virt/kvm/page_hinting.c
@@ -5,7 +5,6 @@ 
 #include <linux/sort.h>
 #include <linux/kernel.h>
 #include <trace/events/kmem.h>
-#include <linux/page_hinting.h>
 
 #define HYPERLIST_THRESHOLD	500
 /*
@@ -30,6 +29,29 @@  void (*request_hypercall)(void *, int);
 EXPORT_SYMBOL(request_hypercall);
 void *balloon_ptr;
 EXPORT_SYMBOL(balloon_ptr);
+struct static_key_false guest_page_hinting_key  = STATIC_KEY_FALSE_INIT;
+EXPORT_SYMBOL(guest_page_hinting_key);
+static DEFINE_MUTEX(hinting_mutex);
+int guest_page_hinting_flag;
+EXPORT_SYMBOL(guest_page_hinting_flag);
+
+int guest_page_hinting_sysctl(struct ctl_table *table, int write,
+			      void __user *buffer, size_t *lenp,
+			      loff_t *ppos)
+{
+	int ret;
+
+	mutex_lock(&hinting_mutex);
+
+	ret = proc_dointvec(table, write, buffer, lenp, ppos);
+
+	if (guest_page_hinting_flag)
+		static_key_enable(&guest_page_hinting_key.key);
+	else
+		static_key_disable(&guest_page_hinting_key.key);
+	mutex_unlock(&hinting_mutex);
+	return ret;
+}
 
 static void empty_hyperlist(void)
 {
@@ -254,7 +276,7 @@  void arch_free_page_slowpath(void)
 	write_sequnlock(&guest_page_lock);
 }
 
-void arch_alloc_page(struct page *page, int order)
+void guest_alloc_page(struct page *page, int order)
 {
 	unsigned int seq;
 
@@ -270,12 +292,11 @@  void arch_alloc_page(struct page *page, int order)
 	trace_guest_alloc_page(page, order);
 }
 
-void arch_free_page(struct page *page, int order)
+void guest_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