Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1201102 > unrolled thread

Re: [PATCH v3 3/9] VMware balloon: add batching to the vmw_balloon.

Started byGreg KH <gregkh@linuxfoundation.org>
First post2015-08-05 22:20 +0200
Last post2015-08-06 00:50 +0200
Articles 4 on this page of 24 — 4 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [PATCH v3 3/9] VMware balloon: add batching to the vmw_balloon. Greg KH <gregkh@linuxfoundation.org> - 2015-08-05 22:20 +0200
    [PATCH v4 3/9] VMware balloon: add batching to the vmw_balloon. "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-06 00:40 +0200
      Re: [PATCH v4 3/9] VMware balloon: add batching to the vmw_balloon. Philip Moltmann <moltmann@vmware.com> - 2015-08-06 00:50 +0200
        Re: [PATCH v4 3/9] VMware balloon: add batching to the vmw_balloon. "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org> - 2015-08-06 01:30 +0200
          [PATCH v4 0/9] Fourth revision of the performance improvement patch to the VMware balloon driver "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-06 22:40 +0200
            [PATCH v4 5/9] VMware balloon: Show capabilities of balloon and resulting capabilities in the debug-fs node. "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-06 22:40 +0200
            [PATCH v4 6/9] VMware balloon: Do not limit the amount of frees and allocations in non-sleep mode. "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-06 22:40 +0200
            [PATCH v4 8/9] VMware balloon: Treat init like reset "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-06 22:40 +0200
            [PATCH v4 4/9] VMware balloon: Update balloon target on each lock/unlock. "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-06 22:40 +0200
            [PATCH v4 1/9] VMware balloon: partially inline vmballoon_reserve_page. "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-06 22:40 +0200
              Re: [PATCH v4 1/9] VMware balloon: partially inline  vmballoon_reserve_page. Greg KH <gregkh@linuxfoundation.org> - 2015-08-06 23:10 +0200
                [PATCH v5 0/7]  Fifth revision of the performance improvement patch to the VMware balloon driver "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-07 00:30 +0200
                  [PATCH v5 4/7] VMware balloon: Do not limit the amount of frees and allocations in non-sleep mode. "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-07 00:30 +0200
                  [PATCH v5 2/7] VMware balloon: Update balloon target on each lock/unlock. "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-07 00:30 +0200
                  [PATCH v5 6/7] VMware balloon: Treat init like reset "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-07 00:30 +0200
                  [PATCH v5 5/7] VMware balloon: Support 2m page ballooning. "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-07 00:30 +0200
                  [PATCH v5 1/7] VMware balloon: add batching to the vmw_balloon. "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-07 00:30 +0200
                  [PATCH v5 7/7] VMware balloon: Enable notification via VMCI "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-07 00:30 +0200
                  Re: [PATCH v5 0/7]  Fifth revision of the performance improvement  patch to the VMware balloon driver Philip Moltmann <moltmann@vmware.com> - 2015-08-15 01:30 +0200
            [PATCH v4 3/9] VMware balloon: add batching to the vmw_balloon. "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-06 22:40 +0200
            [PATCH v4 2/9] VMware balloon: Add support for balloon capabilities. "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-06 22:40 +0200
            [PATCH v4 7/9] VMware balloon: Support 2m page ballooning. "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-06 22:40 +0200
            [PATCH v4 9/9] VMware balloon: Enable notification via VMCI "Philip P. Moltmann" <moltmann@vmware.com> - 2015-08-06 22:40 +0200
      Re: [PATCH v4 3/9] VMware balloon: add batching to the vmw_balloon. Greg KH <gregkh@linuxfoundation.org> - 2015-08-06 00:50 +0200

Page 2 of 2 — ← Prev page 1 [2]


#1202016 — [PATCH v4 2/9] VMware balloon: Add support for balloon capabilities.

From"Philip P. Moltmann" <moltmann@vmware.com>
Date2015-08-06 22:40 +0200
Subject[PATCH v4 2/9] VMware balloon: Add support for balloon capabilities.
Message-ID<pUA7g-34H-19@gated-at.bofh.it>
In reply to#1202001
From: Xavier Deguillard <xdeguillard@vmware.com>

In order to extend the balloon protocol, the hypervisor and the guest
driver need to agree on a set of supported functionality to use.

Signed-off-by: Xavier Deguillard <xdeguillard@vmware.com>
Acked-by: Dmitry Torokhov <dtor@vmware.com>
Signed-off-by: Philip P. Moltmann <moltmann@vmware.com>
Acked-by: Andy King <acking@vmware.com>
---
 drivers/misc/vmw_balloon.c | 74 +++++++++++++++++++++++++++-------------------
 1 file changed, 44 insertions(+), 30 deletions(-)

diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index 2799c46..ffb5634 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -46,7 +46,7 @@
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.2.2.0-k");
+MODULE_VERSION("1.3.0.0-k");
 MODULE_ALIAS("dmi:*:svnVMware*:*");
 MODULE_ALIAS("vmware_vmmemctl");
 MODULE_LICENSE("GPL");
@@ -110,9 +110,18 @@ MODULE_LICENSE("GPL");
  */
 #define VMW_BALLOON_HV_PORT		0x5670
 #define VMW_BALLOON_HV_MAGIC		0x456c6d6f
-#define VMW_BALLOON_PROTOCOL_VERSION	2
 #define VMW_BALLOON_GUEST_ID		1	/* Linux */
 
+enum vmwballoon_capabilities {
+	/*
+	 * Bit 0 is reserved and not associated to any capability.
+	 */
+	VMW_BALLOON_BASIC_CMDS		= (1 << 1),
+	VMW_BALLOON_BATCHED_CMDS	= (1 << 2)
+};
+
+#define VMW_BALLOON_CAPABILITIES	(VMW_BALLOON_BASIC_CMDS)
+
 #define VMW_BALLOON_CMD_START		0
 #define VMW_BALLOON_CMD_GET_TARGET	1
 #define VMW_BALLOON_CMD_LOCK		2
@@ -120,32 +129,36 @@ MODULE_LICENSE("GPL");
 #define VMW_BALLOON_CMD_GUEST_ID	4
 
 /* error codes */
