]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
vmmemctl: use capability based system to advertise balloon features
authorVMware, Inc <>
Mon, 15 Oct 2012 04:53:17 +0000 (21:53 -0700)
committerDmitry Torokhov <dtor@vmware.com>
Fri, 19 Oct 2012 18:32:41 +0000 (11:32 -0700)
Use a capability based system instead of versioning to advertise
and negotiate balloon features.

On START command, the guest is sending its capability and the
monitor returns the masked capability. That way, the guest knows
exactly what features are supported by the monitor.

Currently the capability use two bits: if the bit 1 is set, then
the unbatched lock and unlock are supported, and if the bit 2 is
set, then the batched lock and unlock are supported. Bit 1 was
chosen to be backward compatible with "protocol v2", and bit 0
is unused to avoid issue with the screwed "protocol v3".

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/modules/freebsd/vmmemctl/os.c
open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.c
open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.h
open-vm-tools/modules/shared/vmmemctl/balloonInt.h
open-vm-tools/modules/shared/vmmemctl/balloon_def.h
open-vm-tools/modules/shared/vmmemctl/os.h
open-vm-tools/modules/shared/vmmemctl/vmballoon.c
open-vm-tools/modules/shared/vmmemctl/vmballoon.h
open-vm-tools/modules/solaris/vmmemctl/os.c

index 29f25a5c84d15d2edf57ed44a329da7de9f5c843..caee2a661c5105ba4979a97c1a3c4793f0b35396 100644 (file)
@@ -230,13 +230,13 @@ OS_ReservedPageGetLimit(void)
 /*
  *-----------------------------------------------------------------------------
  *
- * OS_ReservedPageGetPPN --
+ * OS_ReservedPageGetPA --
  *
  *      Convert a page handle (of a physical page previously reserved with
- *      OS_ReservedPageAlloc()) to a ppn.
+ *      OS_ReservedPageAlloc()) to a pa.
  *
  * Results:
- *      The ppn.
+ *      The pa.
  *
  * Side effects:
  *      None.
@@ -244,10 +244,10 @@ OS_ReservedPageGetLimit(void)
  *-----------------------------------------------------------------------------
  */
 
-PPN64
-OS_ReservedPageGetPPN(PageHandle handle) // IN: A valid page handle
+PA64
+OS_ReservedPageGetPA(PageHandle handle) // IN: A valid page handle
 {
-   return (((vm_page_t)handle)->phys_addr) >> PAGE_SHIFT;
+   return (((vm_page_t)handle)->phys_addr);
 }
 
 
@@ -256,7 +256,7 @@ OS_ReservedPageGetPPN(PageHandle handle) // IN: A valid page handle
  *
  * OS_ReservedPageGetHandle --
  *
