lkml.org 
[lkml]   [2019]   [Mar]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[RFC][Patch v9 5/6] KVM: Enabling guest free page hinting via static key
Date
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@redhat.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
\
 
 \ /
  Last update: 2019-03-06 16:51    [W:0.235 / U:0.480 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site