-#define VMW_BALLOON_SUCCESS		0
-#define VMW_BALLOON_FAILURE		-1
-#define VMW_BALLOON_ERROR_CMD_INVALID	1
-#define VMW_BALLOON_ERROR_PPN_INVALID	2
-#define VMW_BALLOON_ERROR_PPN_LOCKED	3
-#define VMW_BALLOON_ERROR_PPN_UNLOCKED	4
-#define VMW_BALLOON_ERROR_PPN_PINNED	5
-#define VMW_BALLOON_ERROR_PPN_NOTNEEDED	6
-#define VMW_BALLOON_ERROR_RESET		7
-#define VMW_BALLOON_ERROR_BUSY		8
-
-#define VMWARE_BALLOON_CMD(cmd, data, result)		\
-({							\
-	unsigned long __stat, __dummy1, __dummy2;	\
-	__asm__ __volatile__ ("inl %%dx" :		\
-		"=a"(__stat),				\
-		"=c"(__dummy1),				\
-		"=d"(__dummy2),				\
-		"=b"(result) :				\
-		"0"(VMW_BALLOON_HV_MAGIC),		\
-		"1"(VMW_BALLOON_CMD_##cmd),		\
-		"2"(VMW_BALLOON_HV_PORT),		\
-		"3"(data) :				\
-		"memory");				\
-	result &= -1UL;					\
-	__stat & -1UL;					\
+#define VMW_BALLOON_SUCCESS		        0
+#define VMW_BALLOON_FAILURE		        -1
+#define VMW_BALLOON_ERROR_CMD_INVALID	        1
+#define VMW_BALLOON_ERROR_PPN_INVALID	        2
+#define VMW_BALLOON_ERROR_PPN_LOCKED	        3
+#define VMW_BALLOON_ERROR_PPN_UNLOCKED	        4
+#define VMW_BALLOON_ERROR_PPN_PINNED	        5
+#define VMW_BALLOON_ERROR_PPN_NOTNEEDED	        6
+#define VMW_BALLOON_ERROR_RESET		        7
+#define VMW_BALLOON_ERROR_BUSY		        8
+
+#define VMW_BALLOON_SUCCESS_WITH_CAPABILITIES	(0x03000000)
+
+#define VMWARE_BALLOON_CMD(cmd, data, result)			\
+({								\
+	unsigned long __status, __dummy1, __dummy2;		\
+	__asm__ __volatile__ ("inl %%dx" :			\
+		"=a"(__status),					\
+		"=c"(__dummy1),					\
+		"=d"(__dummy2),					\
+		"=b"(result) :					\
+		"0"(VMW_BALLOON_HV_MAGIC),			\
+		"1"(VMW_BALLOON_CMD_##cmd),			\
+		"2"(VMW_BALLOON_HV_PORT),			\
+		"3"(data) :					\
+		"memory");					\
+	if (VMW_BALLOON_CMD_##cmd == VMW_BALLOON_CMD_START)	\
+		result = __dummy1;				\
+	result &= -1UL;						\
+	__status & -1UL;					\
 })
 
 #ifdef CONFIG_DEBUG_FS
@@ -223,11 +236,12 @@ static struct vmballoon balloon;
  */
 static bool vmballoon_send_start(struct vmballoon *b)
 {
-	unsigned long status, dummy;
+	unsigned long status, capabilities;
 
 	STATS_INC(b->stats.start);
 
-	status = VMWARE_BALLOON_CMD(START, VMW_BALLOON_PROTOCOL_VERSION, dummy);
+	status = VMWARE_BALLOON_CMD(START, VMW_BALLOON_CAPABILITIES,
+				capabilities);
 	if (status == VMW_BALLOON_SUCCESS)
 		return true;
 
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1202017 — [PATCH v4 7/9] VMware balloon: Support 2m page ballooning.

From"Philip P. Moltmann" <moltmann@vmware.com>
Date2015-08-06 22:40 +0200
Subject[PATCH v4 7/9] VMware balloon: Support 2m page ballooning.
Message-ID<pUA7h-34H-37@gated-at.bofh.it>
In reply to#1202001
2m ballooning significantly reduces the hypervisor side (and guest side)
overhead of ballooning and unballooning.

hypervisor only:
      balloon  unballoon
4 KB  2 GB/s   2.6 GB/s
2 MB  54 GB/s  767 GB/s

Use 2 MB pages as the hypervisor is alwys 64bit and 2 MB is the smallest
supported super-page size.

The code has to run on older versions of ESX and old balloon drivers run on
newer version of ESX. Hence match the capabilities with the host before 2m
page ballooning could be enabled.

Signed-off-by: Xavier Deguillard <xdeguillard@vmware.com>
---
 drivers/misc/vmw_balloon.c | 376 +++++++++++++++++++++++++++++++--------------
 1 file changed, 258 insertions(+), 118 deletions(-)

diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index aed9525..01519ff 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -47,7 +47,7 @@
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.3.4.0-k");
+MODULE_VERSION("1.4.0.0-k");
 MODULE_ALIAS("dmi:*:svnVMware*:*");
 MODULE_ALIAS("vmware_vmmemctl");
 MODULE_LICENSE("GPL");
@@ -102,11 +102,16 @@ enum vmwballoon_capabilities {
 	 * Bit 0 is reserved and not associated to any capability.
 	 */
 	VMW_BALLOON_BASIC_CMDS		= (1 << 1),
-	VMW_BALLOON_BATCHED_CMDS	= (1 << 2)
+	VMW_BALLOON_BATCHED_CMDS	= (1 << 2),
+	VMW_BALLOON_BATCHED_2M_CMDS     = (1 << 3),
 };
 
 #define VMW_BALLOON_CAPABILITIES	(VMW_BALLOON_BASIC_CMDS \
-					| VMW_BALLOON_BATCHED_CMDS)
+					| VMW_BALLOON_BATCHED_CMDS \
+					| VMW_BALLOON_BATCHED_2M_CMDS)
+
+#define VMW_BALLOON_2M_SHIFT		(9)
+#define VMW_BALLOON_NUM_PAGE_SIZES	(2)
 
 /*
  * Backdoor commands availability:
@@ -117,14 +122,19 @@ enum vmwballoon_capabilities {
  *	LOCK and UNLOCK commands,
  * VMW_BALLOON_BATCHED_CMDS:
  *	BATCHED_LOCK and BATCHED_UNLOCK commands.
+ * VMW BALLOON_BATCHED_2M_CMDS:
+ *	BATCHED_2M_LOCK and BATCHED_2M_UNLOCK commands.
  */
-#define VMW_BALLOON_CMD_START		0
-#define VMW_BALLOON_CMD_GET_TARGET	1
-#define VMW_BALLOON_CMD_LOCK		2
-#define VMW_BALLOON_CMD_UNLOCK		3
-#define VMW_BALLOON_CMD_GUEST_ID	4
-#define VMW_BALLOON_CMD_BATCHED_LOCK	6
-#define VMW_BALLOON_CMD_BATCHED_UNLOCK	7
+#define VMW_BALLOON_CMD_START			0
+#define VMW_BALLOON_CMD_GET_TARGET		1
+#define VMW_BALLOON_CMD_LOCK			2
+#define VMW_BALLOON_CMD_UNLOCK			3
+#define VMW_BALLOON_CMD_GUEST_ID		4
+#define VMW_BALLOON_CMD_BATCHED_LOCK		6
+#define VMW_BALLOON_CMD_BATCHED_UNLOCK		7
+#define VMW_BALLOON_CMD_BATCHED_2M_LOCK		8
+#define VMW_BALLOON_CMD_BATCHED_2M_UNLOCK	9
+
 
 /* error codes */
 #define VMW_BALLOON_SUCCESS		        0
@@ -152,9 +162,6 @@ enum vmwballoon_capabilities {
  * +-------------+----------+--------+
  * 64  PAGE_SHIFT          6         0
  *
- * For now only 4K pages are supported, but we can easily support large pages
- * by using bits in the reserved field.
- *
  * The reserved field should be set to 0.
  */
 #define VMW_BALLOON_BATCH_MAX_PAGES	(PAGE_SIZE / sizeof(u64))
@@ -209,19 +216,19 @@ struct vmballoon_stats {
 	unsigned int timer;
 
 	/* allocation statistics */
-	unsigned int alloc;
-	unsigned int alloc_fail;
+	unsigned int alloc[VMW_BALLOON_NUM_PAGE_SIZES];
+	unsigned int alloc_fail[VMW_BALLOON_NUM_PAGE_SIZES];
 	unsigned int sleep_alloc;
 	unsigned int sleep_alloc_fail;
-	unsigned int refused_alloc;
-	unsigned int refused_free;
-	unsigned int free;
+	unsigned int refused_alloc[VMW_BALLOON_NUM_PAGE_SIZES];
+	unsigned int refused_free[VMW_BALLOON_NUM_PAGE_SIZES];
+	unsigned int free[VMW_BALLOON_NUM_PAGE_SIZES];
 
 	/* monitor operations */
-	unsigned int lock;
-	unsigned int lock_fail;
-	unsigned int unlock;
-	unsigned int unlock_fail;
+	unsigned int lock[VMW_BALLOON_NUM_PAGE_SIZES];
+	unsigned int lock_fail[VMW_BALLOON_NUM_PAGE_SIZES];
+	unsigned int unlock[VMW_BALLOON_NUM_PAGE_SIZES];
+	unsigned int unlock_fail[VMW_BALLOON_NUM_PAGE_SIZES];
 	unsigned int target;
 	unsigned int target_fail;
 	unsigned int start;
@@ -240,19 +247,25 @@ struct vmballoon;
 struct vmballoon_ops {
 	void (*add_page)(struct vmballoon *b, int idx, struct page *p);
 	int (*lock)(struct vmballoon *b, unsigned int num_pages,
-						unsigned int *target);
+			bool is_2m_pages, unsigned int *target);
 	int (*unlock)(struct vmballoon *b, unsigned int num_pages,
-						unsigned int *target);
+			bool is_2m_pages, unsigned int *target);
 };
 
-struct vmballoon {
-
+struct vmballoon_page_size {
 	/* list of reserved physical pages */
 	struct list_head pages;
 
 	/* transient list of non-balloonable pages */
 	struct list_head refused_pages;
 	unsigned int n_refused_pages;
+};
+
+struct vmballoon {
+	struct vmballoon_page_size page_sizes[VMW_BALLOON_NUM_PAGE_SIZES];
+
+	/* supported page sizes. 1 == 4k pages only, 2 == 4k and 2m pages */
+	unsigned supported_page_sizes;
 
 	/* balloon size in pages */
 	unsigned int size;
@@ -297,6 +310,7 @@ static struct vmballoon balloon;
 static bool vmballoon_send_start(struct vmballoon *b, unsigned long req_caps)
 {
 	unsigned long status, capabilities, dummy = 0;
+	bool success;
 
 	STATS_INC(b->stats.start);
 
@@ -305,15 +319,26 @@ static bool vmballoon_send_start(struct vmballoon *b, unsigned long req_caps)
 	switch (status) {
 	case VMW_BALLOON_SUCCESS_WITH_CAPABILITIES:
 		b->capabilities = capabilities;
-		return true;
+		success = true;
+		break;
 	case VMW_BALLOON_SUCCESS:
 		b->capabilities = VMW_BALLOON_BASIC_CMDS;
-		return true;
+		success = true;
+		break;
+	default:
+		success = false;
 	}
 
-	pr_debug("%s - failed, hv returns %ld\n", __func__, status);
-	STATS_INC(b->stats.start_fail);
-	return false;
+	if (b->capabilities & VMW_BALLOON_BATCHED_2M_CMDS)
+		b->supported_page_sizes = 2;
+	else
+		b->supported_page_sizes = 1;
+
+	if (!success) {
+		pr_debug("%s - failed, hv returns %ld\n", __func__, status);
+		STATS_INC(b->stats.start_fail);
+	}
+	return success;
 }
 
 static bool vmballoon_check_status(struct vmballoon *b, unsigned long status)
@@ -354,6 +379,14 @@ static bool vmballoon_send_guest_id(struct vmballoon *b)
 	return false;
 }
 
+static u16 vmballoon_page_size(bool is_2m_page)
+{
+	if (is_2m_page)
+		return 1 << VMW_BALLOON_2M_SHIFT;
+
+	return 1;
+}
+
 /*
  * Retrieve desired balloon size from the host.
  */
@@ -407,31 +440,37 @@ static int vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,
 	if (pfn32 != pfn)
 		return -1;
 
-	STATS_INC(b->stats.lock);
+	STATS_INC(b->stats.lock[false]);
 
 	*hv_status = status = VMWARE_BALLOON_CMD(LOCK, pfn, dummy, *target);
 	if (vmballoon_check_status(b, status))
 		return 0;
 
 	pr_debug("%s - ppn %lx, hv returns %ld\n", __func__, pfn, status);
-	STATS_INC(b->stats.lock_fail);
+	STATS_INC(b->stats.lock_fail[false]);
 	return 1;
 }
 
 static int vmballoon_send_batched_lock(struct vmballoon *b,
-				unsigned int num_pages, unsigned int *target)
+		unsigned int num_pages, bool is_2m_pages, unsigned int *target)
 {
 	unsigned long status;
 	unsigned long pfn = page_to_pfn(b->page);
 
-	STATS_INC(b->stats.lock);
+	STATS_INC(b->stats.lock[is_2m_pages]);
+
+	if (is_2m_pages)
+		status = VMWARE_BALLOON_CMD(BATCHED_2M_LOCK, pfn, num_pages,
+				*target);
+	else
+		status = VMWARE_BALLOON_CMD(BATCHED_LOCK, pfn, num_pages,
+				*target);
 
-	status = VMWARE_BALLOON_CMD(BATCHED_LOCK, pfn, num_pages, *target);
 	if (vmballoon_check_status(b, status))
 		return 0;
 
 	pr_debug("%s - batch ppn %lx, hv returns %ld\n", __func__, pfn, status);
-	STATS_INC(b->stats.lock_fail);
+	STATS_INC(b->stats.lock_fail[is_2m_pages]);
 	return 1;
 }
 
@@ -449,34 +488,56 @@ static bool vmballoon_send_unlock_page(struct vmballoon *b, unsigned long pfn,
 	if (pfn32 != pfn)
 		return false;
 
-	STATS_INC(b->stats.unlock);
+	STATS_INC(b->stats.unlock[false]);
 
 	status = VMWARE_BALLOON_CMD(UNLOCK, pfn, dummy, *target);
 	if (vmballoon_check_status(b, status))
 		return true;
 
 	pr_debug("%s - ppn %lx, hv returns %ld\n", __func__, pfn, status);
-	STATS_INC(b->stats.unlock_fail);
+	STATS_INC(b->stats.unlock_fail[false]);
 	return false;
 }
 
 static bool vmballoon_send_batched_unlock(struct vmballoon *b,
-				unsigned int num_pages, unsigned int *target)
+		unsigned int num_pages, bool is_2m_pages, unsigned int *target)
 {
 	unsigned long status;
 	unsigned long pfn = page_to_pfn(b->page);
 
-	STATS_INC(b->stats.unlock);
+	STATS_INC(b->stats.unlock[is_2m_pages]);
+
+	if (is_2m_pages)
+		status = VMWARE_BALLOON_CMD(BATCHED_2M_UNLOCK, pfn, num_pages,
+				*target);
+	else
+		status = VMWARE_BALLOON_CMD(BATCHED_UNLOCK, pfn, num_pages,
+				*target);
 
-	status = VMWARE_BALLOON_CMD(BATCHED_UNLOCK, pfn, num_pages, *target);
 	if (vmballoon_check_status(b, status))
 		return true;
 
 	pr_debug("%s - batch ppn %lx, hv returns %ld\n", __func__, pfn, status);
-	STATS_INC(b->stats.unlock_fail);
+	STATS_INC(b->stats.unlock_fail[is_2m_pages]);
 	return false;
 }
 
+static struct page *vmballoon_alloc_page(gfp_t flags, bool is_2m_page)
+{
+	if (is_2m_page)
+		return alloc_pages(flags, VMW_BALLOON_2M_SHIFT);
+
+	return alloc_page(flags);
+}
+
+static void vmballoon_free_page(struct page *page, bool is_2m_page)
+{
+	if (is_2m_page)
+		__free_pages(page, VMW_BALLOON_2M_SHIFT);
+	else
+		__free_page(page);
+}
+
 /*
  * Quickly release all pages allocated for the balloon. This function is
  * called when host decides to "reset" balloon for one reason or another.
@@ -486,13 +547,21 @@ static bool vmballoon_send_batched_unlock(struct vmballoon *b,
 static void vmballoon_pop(struct vmballoon *b)
 {
 	struct page *page, *next;
-
-	list_for_each_entry_safe(page, next, &b->pages, lru) {
-		list_del(&page->lru);
-		__free_page(page);
-		STATS_INC(b->stats.free);
-		b->size--;
-		cond_resched();
+	unsigned is_2m_pages;
+
+	for (is_2m_pages = 0; is_2m_pages < VMW_BALLOON_NUM_PAGE_SIZES;
+			is_2m_pages++) {
+		struct vmballoon_page_size *page_size =
+				&b->page_sizes[is_2m_pages];
+		u16 size_per_page = vmballoon_page_size(is_2m_pages);
+
+		list_for_each_entry_safe(page, next, &page_size->pages, lru) {
+			list_del(&page->lru);
+			vmballoon_free_page(page, is_2m_pages);
+			STATS_INC(b->stats.free[is_2m_pages]);
+			b->size -= size_per_page;
+			cond_resched();
+		}
 	}
 
 	if ((b->capabilities & VMW_BALLOON_BATCHED_CMDS) != 0) {
@@ -510,19 +579,22 @@ static void vmballoon_pop(struct vmballoon *b)
  * inflation cycle.
  */
 static int vmballoon_lock_page(struct vmballoon *b, unsigned int num_pages,
-							unsigned int *target)
+				bool is_2m_pages, unsigned int *target)
 {
 	int locked, hv_status;
 	struct page *page = b->page;
+	struct vmballoon_page_size *page_size = &b->page_sizes[false];
+
+	/* is_2m_pages can never happen as 2m pages support implies batching */
 
 	locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status,
 								target);
 	if (locked > 0) {
-		STATS_INC(b->stats.refused_alloc);
+		STATS_INC(b->stats.refused_alloc[false]);
 
 		if (hv_status == VMW_BALLOON_ERROR_RESET ||
 				hv_status == VMW_BALLOON_ERROR_PPN_NOTNEEDED) {
-			__free_page(page);
+			vmballoon_free_page(page, false);
 			return -EIO;
 		}
 
@@ -531,17 +603,17 @@ static int vmballoon_lock_page(struct vmballoon *b, unsigned int num_pages,
 		 * and retry allocation, unless we already accumulated
 		 * too many of them, in which case take a breather.
 		 */
-		if (b->n_refused_pages < VMW_BALLOON_MAX_REFUSED) {
-			b->n_refused_pages++;
-			list_add(&page->lru, &b->refused_pages);
+		if (page_size->n_refused_pages < VMW_BALLOON_MAX_REFUSED) {
+			page_size->n_refused_pages++;
+			list_add(&page->lru, &page_size->refused_pages);
 		} else {
-			__free_page(page);
+			vmballoon_free_page(page, false);
 		}
 		return -EIO;
 	}
 
 	/* track allocated page */
-	list_add(&page->lru, &b->pages);
+	list_add(&page->lru, &page_size->pages);
 
 	/* update balloon size */
 	b->size++;
@@ -550,17 +622,19 @@ static int vmballoon_lock_page(struct vmballoon *b, unsigned int num_pages,
 }
 
 static int vmballoon_lock_batched_page(struct vmballoon *b,
-				unsigned int num_pages, unsigned int *target)
+		unsigned int num_pages, bool is_2m_pages, unsigned int *target)
 {
 	int locked, i;
+	u16 size_per_page = vmballoon_page_size(is_2m_pages);
 
-	locked = vmballoon_send_batched_lock(b, num_pages, target);
+	locked = vmballoon_send_batched_lock(b, num_pages, is_2m_pages,
+			target);
 	if (locked > 0) {
 		for (i = 0; i < num_pages; i++) {
 			u64 pa = vmballoon_batch_get_pa(b->batch_page, i);
 			struct page *p = pfn_to_page(pa >> PAGE_SHIFT);
 
-			__free_page(p);
+			vmballoon_free_page(p, is_2m_pages);
 		}
 
 		return -EIO;
@@ -569,25 +643,28 @@ static int vmballoon_lock_batched_page(struct vmballoon *b,
 	for (i = 0; i < num_pages; i++) {
 		u64 pa = vmballoon_batch_get_pa(b->batch_page, i);
 		struct page *p = pfn_to_page(pa >> PAGE_SHIFT);
+		struct vmballoon_page_size *page_size =
+				&b->page_sizes[is_2m_pages];
 
 		locked = vmballoon_batch_get_status(b->batch_page, i);
 
 		switch (locked) {
 		case VMW_BALLOON_SUCCESS:
-			list_add(&p->lru, &b->pages);
-			b->size++;
+			list_add(&p->lru, &page_size->pages);
+			b->size += size_per_page;
 			break;
 		case VMW_BALLOON_ERROR_PPN_PINNED:
 		case VMW_BALLOON_ERROR_PPN_INVALID:
-			if (b->n_refused_pages < VMW_BALLOON_MAX_REFUSED) {
-				list_add(&p->lru, &b->refused_pages);
-				b->n_refused_pages++;
+			if (page_size->n_refused_pages
+					< VMW_BALLOON_MAX_REFUSED) {
+				list_add(&p->lru, &page_size->refused_pages);
+				page_size->n_refused_pages++;
 				break;
 			}
 			/* Fallthrough */
 		case VMW_BALLOON_ERROR_RESET:
 		case VMW_BALLOON_ERROR_PPN_NOTNEEDED:
-			__free_page(p);
+			vmballoon_free_page(p, is_2m_pages);
 			break;
 		default:
 			/* This should never happen */
@@ -604,18 +681,21 @@ static int vmballoon_lock_batched_page(struct vmballoon *b,
  * to use, if needed.
  */
 static int vmballoon_unlock_page(struct vmballoon *b, unsigned int num_pages,
-							unsigned int *target)
+		bool is_2m_pages, unsigned int *target)
 {
 	struct page *page = b->page;
+	struct vmballoon_page_size *page_size = &b->page_sizes[false];
+
+	/* is_2m_pages can never happen as 2m pages support implies batching */
 
 	if (!vmballoon_send_unlock_page(b, page_to_pfn(page), target)) {
-		list_add(&page->lru, &b->pages);
+		list_add(&page->lru, &page_size->pages);
 		return -EIO;
 	}
 
 	/* deallocate page */
-	__free_page(page);
-	STATS_INC(b->stats.free);
+	vmballoon_free_page(page, false);
+	STATS_INC(b->stats.free[false]);
 
 	/* update balloon size */
 	b->size--;
@@ -624,18 +704,23 @@ static int vmballoon_unlock_page(struct vmballoon *b, unsigned int num_pages,
 }
 
 static int vmballoon_unlock_batched_page(struct vmballoon *b,
-				unsigned int num_pages, unsigned int *target)
+				unsigned int num_pages, bool is_2m_pages,
+				unsigned int *target)
 {
 	int locked, i, ret = 0;
 	bool hv_success;
+	u16 size_per_page = vmballoon_page_size(is_2m_pages);
 
-	hv_success = vmballoon_send_batched_unlock(b, num_pages, target);
+	hv_success = vmballoon_send_batched_unlock(b, num_pages, is_2m_pages,
+			target);
 	if (!hv_success)
 		ret = -EIO;
 
 	for (i = 0; i < num_pages; i++) {
 		u64 pa = vmballoon_batch_get_pa(b->batch_page, i);
 		struct page *p = pfn_to_page(pa >> PAGE_SHIFT);
+		struct vmballoon_page_size *page_size =
+				&b->page_sizes[is_2m_pages];
 
 		locked = vmballoon_batch_get_status(b->batch_page, i);
 		if (!hv_success || locked != VMW_BALLOON_SUCCESS) {
@@ -644,14 +729,14 @@ static int vmballoon_unlock_batched_page(struct vmballoon *b,
 			 * hypervisor, re-add it to the list of pages owned by
 			 * the balloon driver.
 			 */
-			list_add(&p->lru, &b->pages);
+			list_add(&p->lru, &page_size->pages);
 		} else {
 			/* deallocate page */
-			__free_page(p);
-			STATS_INC(b->stats.free);
+			vmballoon_free_page(p, is_2m_pages);
+			STATS_INC(b->stats.free[is_2m_pages]);
 
 			/* update balloon size */
-			b->size--;
+			b->size -= size_per_page;
 		}
 	}
 
@@ -662,17 +747,20 @@ static int vmballoon_unlock_batched_page(struct vmballoon *b,
  * Release pages that were allocated while attempting to inflate the
  * balloon but were refused by the host for one reason or another.
  */
-static void vmballoon_release_refused_pages(struct vmballoon *b)
+static void vmballoon_release_refused_pages(struct vmballoon *b,
+		bool is_2m_pages)
 {
 	struct page *page, *next;
+	struct vmballoon_page_size *page_size =
+			&b->page_sizes[is_2m_pages];
 
-	list_for_each_entry_safe(page, next, &b->refused_pages, lru) {
+	list_for_each_entry_safe(page, next, &page_size->refused_pages, lru) {
 		list_del(&page->lru);
-		__free_page(page);
-		STATS_INC(b->stats.refused_free);
+		vmballoon_free_page(page, is_2m_pages);
+		STATS_INC(b->stats.refused_free[is_2m_pages]);
 	}
 
-	b->n_refused_pages = 0;
+	page_size->n_refused_pages = 0;
 }
 
 static void vmballoon_add_page(struct vmballoon *b, int idx, struct page *p)
@@ -699,6 +787,7 @@ static void vmballoon_inflate(struct vmballoon *b)
 	unsigned int num_pages = 0;
 	int error = 0;
 	gfp_t flags = VMW_PAGE_ALLOC_NOSLEEP;
+	bool is_2m_pages;
 
 	pr_debug("%s - size: %d, target %d\n", __func__, b->size, b->target);
 
@@ -721,22 +810,46 @@ static void vmballoon_inflate(struct vmballoon *b)
 	 * Start with no sleep allocation rate which may be higher
 	 * than sleeping allocation rate.
 	 */
-	rate = b->slow_allocation_cycles ? b->rate_alloc : UINT_MAX;
+	if (b->slow_allocation_cycles) {
+		rate = b->rate_alloc;
+		is_2m_pages = false;
+	} else {
+		rate = UINT_MAX;
+		is_2m_pages =
+			b->supported_page_sizes == VMW_BALLOON_NUM_PAGE_SIZES;
+	}
 
 	pr_debug("%s - goal: %d, no-sleep rate: %u, sleep rate: %d\n",
 		 __func__, b->target - b->size, rate, b->rate_alloc);
 
 	while (!b->reset_required &&
-		b->size < b->target && num_pages < b->target - b->size) {
+		b->size + num_pages * vmballoon_page_size(is_2m_pages)
+		< b->target) {
 		struct page *page;
 
 		if (flags == VMW_PAGE_ALLOC_NOSLEEP)
-			STATS_INC(b->stats.alloc);
+			STATS_INC(b->stats.alloc[is_2m_pages]);
 		else
 			STATS_INC(b->stats.sleep_alloc);
 
-		page = alloc_page(flags);
+		page = vmballoon_alloc_page(flags, is_2m_pages);
 		if (!page) {
+			STATS_INC(b->stats.alloc_fail[is_2m_pages]);
+
+			if (is_2m_pages) {
+				b->ops->lock(b, num_pages, true, &b->target);
+
+				/*
+				 * ignore errors from locking as we now switch
+				 * to 4k pages and we might get different
+				 * errors.
+				 */
+
+				num_pages = 0;
+				is_2m_pages = false;
+				continue;
+			}
+
 			if (flags == VMW_PAGE_ALLOC_CANSLEEP) {
 				/*
 				 * CANSLEEP page allocation failed, so guest
@@ -748,7 +861,6 @@ static void vmballoon_inflate(struct vmballoon *b)
 				STATS_INC(b->stats.sleep_alloc_fail);
 				break;
 			}
-			STATS_INC(b->stats.alloc_fail);
 
 			/*
 			 * NOSLEEP page allocation failed, so the guest is
@@ -771,7 +883,8 @@ static void vmballoon_inflate(struct vmballoon *b)
 
 		b->ops->add_page(b, num_pages++, page);
 		if (num_pages == b->batch_max_pages) {
-			error = b->ops->lock(b, num_pages, &b->target);
+			error = b->ops->lock(b, num_pages, is_2m_pages,
+					&b->target);
 			num_pages = 0;
 			if (error)
 				break;
@@ -786,7 +899,7 @@ static void vmballoon_inflate(struct vmballoon *b)
 	}
 
 	if (num_pages > 0)
-		b->ops->lock(b, num_pages, &b->target);
+		b->ops->lock(b, num_pages, is_2m_pages, &b->target);
 
 	/*
 	 * We reached our goal without failures so try increasing
@@ -800,7 +913,8 @@ static void vmballoon_inflate(struct vmballoon *b)
 			    VMW_BALLOON_RATE_ALLOC_MAX);
 	}
 
-	vmballoon_release_refused_pages(b);
+	vmballoon_release_refused_pages(b, true);
+	vmballoon_release_refused_pages(b, false);
 }
 
 /*
@@ -808,34 +922,45 @@ static void vmballoon_inflate(struct vmballoon *b)
  */
 static void vmballoon_deflate(struct vmballoon *b)
 {
-	struct page *page, *next;
-	unsigned int i = 0;
-	unsigned int num_pages = 0;
-	int error;
+	unsigned is_2m_pages;
 
 	pr_debug("%s - size: %d, target %d\n", __func__, b->size, b->target);
 
 	/* free pages to reach target */
-	list_for_each_entry_safe(page, next, &b->pages, lru) {
-		list_del(&page->lru);
-		b->ops->add_page(b, num_pages++, page);
+	for (is_2m_pages = 0; is_2m_pages < b->supported_page_sizes;
+			is_2m_pages++) {
+		struct page *page, *next;
+		unsigned int num_pages = 0;
+		struct vmballoon_page_size *page_size =
+				&b->page_sizes[is_2m_pages];
+
+		list_for_each_entry_safe(page, next, &page_size->pages, lru) {
+			if (b->reset_required ||
+				(b->target > 0 &&
+					b->size - num_pages
+					* vmballoon_page_size(is_2m_pages)
+				< b->target + vmballoon_page_size(true)))
+				break;
 
+			list_del(&page->lru);
+			b->ops->add_page(b, num_pages++, page);
 
-		if (num_pages == b->batch_max_pages) {
-			error = b->ops->unlock(b, num_pages, &b->target);
-			num_pages = 0;
-			if (error)
-				return;
-		}
+			if (num_pages == b->batch_max_pages) {
+				int error;
 
-		if (b->reset_required || ++i >= b->size - b->target)
-			break;
+				error = b->ops->unlock(b, num_pages,
+						is_2m_pages, &b->target);
+				num_pages = 0;
+				if (error)
+					return;
+			}
 
-		cond_resched();
-	}
+			cond_resched();
+		}
 
-	if (num_pages > 0)
-		b->ops->unlock(b, num_pages, &b->target);
+		if (num_pages > 0)
+			b->ops->unlock(b, num_pages, is_2m_pages, &b->target);
+	}
 }
 
 static const struct vmballoon_ops vmballoon_basic_ops = {
@@ -925,7 +1050,8 @@ static void vmballoon_work(struct work_struct *work)
 
 		if (b->size < target)
 			vmballoon_inflate(b);
-		else if (b->size > target)
+		else if (target == 0 ||
+				b->size > target + vmballoon_page_size(true))
 			vmballoon_deflate(b);
 	}
 
@@ -969,24 +1095,35 @@ static int vmballoon_debug_show(struct seq_file *f, void *offset)
 		   "timer:              %8u\n"
 		   "start:              %8u (%4u failed)\n"
 		   "guestType:          %8u (%4u failed)\n"
+		   "2m-lock:            %8u (%4u failed)\n"
 		   "lock:               %8u (%4u failed)\n"
+		   "2m-unlock:          %8u (%4u failed)\n"
 		   "unlock:             %8u (%4u failed)\n"
 		   "target:             %8u (%4u failed)\n"
+		   "prim2mAlloc:        %8u (%4u failed)\n"
 		   "primNoSleepAlloc:   %8u (%4u failed)\n"
 		   "primCanSleepAlloc:  %8u (%4u failed)\n"
+		   "prim2mFree:         %8u\n"
 		   "primFree:           %8u\n"
+		   "err2mAlloc:         %8u\n"
 		   "errAlloc:           %8u\n"
+		   "err2mFree:          %8u\n"
 		   "errFree:            %8u\n",
 		   stats->timer,
 		   stats->start, stats->start_fail,
 		   stats->guest_type, stats->guest_type_fail,
-		   stats->lock,  stats->lock_fail,
-		   stats->unlock, stats->unlock_fail,
+		   stats->lock[true],  stats->lock_fail[true],
+		   stats->lock[false],  stats->lock_fail[false],
+		   stats->unlock[true], stats->unlock_fail[true],
+		   stats->unlock[false], stats->unlock_fail[false],
 		   stats->target, stats->target_fail,
-		   stats->alloc, stats->alloc_fail,
+		   stats->alloc[true], stats->alloc_fail[true],
+		   stats->alloc[false], stats->alloc_fail[false],
 		   stats->sleep_alloc, stats->sleep_alloc_fail,
-		   stats->free,
-		   stats->refused_alloc, stats->refused_free);
+		   stats->free[true],
+		   stats->free[false],
+		   stats->refused_alloc[true], stats->refused_alloc[false],
+		   stats->refused_free[true], stats->refused_free[false]);
 
 	return 0;
 }
@@ -1040,7 +1177,7 @@ static inline void vmballoon_debugfs_exit(struct vmballoon *b)
 static int __init vmballoon_init(void)
 {
 	int error;
-
+	unsigned is_2m_pages;
 	/*
 	 * Check if we are running on VMware's hypervisor and bail out
 	 * if we are not.
@@ -1048,8 +1185,11 @@ static int __init vmballoon_init(void)
 	if (x86_hyper != &x86_hyper_vmware)
 		return -ENODEV;
 
-	INIT_LIST_HEAD(&balloon.pages);
-	INIT_LIST_HEAD(&balloon.refused_pages);
+	for (is_2m_pages = 0; is_2m_pages < VMW_BALLOON_NUM_PAGE_SIZES;
+			is_2m_pages++) {
+		INIT_LIST_HEAD(&balloon.page_sizes[is_2m_pages].pages);
+		INIT_LIST_HEAD(&balloon.page_sizes[is_2m_pages].refused_pages);
+	}
 
 	/* initialize rates */
 	balloon.rate_alloc = VMW_BALLOON_RATE_ALLOC_MAX;
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1202021 — [PATCH v4 9/9] VMware balloon: Enable notification via VMCI

From"Philip P. Moltmann" <moltmann@vmware.com>
Date2015-08-06 22:40 +0200
Subject[PATCH v4 9/9] VMware balloon: Enable notification via VMCI
Message-ID<pUA7i-34H-49@gated-at.bofh.it>
In reply to#1202001
Get notified immediately when a balloon target is set, instead of waiting for
up to one second.

The up-to 1 second gap could be long enough to cause swapping inside of the
VM that receives the VM.

Acked-by: Andy King <acking@vmware.com>
Signed-off-by: Xavier Deguillard <xdeguillard@vmware.com>
Tested-by: Siva Sankar Reddy B <sankars@vmware.com>
---
 drivers/misc/Kconfig       |   2 +-
 drivers/misc/vmw_balloon.c | 105 +++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 97 insertions(+), 10 deletions(-)

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 42c3852..76a3d42 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -404,7 +404,7 @@ config TI_DAC7512
 
 config VMWARE_BALLOON
 	tristate "VMware Balloon Driver"
-	depends on X86 && HYPERVISOR_GUEST
+	depends on VMWARE_VMCI && X86 && HYPERVISOR_GUEST
 	help
 	  This is VMware physical memory management driver which acts
 	  like a "balloon" that can be inflated to reclaim physical pages
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index 28fe9e5..8930087 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -1,7 +1,7 @@
 /*
  * VMware Balloon driver.
  *
- * Copyright (C) 2000-2013, VMware, Inc. All Rights Reserved.
+ * Copyright (C) 2000-2014, VMware, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -43,11 +43,13 @@
 #include <linux/workqueue.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/vmw_vmci_defs.h>
+#include <linux/vmw_vmci_api.h>
 #include <asm/hypervisor.h>
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.4.1.0-k");
+MODULE_VERSION("1.5.0.0-k");
 MODULE_ALIAS("dmi:*:svnVMware*:*");
 MODULE_ALIAS("vmware_vmmemctl");
 MODULE_LICENSE("GPL");
@@ -101,14 +103,16 @@ enum vmwballoon_capabilities {
 	/*
 	 * Bit 0 is reserved and not associated to any capability.
 	 */
-	VMW_BALLOON_BASIC_CMDS		= (1 << 1),
-	VMW_BALLOON_BATCHED_CMDS	= (1 << 2),
-	VMW_BALLOON_BATCHED_2M_CMDS     = (1 << 3),
+	VMW_BALLOON_BASIC_CMDS			= (1 << 1),
+	VMW_BALLOON_BATCHED_CMDS		= (1 << 2),
+	VMW_BALLOON_BATCHED_2M_CMDS		= (1 << 3),
+	VMW_BALLOON_SIGNALLED_WAKEUP_CMD	= (1 << 4),
 };
 
 #define VMW_BALLOON_CAPABILITIES	(VMW_BALLOON_BASIC_CMDS \
 					| VMW_BALLOON_BATCHED_CMDS \
-					| VMW_BALLOON_BATCHED_2M_CMDS)
+					| VMW_BALLOON_BATCHED_2M_CMDS \
+					| VMW_BALLOON_SIGNALLED_WAKEUP_CMD)
 
 #define VMW_BALLOON_2M_SHIFT		(9)
 #define VMW_BALLOON_NUM_PAGE_SIZES	(2)
@@ -123,7 +127,9 @@ enum vmwballoon_capabilities {
  * VMW_BALLOON_BATCHED_CMDS:
  *	BATCHED_LOCK and BATCHED_UNLOCK commands.
  * VMW BALLOON_BATCHED_2M_CMDS:
- *	BATCHED_2M_LOCK and BATCHED_2M_UNLOCK commands.
+ *	BATCHED_2M_LOCK and BATCHED_2M_UNLOCK commands,
+ * VMW VMW_BALLOON_SIGNALLED_WAKEUP_CMD:
+ *	VMW_BALLOON_CMD_VMCI_DOORBELL_SET command.
  */
 #define VMW_BALLOON_CMD_START			0
 #define VMW_BALLOON_CMD_GET_TARGET		1
@@ -134,6 +140,7 @@ enum vmwballoon_capabilities {
 #define VMW_BALLOON_CMD_BATCHED_UNLOCK		7
 #define VMW_BALLOON_CMD_BATCHED_2M_LOCK		8
 #define VMW_BALLOON_CMD_BATCHED_2M_UNLOCK	9
+#define VMW_BALLOON_CMD_VMCI_DOORBELL_SET	10
 
 
 /* error codes */
@@ -214,6 +221,7 @@ static void vmballoon_batch_set_pa(struct vmballoon_batch_page *batch, int idx,
 #ifdef CONFIG_DEBUG_FS
 struct vmballoon_stats {
 	unsigned int timer;
+	unsigned int doorbell;
 
 	/* allocation statistics */
 	unsigned int alloc[VMW_BALLOON_NUM_PAGE_SIZES];
@@ -235,6 +243,8 @@ struct vmballoon_stats {
 	unsigned int start_fail;
 	unsigned int guest_type;
 	unsigned int guest_type_fail;
+	unsigned int doorbell_set;
+	unsigned int doorbell_unset;
 };
 
 #define STATS_INC(stat) (stat)++
@@ -299,6 +309,8 @@ struct vmballoon {
 	struct sysinfo sysinfo;
 
 	struct delayed_work dwork;
+
+	struct vmci_handle vmci_doorbell;
 };
 
 static struct vmballoon balloon;
@@ -993,12 +1005,75 @@ static bool vmballoon_init_batching(struct vmballoon *b)
 }
 
 /*
+ * Receive notification and resize balloon
+ */
+static void vmballoon_doorbell(void *client_data)
+{
+	struct vmballoon *b = client_data;
+
+	STATS_INC(b->stats.doorbell);
+
+	mod_delayed_work(system_freezable_wq, &b->dwork, 0);
+}
+
+/*
+ * Clean up vmci doorbell
+ */
+static void vmballoon_vmci_cleanup(struct vmballoon *b)
+{
+	int error;
+
+	VMWARE_BALLOON_CMD(VMCI_DOORBELL_SET, VMCI_INVALID_ID,
+			VMCI_INVALID_ID, error);
+	STATS_INC(b->stats.doorbell_unset);
+
+	if (!vmci_handle_is_invalid(b->vmci_doorbell)) {
+		vmci_doorbell_destroy(b->vmci_doorbell);
+		b->vmci_doorbell = VMCI_INVALID_HANDLE;
+	}
+}
+
+/*
+ * Initialize vmci doorbell, to get notified as soon as balloon changes
+ */
+static int vmballoon_vmci_init(struct vmballoon *b)
+{
+	int error = 0;
+
+	if ((b->capabilities & VMW_BALLOON_SIGNALLED_WAKEUP_CMD) != 0) {
+		error = vmci_doorbell_create(&b->vmci_doorbell,
+				VMCI_FLAG_DELAYED_CB,
+				VMCI_PRIVILEGE_FLAG_RESTRICTED,
+				vmballoon_doorbell, b);
+
+		if (error == VMCI_SUCCESS) {
+			VMWARE_BALLOON_CMD(VMCI_DOORBELL_SET,
+					b->vmci_doorbell.context,
+					b->vmci_doorbell.resource, error);
+			STATS_INC(b->stats.doorbell_set);
+		}
+	}
+
+	if (error != 0) {
+		vmballoon_vmci_cleanup(b);
+
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
  * Perform standard reset sequence by popping the balloon (in case it
  * is not  empty) and then restarting protocol. This operation normally
  * happens when host responds with VMW_BALLOON_ERROR_RESET to a command.
  */
 static void vmballoon_reset(struct vmballoon *b)
 {
+	int error;
+
+	vmballoon_vmci_cleanup(b);
+
 	/* free all pages, skipping monitor unlock */
 	vmballoon_pop(b);
 
@@ -1024,6 +1099,11 @@ static void vmballoon_reset(struct vmballoon *b)
 	}
 
 	b->reset_required = false;
+
+	error = vmballoon_vmci_init(b);
+	if (error)
+		pr_err("failed to initialize vmci doorbell\n");
+
 	if (!vmballoon_send_guest_id(b))
 		pr_err("failed to send guest ID to the host\n");
 }
@@ -1097,6 +1177,7 @@ static int vmballoon_debug_show(struct seq_file *f, void *offset)
 	seq_printf(f,
 		   "\n"
 		   "timer:              %8u\n"
+		   "doorbell:           %8u\n"
 		   "start:              %8u (%4u failed)\n"
 		   "guestType:          %8u (%4u failed)\n"
 		   "2m-lock:            %8u (%4u failed)\n"
@@ -1112,8 +1193,11 @@ static int vmballoon_debug_show(struct seq_file *f, void *offset)
 		   "err2mAlloc:         %8u\n"
 		   "errAlloc:           %8u\n"
 		   "err2mFree:          %8u\n"
-		   "errFree:            %8u\n",
+		   "errFree:            %8u\n"
+		   "doorbellSet:        %8u\n"
+		   "doorbellUnset:      %8u\n",
 		   stats->timer,
+		   stats->doorbell,
 		   stats->start, stats->start_fail,
 		   stats->guest_type, stats->guest_type_fail,
 		   stats->lock[true],  stats->lock_fail[true],
@@ -1127,7 +1211,8 @@ static int vmballoon_debug_show(struct seq_file *f, void *offset)
 		   stats->free[true],
 		   stats->free[false],
 		   stats->refused_alloc[true], stats->refused_alloc[false],
-		   stats->refused_free[true], stats->refused_free[false]);
+		   stats->refused_free[true], stats->refused_free[false],
+		   stats->doorbell_set, stats->doorbell_unset);
 
 	return 0;
 }
@@ -1204,6 +1289,7 @@ static int __init vmballoon_init(void)
 	if (error)
 		return error;
 
+	balloon.vmci_doorbell = VMCI_INVALID_HANDLE;
 	balloon.batch_page = NULL;
 	balloon.page = NULL;
 	balloon.reset_required = true;
@@ -1216,6 +1302,7 @@ module_init(vmballoon_init);
 
 static void __exit vmballoon_exit(void)
 {
+	vmballoon_vmci_cleanup(&balloon);
 	cancel_delayed_work_sync(&balloon.dwork);
 
 	vmballoon_debugfs_exit(&balloon);
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1201321 — Re: [PATCH v4 3/9] VMware balloon: add batching to the vmw_balloon.

FromGreg KH <gregkh@linuxfoundation.org>
Date2015-08-06 00:50 +0200
SubjectRe: [PATCH v4 3/9] VMware balloon: add batching to the vmw_balloon.
Message-ID<pUfFw-6J8-7@gated-at.bofh.it>
In reply to#1201311
On Wed, Aug 05, 2015 at 03:36:31PM -0700, Philip P. Moltmann wrote:
> From: Xavier Deguillard <xdeguillard@vmware.com>
> 
> Introduce a new capability to the driver that allow sending 512 pages in
> one hypervisor call. This reduce the cost of the driver when reclaiming
> memory.
> 
> Signed-off-by: Xavier Deguillard <xdeguillard@vmware.com>
> Acked-by: Dmitry Torokhov <dtor@vmware.com>
> Signed-off-by: Philip P. Moltmann <moltmann@vmware.com>
> ---
>  drivers/misc/vmw_balloon.c | 406 +++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 353 insertions(+), 53 deletions(-)

what changed?
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | linux.kernel


csiph-web