- *      Convert a ppn (of a physical page previously reserved with
+ *      Convert a pa (of a physical page previously reserved with
  *      OS_ReservedPageAlloc()) to a page handle.
  *
  * Results:
@@ -269,9 +269,9 @@ OS_ReservedPageGetPPN(PageHandle handle) // IN: A valid page handle
  */
 
 PageHandle
-OS_ReservedPageGetHandle(PPN64 ppn)     // IN
+OS_ReservedPageGetHandle(PA64 pa)     // IN
 {
-   return (PageHandle)PHYS_TO_VM_PAGE(ppn << PAGE_SHIFT);
+   return (PageHandle)PHYS_TO_VM_PAGE(pa);
 }
 
 
@@ -516,7 +516,7 @@ os_balloonobject_create(void)
  *      Reserve a physical page for the exclusive use of this driver.
  *
  * Results:
- *      On success: A valid page handle that can be passed to OS_ReservedPageGetPPN()
+ *      On success: A valid page handle that can be passed to OS_ReservedPageGetPA()
  *                  or OS_ReservedPageFree().
  *      On failure: PAGE_HANDLE_INVALID
  *
index 674391b64022ff0682e54d885d6f84a8b9ac0791..5837e41fcb6d9dff53defcf3391afacc5aeddf13 100644 (file)
@@ -121,14 +121,15 @@ Backdoor_MonitorStart(Balloon *b,               // IN
    status = bp.out.ax.word;
 
    /*
-    * If return code is BALLOON_SUCCESS_WITH_VERSION, then ESX is
-    * sending the protocol version to be used into cx.
+    * If return code is BALLOON_SUCCESS_WITH_CAPABILITY, then ESX is
+    * sending the common capabilities supported by the monitor and the
+    * guest in cx.
     */
-   if (status == BALLOON_SUCCESS_WITH_VERSION) {
-      b->hypervisorProtocolVersion = bp.out.cx.word;
+   if (status == BALLOON_SUCCESS_WITH_CAPABILITIES) {
+      b->hypervisorCapabilities = bp.out.cx.word;
       status = BALLOON_SUCCESS;
    } else if (status == BALLOON_SUCCESS) {
-      b->hypervisorProtocolVersion = BALLOON_PROTOCOL_VERSION_2;
+      b->hypervisorCapabilities = BALLOON_BASIC_CMDS;
    }
 
    /* update stats */
@@ -285,13 +286,11 @@ Backdoor_MonitorLockPage(Balloon *b,    // IN
 {
    uint32 status;
    Backdoor_proto bp;
+   uint32 ppn32 = (uint32)ppn;
 
-   if (b->hypervisorProtocolVersion == BALLOON_PROTOCOL_VERSION_2) {
-      /* Ensure PPN fits in 32-bits, i.e. guest memory is limited to 16TB. */
-      uint32 ppn32 = (uint32)ppn;
-      if (ppn32 != ppn) {
-         return BALLOON_ERROR_PPN_INVALID;
-      }
+   /* Ensure PPN fits in 32-bits, i.e. guest memory is limited to 16TB. */
+   if (ppn32 != ppn) {
+      return BALLOON_ERROR_PPN_INVALID;
    }
 
    /* prepare backdoor args */
@@ -343,13 +342,11 @@ Backdoor_MonitorUnlockPage(Balloon *b,  // IN
 {
    uint32 status;
    Backdoor_proto bp;
+   uint32 ppn32 = (uint32)ppn;
 
-   if (b->hypervisorProtocolVersion == BALLOON_PROTOCOL_VERSION_2) {
-      /* Ensure PPN fits in 32-bits, i.e. guest memory is limited to 16TB. */
-      uint32 ppn32 = (uint32)ppn;
-      if (ppn32 != ppn) {
-         return BALLOON_ERROR_PPN_INVALID;
-      }
+   /* Ensure PPN fits in 32-bits, i.e. guest memory is limited to 16TB. */
+   if (ppn32 != ppn) {
+      return BALLOON_ERROR_PPN_INVALID;
    }
 
    /* prepare backdoor args */
@@ -375,3 +372,101 @@ Backdoor_MonitorUnlockPage(Balloon *b,  // IN
 
    return status;
 }
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Backdoor_MonitorLockPagesBatched --
+ *
+ *      Balloon all PPNs listed in the batch page.
+ *
+ * Results:
+ *      Returns BALLOON_SUCCESS if successful, otherwise error code.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Backdoor_MonitorLockPagesBatched(Balloon *b,    // IN
+                                 PPN64 ppn,     // IN
+                                 uint32 nPages) // IN
+{
+   uint32 status;
+   Backdoor_proto bp;
+
+   /* prepare backdoor args */
+   bp.in.cx.halfs.low = BALLOON_BDOOR_CMD_BATCHED_LOCK;
+   bp.in.size = (size_t)ppn;
+   bp.in.si.word = nPages;
+
+   /* invoke backdoor */
+   BackdoorBalloon(&bp);
+
+   /* parse return values */
+   status = bp.out.ax.word;
+
+   /* set flag if reset requested */
+   if (status == BALLOON_ERROR_RESET) {
+      b->resetFlag = 1;
+   }
+
+   /* update stats */
+   STATS_INC(b->stats.lock);
+   if (status != BALLOON_SUCCESS) {
+      STATS_INC(b->stats.lockFail);
+   }
+
+   return status;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Backdoor_MonitorUnlockPagesBatched --
+ *
+ *      Unballoon all PPNs listed in the batch page.
+ *
+ * Results:
+ *      Returns BALLOON_SUCCESS if successful, otherwise error code.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Backdoor_MonitorUnlockPagesBatched(Balloon *b,          // IN
+                                   PPN64 ppn,           // IN
+                                   uint32 nPages)       // IN
+{
+   uint32 status;
+   Backdoor_proto bp;
+
+   /* prepare backdoor args */
+   bp.in.cx.halfs.low = BALLOON_BDOOR_CMD_BATCHED_UNLOCK;
+   bp.in.size = (size_t)ppn;
+   bp.in.si.word = nPages;
+
+   /* invoke backdoor */
+   BackdoorBalloon(&bp);
+
+   /* parse return values */
+   status = bp.out.ax.word;
+
+   /* set flag if reset requested */
+   if (status == BALLOON_ERROR_RESET) {
+      b->resetFlag = 1;
+   }
+
+   /* update stats */
+   STATS_INC(b->stats.unlock);
+   if (status != BALLOON_SUCCESS) {
+      STATS_INC(b->stats.unlockFail);
+   }
+
+   return status;
+}
index 724ffd832298bdb6907ddc681fae10f2e6396571..3cb53296a77be59eebc1046563a89e434e4b6b8f 100644 (file)
@@ -77,5 +77,7 @@ int Backdoor_MonitorGuestType(Balloon *b);
 int Backdoor_MonitorGetTarget(Balloon *b, uint32 *target);
 int Backdoor_MonitorLockPage(Balloon *b, PPN64 ppn);
 int Backdoor_MonitorUnlockPage(Balloon *b, PPN64 ppn);
+int Backdoor_MonitorLockPagesBatched(Balloon *b, PPN64 ppn, uint32 nPages);
+int Backdoor_MonitorUnlockPagesBatched(Balloon *b, PPN64 ppn, uint32 nPages);
 
 #endif /* _BACKDOOR_BALLOON_H_ */
index 9ffc54b0996a0d036583166e1e8cf396bddad443..facca9ebecfb7f32acfb8bd6910200c2e02aa5f7 100644 (file)
 #define BALLOON_NAME_VERBOSE            "VMware memory control driver"
 
 #if defined __linux__ || defined __FreeBSD__ || defined _WIN32
-#define BALLOON_PROTOCOL_VERSION        BALLOON_PROTOCOL_VERSION_3
+/*
+ * FIXME: Even if the driver support batched commands keep using the
+ * non-batched one until more testing has been done.
+ */
+#define BALLOON_CAPABILITIES    BALLOON_BASIC_CMDS
 #else
-#define BALLOON_PROTOCOL_VERSION        BALLOON_PROTOCOL_VERSION_2
+#define BALLOON_CAPABILITIES    BALLOON_BASIC_CMDS
 #endif
 
 #define BALLOON_RATE_ADAPT      1
 #define        STATS_DEC(stat)
 #endif
 
+#define PPN_2_PA(_ppn)  ((_ppn) << PAGE_SHIFT)
+#define PA_2_PPN(_pa)   ((_pa) >> PAGE_SHIFT)
+
 #endif /* !BALLOONINT_H_ */
index da607bee46e7c853260322c5a21267a18f90c624..ef870cdad6db6a92b41126895c9d8cae54e8808e 100644 (file)
@@ -59,7 +59,7 @@
  *********************************************************/
 
 /*
- * balloon_def.h -- 
+ * balloon_def.h --
  *
  *      Definitions for server "balloon" mechanism for reclaiming
  *      physical memory from a VM.
  * constants
  */
 
-/* protocol versions */
-#define BALLOON_PROTOCOL_VERSION_2      (2)
-#define BALLOON_PROTOCOL_VERSION_3      (3)
-
 /* backdoor port */
 #define BALLOON_BDOOR_PORT              (0x5670)
 #define BALLOON_BDOOR_MAGIC             (0x456c6d6f)
 /*
  * Backdoor commands availability:
  *
- * +====================+===============+
- * |    CMD             |   Protocol    |
- * +--------------------+---------------+
- * | START              |      2 (*)    |
- * | TARGET             |      2        |
- * | LOCK               |      2 (*)    |
- * | UNLOCK             |      2 (*)    |
- * | GUEST_ID           |      2        |
- * +====================+===============+
- *
- * (*) The START, LOCK and UNLOCK has been slightly modified when
- * protocol v3 is used:
- *  - START now returns BALLOON_SUCCESS_WITH_VERSION, with the protocol
- *    version stored in %ecx, only if guest also support protocol v3 or
- *    up.
- *  - LOCK and UNLOCK are now taking a PPN of a page that contains a
- *    BalloonBatchPage, instead of directly taking the PPN to
- *    lock/unlock.
+ * +====================+======================+
+ * |    CMD             | Capabilities         |
+ * +--------------------+----------------------+
+ * | START              | Always available (*) |
+ * | TARGET             | Always available     |
+ * | LOCK               | BASIC_CMDS           |
+ * | UNLOCK             | BASIC_CMDS           |
+ * | GUEST_ID           | Always available     |
+ * | BATCHED_LOCK       | BATCHED_CMDS         |
+ * | BATCHED_UNLOCK     | BATCHED_CMDS         |
+ * +====================+======================+
+ *
+ * (*) The START command has been slightly modified when more than the
+ * basic commands are available: It returns
+ * BALLOON_SUCCESS_WITH_CAPABILITIES with the available capabilities
+ * stored in %ecx. Previously, a versioned protocol was used, and the
+ * protocol that should be used was also returned in %ecx. Protocol
+ * version 2 was the initial version and the only one shipped. Version 3
+ * was temporary used internally but has caused several issue due to
+ * protocol mismatch between monitor and guest.
  *
  */
 
 /* backdoor command numbers */
-#define BALLOON_BDOOR_CMD_START         (0)
-#define BALLOON_BDOOR_CMD_TARGET        (1)
-#define BALLOON_BDOOR_CMD_LOCK          (2)
-#define BALLOON_BDOOR_CMD_UNLOCK        (3)
-#define BALLOON_BDOOR_CMD_GUEST_ID      (4)
+#define BALLOON_BDOOR_CMD_START          (0)
+#define BALLOON_BDOOR_CMD_TARGET         (1)
+#define BALLOON_BDOOR_CMD_LOCK           (2)
+#define BALLOON_BDOOR_CMD_UNLOCK         (3)
+#define BALLOON_BDOOR_CMD_GUEST_ID       (4)
+/* The command 5 was shortly used between 1881144 and 1901153. */
+#define BALLOON_BDOOR_CMD_BATCHED_LOCK   (6)
+#define BALLOON_BDOOR_CMD_BATCHED_UNLOCK (7)
+
+/* balloon capabilities */
+typedef enum {
+   /*
+    * Bit 0 is not used and shouldn't be used, due to issue with
+    * protocol v3, to avoid ambiguity between protocol v3 and
+    * capabilities, leave this bit as 0. That way, by masking guest
+    * capabilities with monitor capabilities, bit 0 will always be set
+    * to 0, and buggy v3 tool will automatically switch to unbatched
+    * LOCK and UNLOCK.
+    */
+   BALLOON_BASIC_CMDS           = (1 << 1),
+   BALLOON_BATCHED_CMDS         = (1 << 2)
+} BalloonCapabilities;
 
 /* use config value for max balloon size */
 #define BALLOON_MAX_SIZE_USE_CONFIG     (0)
@@ -141,113 +156,56 @@ typedef enum {
 } BalloonGuest;
 
 /* error codes */
-#define BALLOON_SUCCESS                 (0)
-#define BALLOON_FAILURE                (-1)
-#define BALLOON_ERROR_CMD_INVALID       (1)
-#define BALLOON_ERROR_PPN_INVALID       (2)
-#define BALLOON_ERROR_PPN_LOCKED        (3)
-#define BALLOON_ERROR_PPN_UNLOCKED      (4)
-#define BALLOON_ERROR_PPN_PINNED        (5)
-#define BALLOON_ERROR_PPN_NOTNEEDED     (6)
-#define BALLOON_ERROR_RESET             (7)
-#define BALLOON_ERROR_BUSY              (8)
-/*
- * Sent on CMD_START to inform the guest to use the protocol v3 or
- * higher.
- */
-#define BALLOON_SUCCESS_WITH_VERSION     (0x03000000)
+#define BALLOON_SUCCESS                         (0)
+#define BALLOON_FAILURE                        (-1)
+#define BALLOON_ERROR_CMD_INVALID               (1)
+#define BALLOON_ERROR_PPN_INVALID               (2)
+#define BALLOON_ERROR_PPN_LOCKED                (3)
+#define BALLOON_ERROR_PPN_UNLOCKED              (4)
+#define BALLOON_ERROR_PPN_PINNED                (5)
+#define BALLOON_ERROR_PPN_NOTNEEDED             (6)
+#define BALLOON_ERROR_RESET                     (7)
+#define BALLOON_ERROR_BUSY                      (8)
+
+#define BALLOON_SUCCESS_WITH_CAPABILITIES       (0x03000000)
 
 /*
  * BatchPage.
  */
-#define BALLOON_BATCH_MAX_PAGES         \
-   ((PAGE_SIZE - sizeof(uint64)) / sizeof(PPN64))
-
-#define BALLOON_BATCH_STATUS_SHIFT      56
-
-typedef struct BalloonBatchPage {
-   uint64 nPages;
-   PPN64 pages[BALLOON_BATCH_MAX_PAGES];
-} BalloonBatchPage;
-
+#define BALLOON_BATCH_MAX_PAGES         (PAGE_SIZE / sizeof(PA64))
 
 /*
- *-----------------------------------------------------------------------------
+ * We are using the fact that for 4k pages, the 12LSB are set to 0, so
+ * we can use them and mask those bit when we need the real PA.
  *
- * Balloon_BatchInit --
+ * +=============+==========+========+
+ * |             |          |        |
+ * | Page number | Reserved | Status |
+ * |             |          |        |
+ * +=============+==========+========+
+ * 64  PAGE_SHIFT          6         0
  *
- * Results:
- *      Return the number of pages that can be embedded inside the batch
- *      page. If the protocol does not support batching, return 0.
+ * For now, only 4k pages are supported by the monitor, but by using
+ * reserved bit we can in the future add some flags that will indicate
+ * whether the page is a 2M page or a 1G page.
  *
- * Side effects:
- *      None.
+ * The reserved field should be set to 0.
  *
- *-----------------------------------------------------------------------------
  */
-static INLINE uint16
-Balloon_BatchInit(uint32 protoVersion)  // IN
-{
-   switch (protoVersion) {
-   case BALLOON_PROTOCOL_VERSION_3:
-      return BALLOON_BATCH_MAX_PAGES;
-   case BALLOON_PROTOCOL_VERSION_2:
-   default:
-      return 0;
-   }
-}
 
 
-/*
- *-----------------------------------------------------------------------------
- *
- * Balloon_BatchGetNumPages --
- *
- *      Return the number of pages contained in the batch page.
- *
- * Results:
- *      See above.
- *
- * Side effects:
- *      None.
- *
- *-----------------------------------------------------------------------------
- */
-static INLINE uint64
-Balloon_BatchGetNumPages(BalloonBatchPage *batchPage)    // IN
-{
-   return batchPage->nPages;
-}
+#define BALLOON_BATCH_STATUS_MASK       MASK64(5)
+#define BALLOON_BATCH_PAGE_MASK         (~MASK64(PAGE_SHIFT))
 
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Balloon_BatchSetNumPages --
- *
- *      Set the number of pages contained in the batch page.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      None.
- *
- *-----------------------------------------------------------------------------
- */
-static INLINE void
-Balloon_BatchSetNumPages(BalloonBatchPage *batchPage,      // IN
-                         uint64 nPages)                    // IN
-{
-   ASSERT(nPages <= BALLOON_BATCH_MAX_PAGES);
-   batchPage->nPages = nPages;
-}
+typedef struct BalloonBatchPage {
+   PA64 pages[BALLOON_BATCH_MAX_PAGES];
+} BalloonBatchPage;
 
 
 /*
  *-----------------------------------------------------------------------------
  *
- * Balloon_BatchGetPPN --
+ * Balloon_BatchGetPA --
  *
  *      Get the page stored in the batch page at idx.
  *
@@ -259,12 +217,12 @@ Balloon_BatchSetNumPages(BalloonBatchPage *batchPage,      // IN
  *
  *-----------------------------------------------------------------------------
  */
-static INLINE PPN64
-Balloon_BatchGetPPN(BalloonBatchPage *batchPage,          // IN
-                    uint16 idx)                           // IN
+static INLINE PA64
+Balloon_BatchGetPA(BalloonBatchPage *batchPage,         // IN
+                   uint16 idx)                          // IN
 {
-   ASSERT(idx < batchPage->nPages);
-   return batchPage->pages[idx] & MASK64(BALLOON_BATCH_STATUS_SHIFT);
+   ASSERT(idx < BALLOON_BATCH_MAX_PAGES);
+   return batchPage->pages[idx] & BALLOON_BATCH_PAGE_MASK;
 }
 
 
@@ -287,15 +245,15 @@ static INLINE uint8
 Balloon_BatchGetStatus(BalloonBatchPage *batchPage,     // IN
                        uint16 idx)                      // IN
 {
-   ASSERT(idx < batchPage->nPages);
-   return (uint8)(batchPage->pages[idx] >> BALLOON_BATCH_STATUS_SHIFT);
+   ASSERT(idx < BALLOON_BATCH_MAX_PAGES);
+   return (uint8)(batchPage->pages[idx] & BALLOON_BATCH_STATUS_MASK);
 }
 
 
 /*
  *-----------------------------------------------------------------------------
  *
- * Balloon_BatchSetPPN --
+ * Balloon_BatchSetPA --
  *
  *      Store the page in the batch page at idx.
  *
@@ -308,12 +266,13 @@ Balloon_BatchGetStatus(BalloonBatchPage *batchPage,     // IN
  *-----------------------------------------------------------------------------
  */
 static INLINE void
-Balloon_BatchSetPPN(BalloonBatchPage *batchPage,           // IN
-                    uint16 idx,                            // IN
-                    PPN64 ppn)                             // IN
+Balloon_BatchSetPA(BalloonBatchPage *batchPage,            // IN
+                   uint16 idx,                             // IN
+                   PA64 pa)                                // IN
 {
    ASSERT(idx < BALLOON_BATCH_MAX_PAGES);
-   batchPage->pages[idx] = ppn;
+   ASSERT((pa & ~BALLOON_BATCH_PAGE_MASK) == 0);
+   batchPage->pages[idx] = pa;
 }
 
 
@@ -337,12 +296,10 @@ Balloon_BatchSetStatus(BalloonBatchPage *batchPage,      // IN
                        uint16 idx,                       // IN
                        int error)                        // IN
 {
-   PPN64 ppn;
-
+   PA64 pa = Balloon_BatchGetPA(batchPage, idx);
    ASSERT(idx < BALLOON_BATCH_MAX_PAGES);
-   ppn = Balloon_BatchGetPPN(batchPage, idx);
-   ppn |=  ((PPN64)error << BALLOON_BATCH_STATUS_SHIFT);
-   batchPage->pages[idx] = ppn;
+   ASSERT(error <= BALLOON_ERROR_BUSY && error >= BALLOON_FAILURE);
+   batchPage->pages[idx] = pa | (PPN64)error;
 }
 
 MY_ASSERTS(BALLOON_BATCH_SIZE,
index 2f3fe29db8d243105ba5aecce9529ef482c6676f..9ef96979277df62d39bd6e3b37231b993ca1e360 100644 (file)
@@ -93,8 +93,8 @@ extern void OS_Free(void *ptr, size_t size);
 extern void OS_Yield(void);
 
 extern unsigned long OS_ReservedPageGetLimit(void);
-extern PPN64         OS_ReservedPageGetPPN(PageHandle handle);
-extern PageHandle    OS_ReservedPageGetHandle(PPN64 ppn);
+extern PA64          OS_ReservedPageGetPA(PageHandle handle);
+extern PageHandle    OS_ReservedPageGetHandle(PA64 pa);
 extern PageHandle    OS_ReservedPageAlloc(int canSleep);
 extern void          OS_ReservedPageFree(PageHandle handle);
 
index 2674bbb294680d7231819a7d27194dbd29c86135..15b56df294e6b4fc58ce6bc4adc1f001458c1ac9 100644 (file)
@@ -109,12 +109,12 @@ static int  BalloonPageFree(Balloon *b);
 static int  BalloonAdjustSize(Balloon *b, uint32 target);
 static void BalloonReset(Balloon *b);
 
-static void BalloonAddPagev2(Balloon *b, uint16 idx, PageHandle page);
-static void BalloonAddPagev3(Balloon *b, uint16 idx, PageHandle page);
-static int  BalloonLockv2(Balloon *b, uint16 nPages);
-static int  BalloonLockv3(Balloon *b, uint16 nPages);
-static int  BalloonUnlockv2(Balloon *b, uint16 nPages);
-static int  BalloonUnlockv3(Balloon *b, uint16 nPages);
+static void BalloonAddPage(Balloon *b, uint16 idx, PageHandle page);
+static void BalloonAddPageBatched(Balloon *b, uint16 idx, PageHandle page);
+static int  BalloonLock(Balloon *b, uint16 nPages);
+static int  BalloonLockBatched(Balloon *b, uint16 nPages);
+static int  BalloonUnlock(Balloon *b, uint16 nPages);
+static int  BalloonUnlockBatched(Balloon *b, uint16 nPages);
 
 /*
  * Globals
@@ -122,16 +122,16 @@ static int  BalloonUnlockv3(Balloon *b, uint16 nPages);
 
 static Balloon globalBalloon;
 
-static const BalloonOps balloonOpsv2 = {
-   .addPage = BalloonAddPagev2,
-   .lock = BalloonLockv2,
-   .unlock = BalloonUnlockv2
+static const BalloonOps balloonOps = {
+   .addPage = BalloonAddPage,
+   .lock = BalloonLock,
+   .unlock = BalloonUnlock
 };
 
-static const struct BalloonOps balloonOpsv3 = {
-   .addPage = BalloonAddPagev3,
-   .lock = BalloonLockv3,
-   .unlock = BalloonUnlockv3
+static const struct BalloonOps balloonOpsBatched = {
+   .addPage = BalloonAddPageBatched,
+   .lock = BalloonLockBatched,
+   .unlock = BalloonUnlockBatched
 };
 
 /*
@@ -178,7 +178,7 @@ Balloon_GetStats(void)
  * BalloonChunk_Create --
  *
  *      Creates a new BalloonChunk object capable of tracking
- *      BALLOON_CHUNK_PAGES PPNs.
+ *      BALLOON_CHUNK_PAGES PAs.
  *
  *      We do not bother to define two versions (NOSLEEP and CANSLEEP)
  *      of OS_Malloc because Chunk_Create does not require a new page
@@ -268,17 +268,15 @@ Balloon_Deallocate(Balloon *b) // IN
    }
 
    /* Release the batch page */
-   if (b->hypervisorProtocolVersion > BALLOON_PROTOCOL_VERSION_2) {
-      if (b->batchPageMapping != MAPPING_INVALID) {
-         OS_UnmapPage(b->batchPageMapping);
-         b->batchPageMapping = MAPPING_INVALID;
-         b->batchPage = NULL;
-      }
+   if (b->batchPageMapping != MAPPING_INVALID) {
+      OS_UnmapPage(b->batchPageMapping);
+      b->batchPageMapping = MAPPING_INVALID;
+      b->batchPage = NULL;
+   }
 
-      if (b->pageHandle != PAGE_HANDLE_INVALID) {
-         OS_ReservedPageFree(b->pageHandle);
-         b->pageHandle = PAGE_HANDLE_INVALID;
-      }
+   if (b->pageHandle != PAGE_HANDLE_INVALID) {
+      OS_ReservedPageFree(b->pageHandle);
+      b->pageHandle = PAGE_HANDLE_INVALID;
    }
 }
 
@@ -301,8 +299,7 @@ Balloon_Deallocate(Balloon *b) // IN
 static int
 BalloonInitBatching(Balloon *b) // IN
 {
-   b->batchMaxPages = Balloon_BatchInit(b->hypervisorProtocolVersion);
-   ASSERT(b->batchMaxPages != 0);
+   b->batchMaxPages = BALLOON_BATCH_MAX_PAGES;
 
    b->pageHandle = OS_ReservedPageAlloc(BALLOON_PAGE_ALLOC_NOSLEEP);
    if (b->pageHandle == PAGE_HANDLE_INVALID) {
@@ -346,30 +343,30 @@ BalloonReset(Balloon *b) // IN
    /* free all pages, skipping monitor unlock */
    Balloon_Deallocate(b);
 
-   status = Backdoor_MonitorStart(b, BALLOON_PROTOCOL_VERSION);
+   status = Backdoor_MonitorStart(b, BALLOON_CAPABILITIES);
    if (status != BALLOON_SUCCESS) {
       return;
    }
 
-   if (b->hypervisorProtocolVersion > BALLOON_PROTOCOL_VERSION_2) {
+   if ((b->hypervisorCapabilities & BALLOON_BATCHED_CMDS) != 0) {
       status = BalloonInitBatching(b);
       if (status != BALLOON_SUCCESS) {
-         status = Backdoor_MonitorStart(b, BALLOON_PROTOCOL_VERSION_2);
-         if (status != BALLOON_SUCCESS) {
-            return;
-         }
+         /*
+          * We failed to initialize the batching in the guest, inform
+          * the monitor about that by sending a null capability.
+          *
+          * The guest will retry to init itself in one second.
+          */
+         Backdoor_MonitorStart(b, 0);
+         return;
       }
    }
 
-   switch (b->hypervisorProtocolVersion) {
-   case BALLOON_PROTOCOL_VERSION_3:
-      b->balloonOps = &balloonOpsv3;
-      break;
-   case BALLOON_PROTOCOL_VERSION_2:
-   default:
-      b->balloonOps = &balloonOpsv2;
+   if ((b->hypervisorCapabilities & BALLOON_BATCHED_CMDS) != 0) {
+      b->balloonOps = &balloonOpsBatched;
+   } else if ((b->hypervisorCapabilities & BALLOON_BASIC_CMDS) != 0) {
+      b->balloonOps = &balloonOps;
       b->batchMaxPages = 1;
-      break;
    }
 
    /* clear flag */
@@ -778,10 +775,10 @@ BalloonInflate(Balloon *b,      // IN
 /*
  *----------------------------------------------------------------------
  *
- * BalloonLockv3 --
+ * BalloonLockBatched --
  *
  *      Lock all the batched page, previously stored by
- *      BalloonAddPagev3.
+ *      BalloonAddPageBatched.
  *
  * Results:
  *      BALLOON_SUCCESS or an error code.
@@ -792,8 +789,8 @@ BalloonInflate(Balloon *b,      // IN
  *----------------------------------------------------------------------
  */
 static int
-BalloonLockv3(Balloon *b,       // IN
-              uint16 nPages)    // IN
+BalloonLockBatched(Balloon *b,       // IN
+                   uint16 nPages)    // IN
 {
    int          status;
    uint32       i;
@@ -802,8 +799,7 @@ BalloonLockv3(Balloon *b,       // IN
    PPN64        batchPagePPN;
    BalloonChunk *chunk = NULL;
 
-   Balloon_BatchSetNumPages(b->batchPage, nPages);
-   batchPagePPN = OS_ReservedPageGetPPN(b->pageHandle);
+   batchPagePPN = PA_2_PPN(OS_ReservedPageGetPA(b->pageHandle));
 
    /*
     * Make sure that we will always have an available chunk before doing
@@ -814,13 +810,13 @@ BalloonLockv3(Balloon *b,       // IN
    if (b->fallbackChunk == NULL) {
       status = BALLOON_PAGE_ALLOC_FAILURE;
    } else {
-      status = Backdoor_MonitorLockPage(b, batchPagePPN);
+      status = Backdoor_MonitorLockPagesBatched(b, batchPagePPN, nPages);
    }
 
    if (status != BALLOON_SUCCESS) {
       for (i = 0; i < nPages; i++) {
-         PPN64 ppn = Balloon_BatchGetPPN(b->batchPage, i);
-         handle = OS_ReservedPageGetHandle(ppn);
+         PA64 pa = Balloon_BatchGetPA(b->batchPage, i);
+         handle = OS_ReservedPageGetHandle(pa);
 
          OS_ReservedPageFree(handle);
       }
@@ -830,11 +826,11 @@ BalloonLockv3(Balloon *b,       // IN
 
    nLockedPages = 0;
    for (i = 0; i < nPages; i++) {
-      PPN64             ppn;
+      PA64              pa;
       int               error;
 
-      ppn = Balloon_BatchGetPPN(b->batchPage, i);
-      handle = OS_ReservedPageGetHandle(ppn);
+      pa = Balloon_BatchGetPA(b->batchPage, i);
+      handle = OS_ReservedPageGetHandle(pa);
       error = Balloon_BatchGetStatus(b->batchPage, i);
       if (error != BALLOON_SUCCESS) {
          switch (error) {
@@ -885,10 +881,10 @@ out:
 /*
  *----------------------------------------------------------------------
  *
- * BalloonUnlockv3 --
+ * BalloonUnlockBatched --
  *
  *      Unlock all the batched page, previously stored by
- *      BalloonAddPagev3.
+ *      BalloonAddPageBatched.
  *
  * Results:
  *      BALLOON_SUCCESS or an error code.
@@ -899,8 +895,8 @@ out:
  *----------------------------------------------------------------------
  */
 static int
-BalloonUnlockv3(Balloon *b,     // IN
-                uint16 nPages)  // IN
+BalloonUnlockBatched(Balloon *b,     // IN
+                     uint16 nPages)  // IN
 {
    uint32 i;
    int status = BALLOON_SUCCESS;
@@ -908,14 +904,13 @@ BalloonUnlockv3(Balloon *b,     // IN
    PPN64 batchPagePPN;
    BalloonChunk *chunk = NULL;
 
-   Balloon_BatchSetNumPages(b->batchPage, nPages);
-   batchPagePPN = OS_ReservedPageGetPPN(b->pageHandle);
-   status = Backdoor_MonitorUnlockPage(b, batchPagePPN);
+   batchPagePPN = PA_2_PPN(OS_ReservedPageGetPA(b->pageHandle));
+   status = Backdoor_MonitorUnlockPagesBatched(b, batchPagePPN, nPages);
 
    if (status != BALLOON_SUCCESS) {
       for (i = 0; i < nPages; i++) {
-         PPN64 ppn = Balloon_BatchGetPPN(b->batchPage, i);
-         PageHandle handle = OS_ReservedPageGetHandle(ppn);
+         PA64 pa = Balloon_BatchGetPA(b->batchPage, i);
+         PageHandle handle = OS_ReservedPageGetHandle(pa);
 
          chunk = BalloonGetChunkOrFallback(b);
          BalloonPageStore(chunk, handle);
@@ -926,8 +921,8 @@ BalloonUnlockv3(Balloon *b,     // IN
    nUnlockedPages = 0;
    for (i = 0; i < nPages; i++) {
       int status = Balloon_BatchGetStatus(b->batchPage, i);
-      PPN64 ppn = Balloon_BatchGetPPN(b->batchPage, i);
-      PageHandle handle = OS_ReservedPageGetHandle(ppn);
+      PA64 pa = Balloon_BatchGetPA(b->batchPage, i);
+      PageHandle handle = OS_ReservedPageGetHandle(pa);
 
       if (status != BALLOON_SUCCESS) {
          chunk = BalloonGetChunkOrFallback(b);
@@ -954,7 +949,7 @@ out:
 /*
  *----------------------------------------------------------------------
  *
- * BalloonAddPagev3 --
+ * BalloonAddPageBatched --
  *
  *      Add a page to the batch page, that will be ballooned later.
  *
@@ -968,20 +963,20 @@ out:
  */
 
 static void
-BalloonAddPagev3(Balloon *b,            // IN
-                 uint16 idx,            // IN
-                 PageHandle page)       // IN
+BalloonAddPageBatched(Balloon *b,            // IN
+                      uint16 idx,            // IN
+                      PageHandle page)       // IN
 {
-   PPN64 ppn = OS_ReservedPageGetPPN(page);
-   Balloon_BatchSetPPN(b->batchPage, idx, ppn);
+   PA64 pa = OS_ReservedPageGetPA(page);
+   Balloon_BatchSetPA(b->batchPage, idx, pa);
 }
 
 /*
  *----------------------------------------------------------------------
  *
- * Balloonlockv2 --
+ * BalloonLock --
  *
- *      Lock a page, previously stored with a call to BalloonAddPagev2,
+ *      Lock a page, previously stored with a call to BalloonAddPage,
  *      by notifying the monitor.
  *
  * Results:
@@ -994,8 +989,8 @@ BalloonAddPagev3(Balloon *b,            // IN
  */
 
 static int
-BalloonLockv2(Balloon *b,       // IN
-              uint16 nPages)    // IN
+BalloonLock(Balloon *b,       // IN
+            uint16 nPages)    // IN
 {
    PPN pagePPN;
    BalloonChunk *chunk;
@@ -1009,7 +1004,7 @@ BalloonLockv2(Balloon *b,       // IN
    }
 
    /* inform monitor via backdoor */
-   pagePPN = OS_ReservedPageGetPPN(b->pageHandle);
+   pagePPN = PA_2_PPN(OS_ReservedPageGetPA(b->pageHandle));
    status = Backdoor_MonitorLockPage(b, pagePPN);
    if (status != BALLOON_SUCCESS) {
       int old_status = status;
@@ -1042,10 +1037,10 @@ BalloonLockv2(Balloon *b,       // IN
 /*
  *----------------------------------------------------------------------
  *
- * BalloonUnlockv2 --
+ * BalloonUnlock --
  *
  *      Unlock a page, previously stored with a call to
- *      BalloonAddPagev2, by notifying the monitor.
+ *      BalloonAddPage, by notifying the monitor.
  *
  * Results:
  *      BALLOON_SUCCESS or an error code.
@@ -1057,10 +1052,10 @@ BalloonLockv2(Balloon *b,       // IN
  */
 
 static int
-BalloonUnlockv2(Balloon *b,     // IN
-                uint16 nPages)  // IN
+BalloonUnlock(Balloon *b,     // IN
+              uint16 nPages)  // IN
 {
-   PPN pagePPN = OS_ReservedPageGetPPN(b->pageHandle);
+   PPN pagePPN = PA_2_PPN(OS_ReservedPageGetPA(b->pageHandle));
    int status = Backdoor_MonitorUnlockPage(b, pagePPN);
 
    if (status != BALLOON_SUCCESS) {
@@ -1083,7 +1078,7 @@ out:
 /*
  *----------------------------------------------------------------------
  *
- * BalloonAddPagev2 --
+ * BalloonAddPage --
  *
  *      Add a page to be ballooned later.
  *
@@ -1097,9 +1092,9 @@ out:
  */
 
 static void
-BalloonAddPagev2(Balloon *b,            // IN
-                 uint16 idx,            // IN
-                 PageHandle page)       // IN
+BalloonAddPage(Balloon *b,            // IN
+               uint16 idx,            // IN
+               PageHandle page)       // IN
 {
    b->pageHandle = page;
 }
@@ -1288,7 +1283,7 @@ Balloon_Cleanup(void)
     * Reset connection before deallocating memory to avoid potential for
     * additional spurious resets from guest touching deallocated pages.
     */
-   Backdoor_MonitorStart(b, BALLOON_PROTOCOL_VERSION);
+   Backdoor_MonitorStart(b, BALLOON_CAPABILITIES);
    Balloon_Deallocate(b);
 }
 
index c859f4595de703da5bda6339e4d94e215f87f39c..c8d5f0edeb9adb844db3711843955711082bd8e3 100644 (file)
@@ -160,10 +160,10 @@ typedef struct {
    /* statistics */
    BalloonStats stats;
 
-   /* balloon protocol to use */
-   uint32 hypervisorProtocolVersion;
+   /* hypervisor exposed capabilities */
+   BalloonCapabilities hypervisorCapabilities;
 
-   /* balloon operations, tied to the protocol version */
+   /* balloon operations, tied to the capabilities */
    const struct BalloonOps *balloonOps;
 
    /* Either the batch page handle, or the page to lock on v2 */
index daf8a617d784bc7b13ccbbd9214908aa1fe80863..93b762263b29fccc8fbb408e94731c69f42469a7 100644 (file)
@@ -221,13 +221,13 @@ OS_ReservedPageGetLimit(void)
 /*
  *-----------------------------------------------------------------------------
  *
- * OS_ReservedPageGetPPN --
+ * OS_ReservedPageGetPA --
  *
  *      Convert a page handle (of a physical page previously reserved with
- *      OS_ReservedPageAlloc()) to a ppn.
+ *      OS_ReservedPageAlloc()) to a pa.
  *
  * Results:
- *      The ppn.
+ *      The pa.
  *
  * Side effects:
  *      None.
@@ -235,10 +235,10 @@ OS_ReservedPageGetLimit(void)
  *-----------------------------------------------------------------------------
  */
 
-PPN64
-OS_ReservedPageGetPPN(PageHandle handle) // IN: A valid page handle
+PA64
+OS_ReservedPageGetPA(PageHandle handle) // IN: A valid page handle
 {
-   return page_pptonum(((os_page *)handle)->pp);
+   return ptob(page_pptonum(((os_page *)handle)->pp));
 }
 
 
@@ -247,7 +247,7 @@ OS_ReservedPageGetPPN(PageHandle handle) // IN: A valid page handle
  *
  * OS_ReservedPageGetHandle --
  *
- *      Convert a ppn (of a physical page previously reserved with
+ *      Convert a pa (of a physical page previously reserved with
  *      OS_ReservedPageAlloc()) to a page handle.
  *
  * Results:
@@ -263,9 +263,9 @@ OS_ReservedPageGetPPN(PageHandle handle) // IN: A valid page handle
  */
 
 PageHandle
-OS_ReservedPageGetHandle(PPN64 ppn)     // IN
+OS_ReservedPageGetHandle(PA64 pa)     // IN
 {
-   // Solaris does not use protocol v3.
+   // Solaris does not use batched commands.
    NOT_IMPLEMENTED();
 }
 
@@ -293,7 +293,7 @@ OS_ReservedPageGetHandle(PPN64 ppn)     // IN
 Mapping
 OS_MapPageHandle(PageHandle handle)     // IN
 {
-   // Solaris does not use protocol v3.
+   // Solaris does not use batched commands.
    NOT_IMPLEMENTED();
 }
 
@@ -321,7 +321,7 @@ OS_MapPageHandle(PageHandle handle)     // IN
 void *
 OS_Mapping2Addr(Mapping mapping)        // IN
 {
-   // Solaris does not use protocol v3.
+   // Solaris does not use batched commands.
    NOT_IMPLEMENTED();
 }
 
@@ -381,7 +381,7 @@ OS_UnmapPage(Mapping mapping)   // IN
  *      eliminate some of this.
  *
  * Results:
- *      On success: A valid page handle that can be passed to OS_ReservedPageGetPPN()
+ *      On success: A valid page handle that can be passed to OS_ReservedPageGetPA()
  *                  or OS_ReservedPageFree().
  *      On failure: PAGE_HANDLE_INVALID
  *