Message ID | 20171128200324.4432-6-nilal@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Nitesh, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on kvm/linux-next] [also build test WARNING on v4.15-rc1 next-20171128] [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/nilal-redhat-com/KVM-Guest-page-hinting/20171129-180331 base: https://git.kernel.org/pub/scm/virt/kvm/kvm.git linux-next config: i386-randconfig-x016-201748 (attached as .config) compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025 reproduce: # save the attached .config to linux build tree make ARCH=i386 All warnings (new ones prefixed by >>): drivers//virtio/virtio_balloon.c: In function 'tell_host_one_page': >> drivers//virtio/virtio_balloon.c:107:28: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] u64 gpaddr = virt_to_phys((void *)gvaddr); ^ drivers//virtio/virtio_balloon.c:110:39: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] virtqueue_add_chain(vq, id, 0, NULL, (void *)gpaddr, NULL); ^ drivers//virtio/virtio_balloon.c: In function 'virtballoon_page_hinting': >> drivers//virtio/virtio_balloon.c:115:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] u64 gvaddr = (u64)hypervisor_pagelist; ^ vim +107 drivers//virtio/virtio_balloon.c 101 102 #ifdef CONFIG_KVM_FREE_PAGE_HINTING 103 static void tell_host_one_page(struct virtio_balloon *vb, struct virtqueue *vq, 104 u64 gvaddr, int len) 105 { 106 unsigned int id = VIRTQUEUE_DESC_ID_INIT; > 107 u64 gpaddr = virt_to_phys((void *)gvaddr); 108 109 virtqueue_add_chain_desc(vq, gpaddr, len, &id, &id, 0); 110 virtqueue_add_chain(vq, id, 0, NULL, (void *)gpaddr, NULL); 111 } 112 113 void virtballoon_page_hinting(struct virtio_balloon *vb, int hyper_entries) 114 { > 115 u64 gvaddr = (u64)hypervisor_pagelist; 116 117 vb->num_pfns = hyper_entries; 118 tell_host_one_page(vb, vb->hinting_vq, gvaddr, hyper_entries); 119 } 120 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Nitesh, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on kvm/linux-next] [also build test WARNING on v4.15-rc1 next-20171128] [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/nilal-redhat-com/KVM-Guest-page-hinting/20171129-180331 base: https://git.kernel.org/pub/scm/virt/kvm/kvm.git linux-next config: i386-randconfig-x008-201748 (attached as .config) compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025 reproduce: # save the attached .config to linux build tree make ARCH=i386 All warnings (new ones prefixed by >>): drivers//virtio/virtio_balloon.c:59:6: error: #elif with no expression #elif ^ drivers//virtio/virtio_balloon.c: In function 'fill_balloon': drivers//virtio/virtio_balloon.c:220:19: error: 'struct virtio_balloon' has no member named 'inflate_vq' tell_host(vb, vb->inflate_vq); ^~ drivers//virtio/virtio_balloon.c: In function 'leak_balloon': drivers//virtio/virtio_balloon.c:270:19: error: 'struct virtio_balloon' has no member named 'deflate_vq' tell_host(vb, vb->deflate_vq); ^~ drivers//virtio/virtio_balloon.c: In function 'stats_handle_request': drivers//virtio/virtio_balloon.c:343:11: error: 'struct virtio_balloon' has no member named 'stats_vq'; did you mean 'stats'? vq = vb->stats_vq; ^~~~~~~~ stats drivers//virtio/virtio_balloon.c: In function 'init_vqs': drivers//virtio/virtio_balloon.c:454:12: error: 'hinting_ack' undeclared (first use in this function) hinting_ack }; ^~~~~~~~~~~ drivers//virtio/virtio_balloon.c:454:12: note: each undeclared identifier is reported only once for each function it appears in drivers//virtio/virtio_balloon.c:480:4: error: 'struct virtio_balloon' has no member named 'inflate_vq' vb->inflate_vq = vqs[0]; ^~ drivers//virtio/virtio_balloon.c:480:2: warning: statement with no effect [-Wunused-value] vb->inflate_vq = vqs[0]; ^~ drivers//virtio/virtio_balloon.c:481:4: error: 'struct virtio_balloon' has no member named 'deflate_vq' vb->deflate_vq = vqs[1]; ^~ drivers//virtio/virtio_balloon.c:481:2: warning: statement with no effect [-Wunused-value] vb->deflate_vq = vqs[1]; ^~ drivers//virtio/virtio_balloon.c:483:5: error: 'struct virtio_balloon' has no member named 'hinting_vq' vb->hinting_vq = vqs[3]; ^~ drivers//virtio/virtio_balloon.c:483:3: warning: statement with no effect [-Wunused-value] vb->hinting_vq = vqs[3]; ^~ drivers//virtio/virtio_balloon.c:487:7: error: 'struct virtio_balloon' has no member named 'stats_vq'; did you mean 'stats'? vb->stats_vq = vqs[2]; ^~~~~~~~ stats drivers//virtio/virtio_balloon.c:487:3: warning: statement with no effect [-Wunused-value] vb->stats_vq = vqs[2]; ^~ In file included from include/linux/string.h:6:0, from include/linux/scatterlist.h:5, from include/linux/virtio.h:7, from drivers//virtio/virtio_balloon.c:22: drivers//virtio/virtio_balloon.c:496:32: error: 'struct virtio_balloon' has no member named 'stats_vq'; did you mean 'stats'? if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) ^ include/linux/compiler.h:58:30: note: in definition of macro '__trace_if' if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ^~~~ >> drivers//virtio/virtio_balloon.c:496:3: note: in expansion of macro 'if' if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) ^~ drivers//virtio/virtio_balloon.c:496:28: error: passing argument 1 of 'virtqueue_add_outbuf' from incompatible pointer type [-Werror=incompatible-pointer-types] if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) ^ include/linux/compiler.h:58:30: note: in definition of macro '__trace_if' if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ^~~~ >> drivers//virtio/virtio_balloon.c:496:3: note: in expansion of macro 'if' if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) ^~ In file included from drivers//virtio/virtio_balloon.c:22:0: include/linux/virtio.h:38:5: note: expected 'struct virtqueue *' but argument is of type 'void (**)(struct virtqueue *)' int virtqueue_add_outbuf(struct virtqueue *vq, ^~~~~~~~~~~~~~~~~~~~ In file included from include/linux/string.h:6:0, from include/linux/scatterlist.h:5, from include/linux/virtio.h:7, from drivers//virtio/virtio_balloon.c:22: drivers//virtio/virtio_balloon.c:496:32: error: 'struct virtio_balloon' has no member named 'stats_vq'; did you mean 'stats'? if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) ^ include/linux/compiler.h:58:42: note: in definition of macro '__trace_if' if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ^~~~ >> drivers//virtio/virtio_balloon.c:496:3: note: in expansion of macro 'if' if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) ^~ drivers//virtio/virtio_balloon.c:496:28: error: passing argument 1 of 'virtqueue_add_outbuf' from incompatible pointer type [-Werror=incompatible-pointer-types] if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) ^ include/linux/compiler.h:58:42: note: in definition of macro '__trace_if' if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ ^~~~ >> drivers//virtio/virtio_balloon.c:496:3: note: in expansion of macro 'if' if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) ^~ In file included from drivers//virtio/virtio_balloon.c:22:0: include/linux/virtio.h:38:5: note: expected 'struct virtqueue *' but argument is of type 'void (**)(struct virtqueue *)' int virtqueue_add_outbuf(struct virtqueue *vq, ^~~~~~~~~~~~~~~~~~~~ In file included from include/linux/string.h:6:0, from include/linux/scatterlist.h:5, from include/linux/virtio.h:7, from drivers//virtio/virtio_balloon.c:22: drivers//virtio/virtio_balloon.c:496:32: error: 'struct virtio_balloon' has no member named 'stats_vq'; did you mean 'stats'? if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) ^ include/linux/compiler.h:69:16: note: in definition of macro '__trace_if' ______r = !!(cond); \ ^~~~ >> drivers//virtio/virtio_balloon.c:496:3: note: in expansion of macro 'if' if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) ^~ drivers//virtio/virtio_balloon.c:496:28: error: passing argument 1 of 'virtqueue_add_outbuf' from incompatible pointer type [-Werror=incompatible-pointer-types] if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) ^ include/linux/compiler.h:69:16: note: in definition of macro '__trace_if' ______r = !!(cond); \ ^~~~ >> drivers//virtio/virtio_balloon.c:496:3: note: in expansion of macro 'if' if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) ^~ In file included from drivers//virtio/virtio_balloon.c:22:0: include/linux/virtio.h:38:5: note: expected 'struct virtqueue *' but argument is of type 'void (**)(struct virtqueue *)' int virtqueue_add_outbuf(struct virtqueue *vq, ^~~~~~~~~~~~~~~~~~~~ drivers//virtio/virtio_balloon.c:499:22: error: 'struct virtio_balloon' has no member named 'stats_vq'; did you mean 'stats'? virtqueue_kick(vb->stats_vq); ^~~~~~~~ stats drivers//virtio/virtio_balloon.c:499:18: error: passing argument 1 of 'virtqueue_kick' from incompatible pointer type [-Werror=incompatible-pointer-types] virtqueue_kick(vb->stats_vq); ^~ In file included from drivers//virtio/virtio_balloon.c:22:0: include/linux/virtio.h:80:6: note: expected 'struct virtqueue *' but argument is of type 'void (**)(struct virtqueue *)' bool virtqueue_kick(struct virtqueue *vq); ^~~~~~~~~~~~~~ drivers//virtio/virtio_balloon.c: In function 'virtballoon_probe': drivers//virtio/virtio_balloon.c:646:32: error: 'virtballoon_page_hinting' undeclared (first use in this function); did you mean 'virtballoon_oom_notify'? request_hypercall = (void *)&virtballoon_page_hinting; ^~~~~~~~~~~~~~~~~~~~~~~~ virtballoon_oom_notify In file included from include/linux/string.h:6:0, from include/linux/scatterlist.h:5, from include/linux/virtio.h:7, from drivers//virtio/virtio_balloon.c:22: drivers//virtio/virtio_balloon.c: At top level: include/linux/compiler.h:64:4: warning: '______f' is static but declared in inline function 'strcpy' which is not static ______f = { \ ^ include/linux/compiler.h:56:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:422:2: note: in expansion of macro 'if' if (p_size == (size_t)-1 && q_size == (size_t)-1) ^~ include/linux/compiler.h:64:4: warning: '______f' is static but declared in inline function 'kmemdup' which is not static ______f = { \ ^ include/linux/compiler.h:56:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:412:2: note: in expansion of macro 'if' if (p_size < size) ^~ include/linux/compiler.h:64:4: warning: '______f' is static but declared in inline function 'kmemdup' which is not static ______f = { \ ^ include/linux/compiler.h:56:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:410:2: note: in expansion of macro 'if' if (__builtin_constant_p(size) && p_size < size) ^~ include/linux/compiler.h:64:4: warning: '______f' is static but declared in inline function 'memchr_inv' which is not static ______f = { \ ^ include/linux/compiler.h:56:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:401:2: note: in expansion of macro 'if' if (p_size < size) ^~ include/linux/compiler.h:64:4: warning: '______f' is static but declared in inline function 'memchr_inv' which is not static ______f = { \ ^ include/linux/compiler.h:56:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:399:2: note: in expansion of macro 'if' if (__builtin_constant_p(size) && p_size < size) ^~ include/linux/compiler.h:64:4: warning: '______f' is static but declared in inline function 'memchr' which is not static ______f = { \ ^ include/linux/compiler.h:56:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:390:2: note: in expansion of macro 'if' if (p_size < size) ^~ include/linux/compiler.h:64:4: warning: '______f' is static but declared in inline function 'memchr' which is not static ______f = { \ ^ include/linux/compiler.h:56:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:388:2: note: in expansion of macro 'if' if (__builtin_constant_p(size) && p_size < size) ^~ include/linux/compiler.h:64:4: warning: '______f' is static but declared in inline function 'memcmp' which is not static ______f = { \ ^ include/linux/compiler.h:56:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:380:2: note: in expansion of macro 'if' if (p_size < size || q_size < size) ^~ include/linux/compiler.h:64:4: warning: '______f' is static but declared in inline function 'memcmp' which is not static vim +/if +496 drivers//virtio/virtio_balloon.c 6b35e4076 Rusty Russell 2008-02-04 449 be91c33dd Amit Shah 2011-12-22 450 static int init_vqs(struct virtio_balloon *vb) 6b35e4076 Rusty Russell 2008-02-04 451 { 1006af9c7 Nitesh Narayan Lal 2017-11-28 452 struct virtqueue *vqs[4]; 1006af9c7 Nitesh Narayan Lal 2017-11-28 453 vq_callback_t *callbacks[] = { balloon_ack, balloon_ack, stats_request, 1006af9c7 Nitesh Narayan Lal 2017-11-28 454 hinting_ack }; 1006af9c7 Nitesh Narayan Lal 2017-11-28 455 static const char * const names[] = { "inflate", "deflate", "stats", 1006af9c7 Nitesh Narayan Lal 2017-11-28 456 "hinting" }; 9564e138b Adam Litke 2009-11-30 457 int err, nvqs; 1006af9c7 Nitesh Narayan Lal 2017-11-28 458 bool stats_vq_support, page_hinting_support; 6b35e4076 Rusty Russell 2008-02-04 459 be91c33dd Amit Shah 2011-12-22 460 /* be91c33dd Amit Shah 2011-12-22 461 * We expect two virtqueues: inflate and deflate, and 1006af9c7 Nitesh Narayan Lal 2017-11-28 462 * optionally stat and hinting. be91c33dd Amit Shah 2011-12-22 463 */ 1006af9c7 Nitesh Narayan Lal 2017-11-28 464 stats_vq_support = virtio_has_feature(vb->vdev, 1006af9c7 Nitesh Narayan Lal 2017-11-28 465 VIRTIO_BALLOON_F_STATS_VQ); 1006af9c7 Nitesh Narayan Lal 2017-11-28 466 page_hinting_support = virtio_has_feature(vb->vdev, 1006af9c7 Nitesh Narayan Lal 2017-11-28 467 VIRTIO_GUEST_PAGE_HINTING_VQ 1006af9c7 Nitesh Narayan Lal 2017-11-28 468 ); 1006af9c7 Nitesh Narayan Lal 2017-11-28 469 if (stats_vq_support && page_hinting_support) 1006af9c7 Nitesh Narayan Lal 2017-11-28 470 nvqs = 4; 1006af9c7 Nitesh Narayan Lal 2017-11-28 471 else if (stats_vq_support || page_hinting_support) 1006af9c7 Nitesh Narayan Lal 2017-11-28 472 nvqs = 3; 1006af9c7 Nitesh Narayan Lal 2017-11-28 473 else 1006af9c7 Nitesh Narayan Lal 2017-11-28 474 nvqs = 2; 1006af9c7 Nitesh Narayan Lal 2017-11-28 475 9b2bbdb22 Michael S. Tsirkin 2017-03-06 476 err = virtio_find_vqs(vb->vdev, nvqs, vqs, callbacks, names, NULL); d2a7ddda9 Michael S. Tsirkin 2009-06-12 477 if (err) be91c33dd Amit Shah 2011-12-22 478 return err; 6b35e4076 Rusty Russell 2008-02-04 479 d2a7ddda9 Michael S. Tsirkin 2009-06-12 480 vb->inflate_vq = vqs[0]; d2a7ddda9 Michael S. Tsirkin 2009-06-12 481 vb->deflate_vq = vqs[1]; 1006af9c7 Nitesh Narayan Lal 2017-11-28 482 if (page_hinting_support) 1006af9c7 Nitesh Narayan Lal 2017-11-28 483 vb->hinting_vq = vqs[3]; 9564e138b Adam Litke 2009-11-30 484 if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { 9564e138b Adam Litke 2009-11-30 485 struct scatterlist sg; 9646b26e8 Ladi Prosek 2017-03-28 486 unsigned int num_stats; 9564e138b Adam Litke 2009-11-30 487 vb->stats_vq = vqs[2]; 9564e138b Adam Litke 2009-11-30 488 9564e138b Adam Litke 2009-11-30 489 /* 9564e138b Adam Litke 2009-11-30 490 * Prime this virtqueue with one buffer so the hypervisor can 4951cc908 Rusty Russell 2014-03-13 491 * use it to signal us later (it can't be broken yet!). 9564e138b Adam Litke 2009-11-30 492 */ 9646b26e8 Ladi Prosek 2017-03-28 493 num_stats = update_balloon_stats(vb); fc8653228 Ladi Prosek 2017-03-23 494 9646b26e8 Ladi Prosek 2017-03-28 495 sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats); 92549abc6 Rusty Russell 2013-03-20 @496 if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) f96fde41f Rusty Russell 2012-01-12 497 < 0) 9564e138b Adam Litke 2009-11-30 498 BUG(); 946cfe0e0 Michael S. Tsirkin 2010-04-12 499 virtqueue_kick(vb->stats_vq); 9564e138b Adam Litke 2009-11-30 500 } be91c33dd Amit Shah 2011-12-22 501 return 0; be91c33dd Amit Shah 2011-12-22 502 } be91c33dd Amit Shah 2011-12-22 503 :::::: The code at line 496 was first introduced by commit :::::: 92549abc6a6573294fc1bb9330db8b52dedfea5f virtio_balloon: use simplified virtqueue accessors. :::::: TO: Rusty Russell <rusty@rustcorp.com.au> :::::: CC: Rusty Russell <rusty@rustcorp.com.au> --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 7960746..f9e25b7 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,8 +54,11 @@ static struct vfsmount *balloon_mnt; struct virtio_balloon { struct virtio_device *vdev; - struct virtqueue *inflate_vq, *deflate_vq, *stats_vq; - +#ifdef CONFIG_KVM_FREE_PAGE_HINTING + struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *hinting_vq; +#elif + struct virtqueue *inflate_vq, *deflate_vq, *stats_vq_vq; +#endif /* The balloon servicing is delegated to a freezable workqueue. */ struct work_struct update_balloon_stats_work; struct work_struct update_balloon_size_work; @@ -95,6 +99,33 @@ 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); +} + +static void hinting_ack(struct virtqueue *vq) +{ + struct virtio_balloon *vb = vq->vdev->priv; + + wake_up(&vb->acked); +} +#endif + static u32 page_to_balloon_pfn(struct page *page) { unsigned long pfn = page_to_pfn(page); @@ -418,22 +449,38 @@ 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, stats_request, + hinting_ack }; + static const char * const names[] = { "inflate", "deflate", "stats", + "hinting" }; int err, nvqs; + bool stats_vq_support, page_hinting_support; /* * We expect two virtqueues: inflate and deflate, and - * optionally stat. + * optionally stat and hinting. */ - nvqs = virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ) ? 3 : 2; + stats_vq_support = virtio_has_feature(vb->vdev, + VIRTIO_BALLOON_F_STATS_VQ); + page_hinting_support = virtio_has_feature(vb->vdev, + VIRTIO_GUEST_PAGE_HINTING_VQ + ); + if (stats_vq_support && page_hinting_support) + nvqs = 4; + else if (stats_vq_support || page_hinting_support) + nvqs = 3; + else + nvqs = 2; + 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]; + if (page_hinting_support) + vb->hinting_vq = vqs[3]; if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { struct scatterlist sg; unsigned int num_stats; @@ -595,6 +642,11 @@ static int virtballoon_probe(struct virtio_device *vdev) virtio_device_ready(vdev); + if (virtio_has_feature(vb->vdev, VIRTIO_GUEST_PAGE_HINTING_VQ)) { + request_hypercall = (void *)&virtballoon_page_hinting; + balloon_ptr = vb; + } + if (towards_target(vb)) virtballoon_changed(vdev); return 0; @@ -683,6 +735,7 @@ static unsigned int features[] = { VIRTIO_BALLOON_F_MUST_TELL_HOST, VIRTIO_BALLOON_F_STATS_VQ, VIRTIO_BALLOON_F_DEFLATE_ON_OOM, + VIRTIO_GUEST_PAGE_HINTING_VQ, }; static struct virtio_driver virtio_balloon_driver = { 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/uapi/linux/virtio_balloon.h b/include/uapi/linux/virtio_balloon.h index 343d7dd..45bdcc8 100644 --- a/include/uapi/linux/virtio_balloon.h +++ b/include/uapi/linux/virtio_balloon.h @@ -34,6 +34,7 @@ #define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */ #define VIRTIO_BALLOON_F_STATS_VQ 1 /* Memory Stats virtqueue */ #define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 2 /* Deflate balloon on OOM */ +#define VIRTIO_GUEST_PAGE_HINTING_VQ 3 /* Page hinting virtqueue */ /* Size of a PFN in the balloon interface. */ #define VIRTIO_BALLOON_PFN_SHIFT 12 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));