lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed,  6 Mar 2019 10:50:47 -0500
From:   Nitesh Narayan Lal <nitesh@...hat.com>
To:     kvm@...r.kernel.org, linux-kernel@...r.kernel.org,
        linux-mm@...ck.org, pbonzini@...hat.com, lcapitulino@...hat.com,
        pagupta@...hat.com, wei.w.wang@...el.com, yang.zhang.wz@...il.com,
        riel@...riel.com, david@...hat.com, mst@...hat.com,
        dodgen@...gle.com, konrad.wilk@...cle.com, dhildenb@...hat.com,
        aarcange@...hat.com, alexander.duyck@...il.com
Subject: [RFC][Patch v9 5/6] KVM: Enabling guest free page hinting via static key

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

Signed-off-by: Nitesh Narayan Lal <nitesh@...hat.com>
---
 Documentation/sysctl/vm.txt     | 12 ++++++++++++
 drivers/virtio/virtio_balloon.c |  4 ++++
 include/linux/page_hinting.h    |  5 +++++
 kernel/sysctl.c                 | 12 ++++++++++++
 virt/kvm/page_hinting.c         | 26 ++++++++++++++++++++++++++
 5 files changed, 59 insertions(+)

diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 187ce4f599a2..eae9180ea0aa 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -31,6 +31,7 @@ Currently, these files are in /proc/sys/vm:
 - dirty_writeback_centisecs
 - drop_caches
 - extfrag_threshold
+- guest_free_page_hinting
 - hugetlb_shm_group
 - laptop_mode
 - legacy_va_layout
@@ -255,6 +256,17 @@ fragmentation index is <= extfrag_threshold. The default value is 500.
 
 ==============================================================
 
+guest_free_page_hinting
+
+This parameter enables the kernel to report KVM guest free pages to the host
+via virtio balloon driver. QEMU receives these free page hints and frees them
+by performing MADVISE_DONTNEED on it.
+
+It depends on VIRTIO_BALLOON for its functionality. In case VIRTIO_BALLOON
+driver is missing, this feature is disabled by default.
+
+==============================================================
+
 highmem_is_dirtyable
 
 Available only for systems with CONFIG_HIGHMEM enabled (32b systems).
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index e82c72cd916b..171fd72ef2ae 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -164,12 +164,16 @@ static void hinting_ack(struct virtqueue *vq)
 
 static void enable_hinting(struct virtio_balloon *vb)
 {
+	guest_free_page_hinting_flag = 1;
+	static_branch_enable(&guest_free_page_hinting_key);
 	request_hypercall = (void *)&virtballoon_page_hinting;
 	balloon_ptr = vb;
 }
 
 static void disable_hinting(void)
 {
+	guest_free_page_hinting_flag = 0;
+	static_branch_enable(&guest_free_page_hinting_key);
 	balloon_ptr = NULL;
 }
 #endif
diff --git a/include/linux/page_hinting.h b/include/linux/page_hinting.h
index a32af8851081..60e0a21bfbe6 100644
--- a/include/linux/page_hinting.h
+++ b/include/linux/page_hinting.h
@@ -12,6 +12,8 @@
 #define FREE_PAGE_HINTING_MIN_ORDER	(MAX_ORDER - 1)
 
 extern void *balloon_ptr;
+extern int guest_free_page_hinting_flag;
+extern struct static_key_false guest_free_page_hinting_key;
 
 void guest_free_page_enqueue(struct page *page, int order);
 void guest_free_page_try_hinting(void);
@@ -22,3 +24,6 @@ extern void __free_one_page(struct page *page, unsigned long pfn,
 void release_buddy_pages(void *obj_to_free, int entries);
 extern int (*request_hypercall)(void *balloon_ptr,
 				void *hinting_req, int entries);
+int guest_free_page_hinting_sysctl(struct ctl_table *table, int write,
+				   void __user *buffer, size_t *lenp,
+				   loff_t *ppos);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index ba4d9e85feb8..7b2970e9e937 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -96,6 +96,9 @@
 #ifdef CONFIG_LOCKUP_DETECTOR
 #include <linux/nmi.h>
 #endif
+#ifdef CONFIG_KVM_FREE_PAGE_HINTING
+#include <linux/page_hinting.h>
+#endif
 
 #if defined(CONFIG_SYSCTL)
 
@@ -1690,6 +1693,15 @@ static struct ctl_table vm_table[] = {
 		.extra1		= (void *)&mmap_rnd_compat_bits_min,
 		.extra2		= (void *)&mmap_rnd_compat_bits_max,
 	},
+#endif
+#ifdef CONFIG_KVM_FREE_PAGE_HINTING
+	{
+		.procname       = "guest-free-page-hinting",
+		.data           = &guest_free_page_hinting_flag,
+		.maxlen         = sizeof(guest_free_page_hinting_flag),
+		.mode           = 0644,
+		.proc_handler   = guest_free_page_hinting_sysctl,
+	},
 #endif
 	{ }
 };
diff --git a/virt/kvm/page_hinting.c b/virt/kvm/page_hinting.c
index eb0c0ddfe990..5980682e0b86 100644
--- a/virt/kvm/page_hinting.c
+++ b/virt/kvm/page_hinting.c
@@ -36,6 +36,28 @@ EXPORT_SYMBOL(request_hypercall);
 void *balloon_ptr;
 EXPORT_SYMBOL(balloon_ptr);
 
+struct static_key_false guest_free_page_hinting_key  = STATIC_KEY_FALSE_INIT;
+EXPORT_SYMBOL(guest_free_page_hinting_key);
+static DEFINE_MUTEX(hinting_mutex);
+int guest_free_page_hinting_flag;
+EXPORT_SYMBOL(guest_free_page_hinting_flag);
+
+int guest_free_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_free_page_hinting_flag)
+		static_key_enable(&guest_free_page_hinting_key.key);
+	else
+		static_key_disable(&guest_free_page_hinting_key.key);
+	mutex_unlock(&hinting_mutex);
+	return ret;
+}
+
 void release_buddy_pages(void *hinting_req, int entries)
 {
 	int i = 0;
@@ -223,6 +245,8 @@ void guest_free_page_enqueue(struct page *page, int order)
 	struct guest_free_pages *hinting_obj;
 	int l_idx;
 
+	if (!static_branch_unlikely(&guest_free_page_hinting_key))
+		return;
 	/*
 	 * use of global variables may trigger a race condition between irq and
 	 * process context causing unwanted overwrites. This will be replaced
@@ -258,6 +282,8 @@ void guest_free_page_try_hinting(void)
 {
 	struct guest_free_pages *hinting_obj;
 
+	if (!static_branch_unlikely(&guest_free_page_hinting_key))
+		return;
 	hinting_obj = this_cpu_ptr(&free_pages_obj);
 	if (hinting_obj->free_pages_idx >= HINTING_THRESHOLD)
 		guest_free_page_hinting();
-- 
2.17.2

Powered by blists - more mailing lists