#define VMW_BALLOON_CMD_BATCHED_2M_UNLOCK 9
#define VMW_BALLOON_CMD_VMCI_DOORBELL_SET 10
+#define VMW_BALLOON_CMD_NUM 11
/* error codes */
#define VMW_BALLOON_SUCCESS 0
(1UL << VMW_BALLOON_CMD_BATCHED_2M_LOCK) | \
(1UL << VMW_BALLOON_CMD_BATCHED_2M_UNLOCK))
+static const char * const vmballoon_cmd_names[] = {
+ [VMW_BALLOON_CMD_START] = "start",
+ [VMW_BALLOON_CMD_GET_TARGET] = "target",
+ [VMW_BALLOON_CMD_LOCK] = "lock",
+ [VMW_BALLOON_CMD_UNLOCK] = "unlock",
+ [VMW_BALLOON_CMD_GUEST_ID] = "guestType",
+ [VMW_BALLOON_CMD_BATCHED_LOCK] = "batchLock",
+ [VMW_BALLOON_CMD_BATCHED_UNLOCK] = "batchUnlock",
+ [VMW_BALLOON_CMD_BATCHED_2M_LOCK] = "2m-lock",
+ [VMW_BALLOON_CMD_BATCHED_2M_UNLOCK] = "2m-unlock",
+ [VMW_BALLOON_CMD_VMCI_DOORBELL_SET] = "doorbellSet"
+};
+
struct vmballoon_batch_page {
u64 pages[VMW_BALLOON_BATCH_MAX_PAGES];
};
unsigned int refused_free[VMW_BALLOON_NUM_PAGE_SIZES];
unsigned int free[VMW_BALLOON_NUM_PAGE_SIZES];
- /* monitor operations */
- 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;
- unsigned int start_fail;
- unsigned int guest_type;
- unsigned int guest_type_fail;
- unsigned int doorbell_set;
- unsigned int doorbell_unset;
+ /* Monitor operations. */
+ unsigned long ops[VMW_BALLOON_CMD_NUM];
+ unsigned long ops_fail[VMW_BALLOON_CMD_NUM];
};
#define STATS_INC(stat) (stat)++
{
unsigned long status, dummy1, dummy2, dummy3, local_result;
+ STATS_INC(b->stats.ops[cmd]);
+
asm volatile ("inl %%dx" :
"=a"(status),
"=c"(dummy1),
((1ul << cmd) & VMW_BALLOON_CMD_WITH_TARGET_MASK))
b->target = local_result;
+ if (status != VMW_BALLOON_SUCCESS &&
+ status != VMW_BALLOON_SUCCESS_WITH_CAPABILITIES) {
+ STATS_INC(b->stats.ops_fail[cmd]);
+ pr_debug("%s: %s [0x%lx,0x%lx) failed, returned %ld\n",
+ __func__, vmballoon_cmd_names[cmd], arg1, arg2,
+ status);
+ }
+
/* mark reset required accordingly */
if (status == VMW_BALLOON_ERROR_RESET)
b->reset_required = true;
unsigned long status, capabilities;
bool success;
- STATS_INC(b->stats.start);
-
status = __vmballoon_cmd(b, VMW_BALLOON_CMD_START, req_caps, 0,
&capabilities);
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;
}
status = vmballoon_cmd(b, VMW_BALLOON_CMD_GUEST_ID,
VMW_BALLOON_GUEST_ID, 0);
- STATS_INC(b->stats.guest_type);
-
if (status == VMW_BALLOON_SUCCESS)
return true;
- pr_debug("%s - failed, hv returns %ld\n", __func__, status);
- STATS_INC(b->stats.guest_type_fail);
return false;
}
if (limit != limit32)
return false;
- /* update stats */
- STATS_INC(b->stats.target);
-
status = vmballoon_cmd(b, VMW_BALLOON_CMD_GET_TARGET, limit, 0);
if (status == VMW_BALLOON_SUCCESS)
return true;
- pr_debug("%s - failed, hv returns %ld\n", __func__, status);
- STATS_INC(b->stats.target_fail);
return false;
}
if (pfn32 != pfn)
return -EINVAL;
- STATS_INC(b->stats.lock[false]);
-
*hv_status = status = vmballoon_cmd(b, VMW_BALLOON_CMD_LOCK, pfn, 0);
if (status == VMW_BALLOON_SUCCESS)
return 0;
- pr_debug("%s - ppn %lx, hv returns %ld\n", __func__, pfn, status);
- STATS_INC(b->stats.lock_fail[false]);
return -EIO;
}
unsigned long pfn = PHYS_PFN(virt_to_phys(b->batch_page));
unsigned long status, cmd;
- STATS_INC(b->stats.lock[is_2m_pages]);
-
cmd = is_2m_pages ? VMW_BALLOON_CMD_BATCHED_2M_LOCK :
VMW_BALLOON_CMD_BATCHED_LOCK;
if (status == VMW_BALLOON_SUCCESS)
return 0;
- pr_debug("%s - batch ppn %lx, hv returns %ld\n", __func__, pfn, status);
- STATS_INC(b->stats.lock_fail[is_2m_pages]);
return 1;
}
if (pfn32 != pfn)
return false;
- STATS_INC(b->stats.unlock[false]);
-
status = vmballoon_cmd(b, VMW_BALLOON_CMD_UNLOCK, pfn, 0);
- if (status == VMW_BALLOON_SUCCESS)
- return true;
-
- pr_debug("%s - ppn %lx, hv returns %ld\n", __func__, pfn, status);
- STATS_INC(b->stats.unlock_fail[false]);
- return false;
+ return status == VMW_BALLOON_SUCCESS;
}
static bool vmballoon_send_batched_unlock(struct vmballoon *b,
unsigned long pfn = PHYS_PFN(virt_to_phys(b->batch_page));
unsigned long status, cmd;
- STATS_INC(b->stats.unlock[is_2m_pages]);
-
cmd = is_2m_pages ? VMW_BALLOON_CMD_BATCHED_2M_UNLOCK :
VMW_BALLOON_CMD_BATCHED_UNLOCK;
status = vmballoon_cmd(b, cmd, pfn, num_pages);
- if (status == VMW_BALLOON_SUCCESS)
- return true;
-
- pr_debug("%s - batch ppn %lx, hv returns %ld\n", __func__, pfn, status);
- STATS_INC(b->stats.unlock_fail[is_2m_pages]);
- return false;
+ return status == VMW_BALLOON_SUCCESS;
}
static struct page *vmballoon_alloc_page(gfp_t flags, bool is_2m_page)
vmballoon_cmd(b, VMW_BALLOON_CMD_VMCI_DOORBELL_SET,
VMCI_INVALID_ID, VMCI_INVALID_ID);
- 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;
b->vmci_doorbell.context,
b->vmci_doorbell.resource, NULL);
- STATS_INC(b->stats.doorbell_set);
-
if (error != VMW_BALLOON_SUCCESS)
goto fail;
{
struct vmballoon *b = f->private;
struct vmballoon_stats *stats = &b->stats;
+ int i;
/* format capabilities info */
seq_printf(f,
"current: %8d pages\n",
b->target, b->size);
+ for (i = 0; i < VMW_BALLOON_CMD_NUM; i++) {
+ if (vmballoon_cmd_names[i] == NULL)
+ continue;
+
+ seq_printf(f, "%-22s: %16lu (%lu failed)\n",
+ vmballoon_cmd_names[i], stats->ops[i],
+ stats->ops_fail[i]);
+ }
+
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"
- "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"
"err2mAlloc: %8u\n"
"errAlloc: %8u\n"
"err2mFree: %8u\n"
- "errFree: %8u\n"
- "doorbellSet: %8u\n"
- "doorbellUnset: %8u\n",
+ "errFree: %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],
- 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[true], stats->alloc_fail[true],
stats->alloc[false], stats->alloc_fail[false],
stats->sleep_alloc, stats->sleep_alloc_fail,
stats->free[true],
stats->free[false],
stats->refused_alloc[true], stats->refused_alloc[false],
- stats->refused_free[true], stats->refused_free[false],
- stats->doorbell_set, stats->doorbell_unset);
+ stats->refused_free[true], stats->refused_free[false]);
return 0;
}