From: nilal@redhat.com
To: kvm@vger.kernel.org, pbonzini@redhat.com, pagupta@redhat.com,
wei.w.wang@intel.com, yang.zhang.wz@gmail.com, riel@redhat.com,
david@redhat.com, mst@redhat.com, dodgen@google.com,
konrad.wilk@oracle.com
Subject: [Patch v4 5/6] KVM: Sending hyperlist to the host via hinting_vq
Date: Fri, 3 Nov 2017 16:30:12 -0400 [thread overview]
Message-ID: <20171103203013.9521-6-nilal@redhat.com> (raw)
In-Reply-To: <20171103203013.9521-1-nilal@redhat.com>
From: Nitesh Narayan Lal <nilal@redhat.com>
This patch creates a new vq (hinting_vq) to be used for page hinting
and adds support in the existing virtio balloon infrastructure so
that the hyper list carrying pages which are supposed to be freed
could be sent to the host (QEMU) for processing by using hinting_vq.
Signed-off-by: Nitesh Narayan Lal <nilal@redhat.com>
---
drivers/virtio/virtio_balloon.c | 45 ++++++++++++++++++++++++++++++++++++-----
include/linux/page_hinting.h | 16 +++++++++++++++
virt/kvm/page_hinting.c | 36 +++++++++++++--------------------
3 files changed, 70 insertions(+), 27 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..e678196 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
@@ -53,7 +54,7 @@ static struct vfsmount *balloon_mnt;
struct virtio_balloon {
struct virtio_device *vdev;
- struct virtqueue *inflate_vq, *deflate_vq, *stats_vq;
+ struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *hinting_vq;
/* The balloon servicing is delegated to a freezable workqueue. */
struct work_struct update_balloon_stats_work;
@@ -95,6 +96,26 @@ 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,
+ u64 gvaddr, int len)
+{
+ unsigned int id = VIRTQUEUE_DESC_ID_INIT;
+ u64 gpaddr = virt_to_phys((void *)gvaddr);
+
+ virtqueue_add_chain_desc(vq, gpaddr, len, &id, &id, 0);
+ virtqueue_add_chain(vq, id, 0, NULL, (void *)gpaddr, NULL);
+}
+
+void virtballoon_page_hinting(struct virtio_balloon *vb, int hyper_entries)
+{
+ u64 gvaddr = (u64)hypervisor_pagelist;
+
+ vb->num_pfns = hyper_entries;
+ tell_host_one_page(vb, vb->hinting_vq, gvaddr, hyper_entries);
+}
+#endif
+
static u32 page_to_balloon_pfn(struct page *page)
{
unsigned long pfn = page_to_pfn(page);
@@ -111,6 +132,12 @@ static void balloon_ack(struct virtqueue *vq)
wake_up(&vb->acked);
}
+static void hinting_ack(struct virtqueue *vq)
+{
+ struct virtio_balloon *vb = vq->vdev->priv;
+
+ wake_up(&vb->acked);
+}
static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
{
struct scatterlist sg;
@@ -404,22 +431,25 @@ static void update_balloon_size_func(struct work_struct *work)
static int init_vqs(struct virtio_balloon *vb)
{
- struct virtqueue *vqs[3];
- vq_callback_t *callbacks[] = { balloon_ack, balloon_ack, stats_request };
- static const char * const names[] = { "inflate", "deflate", "stats" };
+ struct virtqueue *vqs[4];
+ vq_callback_t *callbacks[] = { balloon_ack, balloon_ack, hinting_ack,
+ stats_request };
+ static const char * const names[] = { "inflate", "deflate", "hinting",
+ "stats" };
int err, nvqs;
/*
* We expect two virtqueues: inflate and deflate, and
* optionally stat.
*/
- nvqs = virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ) ? 3 : 2;
+ nvqs = virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ) ? 4 : 3;
err = virtio_find_vqs(vb->vdev, nvqs, vqs, callbacks, names, NULL);
if (err)
return err;
vb->inflate_vq = vqs[0];
vb->deflate_vq = vqs[1];
+ vb->hinting_vq = vqs[3];
if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) {
struct scatterlist sg;
unsigned int num_stats;
@@ -581,6 +611,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/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/virt/kvm/page_hinting.c b/virt/kvm/page_hinting.c
index 54fe6bc..22c892b 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/kmem.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,15 @@ 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];
+EXPORT_SYMBOL(hypervisor_pagelist);
+void (*request_hypercall)(void *, int);
+EXPORT_SYMBOL(request_hypercall);
+void *balloon_ptr;
+EXPORT_SYMBOL(balloon_ptr);
static void empty_hyperlist(void)
{
@@ -49,13 +42,11 @@ static void empty_hyperlist(void)
}
}
-void make_hypercall(void)
+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
next prev parent reply other threads:[~2017-11-03 20:31 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-03 20:30 [Patch v4 0/6] KVM: Guest page hinting nilal
2017-11-03 20:30 ` [Patch v4 1/6] KVM: Support for guest " nilal
2017-11-13 17:59 ` Michael S. Tsirkin
2017-11-15 19:38 ` Nitesh Narayan Lal
2017-11-15 20:06 ` Michael S. Tsirkin
2017-11-03 20:30 ` [Patch v4 2/6] KVM: Guest page hinting functionality nilal
2017-11-13 18:03 ` Michael S. Tsirkin
2017-11-03 20:30 ` [Patch v4 3/6] KVM: Adding tracepoints for guest page hinting nilal
2017-11-03 20:30 ` [Patch v4 4/6] virtio: Exposes added descriptor to the other side synchronously nilal
2017-11-03 20:30 ` nilal [this message]
2017-11-03 20:30 ` [Patch v4 6/6] KVM: Enabling guest page hinting via static key nilal
2017-11-03 20:37 ` [QEMU PATCH] kvm: Support for guest page hinting nilal
2017-11-03 20:37 ` nilal
2017-11-06 11:21 ` Pankaj Gupta
2017-11-06 14:21 ` Nitesh Narayan Lal
2017-11-12 21:23 ` [Patch v4 0/6] KVM: Guest " Rik van Riel
2017-11-13 15:14 ` Nitesh Narayan Lal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171103203013.9521-6-nilal@redhat.com \
--to=nilal@redhat.com \
--cc=david@redhat.com \
--cc=dodgen@google.com \
--cc=konrad.wilk@oracle.com \
--cc=kvm@vger.kernel.org \
--cc=mst@redhat.com \
--cc=pagupta@redhat.com \
--cc=pbonzini@redhat.com \
--cc=riel@redhat.com \
--cc=wei.w.wang@intel.com \
--cc=yang.zhang.wz@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox