summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2013-05-10 02:59:49 +0000
committerneel <neel@FreeBSD.org>2013-05-10 02:59:49 +0000
commitc5e619b651d1ca95e1c461c940ab382e1b3a019e (patch)
treeabf6447962d8096447a14aa6d940742871e6d79d
parent4cfb7cf5acee479be43a8536626786afcc254dbe (diff)
downloadFreeBSD-src-c5e619b651d1ca95e1c461c940ab382e1b3a019e.zip
FreeBSD-src-c5e619b651d1ca95e1c461c940ab382e1b3a019e.tar.gz
Support array-type of stats in bhyve.
An array-type stat in vmm.ko is defined as follows: VMM_STAT_ARRAY(IPIS_SENT, VM_MAXCPU, "ipis sent to vcpu"); It is incremented as follows: vmm_stat_array_incr(vm, vcpuid, IPIS_SENT, array_index, 1); And output of 'bhyvectl --get-stats' looks like: ipis sent to vcpu[0] 3114 ipis sent to vcpu[1] 0 Reviewed by: grehan Obtained from: NetApp
-rw-r--r--sys/amd64/vmm/io/vlapic.c8
-rw-r--r--sys/amd64/vmm/vmm_dev.c11
-rw-r--r--sys/amd64/vmm/vmm_stat.c50
-rw-r--r--sys/amd64/vmm/vmm_stat.h40
4 files changed, 74 insertions, 35 deletions
diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c
index a56a36e..b6d2a3a 100644
--- a/sys/amd64/vmm/io/vlapic.c
+++ b/sys/amd64/vmm/io/vlapic.c
@@ -430,6 +430,8 @@ vlapic_fire_timer(struct vlapic *vlapic)
}
}
+static VMM_STAT_ARRAY(IPIS_SENT, VM_MAXCPU, "ipis sent to vcpu");
+
static int
lapic_process_icr(struct vlapic *vlapic, uint64_t icrval)
{
@@ -466,9 +468,11 @@ lapic_process_icr(struct vlapic *vlapic, uint64_t icrval)
while ((i = cpusetobj_ffs(&dmask)) != 0) {
i--;
CPU_CLR(i, &dmask);
- if (mode == APIC_DELMODE_FIXED)
+ if (mode == APIC_DELMODE_FIXED) {
lapic_set_intr(vlapic->vm, i, vec);
- else
+ vmm_stat_array_incr(vlapic->vm, vlapic->vcpuid,
+ IPIS_SENT, i, 1);
+ } else
vm_inject_nmi(vlapic->vm, i);
}
diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c
index 4a3c4cd..8c03b3e 100644
--- a/sys/amd64/vmm/vmm_dev.c
+++ b/sys/amd64/vmm/vmm_dev.c
@@ -235,18 +235,13 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
error = vm_run(sc->vm, vmrun);
break;
case VM_STAT_DESC: {
- const char *desc;
statdesc = (struct vm_stat_desc *)data;
- desc = vmm_stat_desc(statdesc->index);
- if (desc != NULL) {
- error = 0;
- strlcpy(statdesc->desc, desc, sizeof(statdesc->desc));
- } else
- error = EINVAL;
+ error = vmm_stat_desc_copy(statdesc->index,
+ statdesc->desc, sizeof(statdesc->desc));
break;
}
case VM_STATS: {
- CTASSERT(MAX_VM_STATS >= MAX_VMM_STAT_TYPES);
+ CTASSERT(MAX_VM_STATS >= MAX_VMM_STAT_ELEMS);
vmstats = (struct vm_stats *)data;
getmicrotime(&vmstats->tv);
error = vmm_stat_copy(sc->vm, vmstats->cpuid,
diff --git a/sys/amd64/vmm/vmm_stat.c b/sys/amd64/vmm/vmm_stat.c
index 2143d25..781fda5 100644
--- a/sys/amd64/vmm/vmm_stat.c
+++ b/sys/amd64/vmm/vmm_stat.c
@@ -39,8 +39,16 @@ __FBSDID("$FreeBSD$");
#include "vmm_util.h"
#include "vmm_stat.h"
-static int vstnum;
-static struct vmm_stat_type *vsttab[MAX_VMM_STAT_TYPES];
+/*
+ * 'vst_num_elems' is the total number of addressable statistic elements
+ * 'vst_num_types' is the number of unique statistic types
+ *
+ * It is always true that 'vst_num_elems' is greater than or equal to
+ * 'vst_num_types'. This is because a stat type may represent more than
+ * one element (for e.g. VMM_STAT_ARRAY).
+ */
+static int vst_num_elems, vst_num_types;
+static struct vmm_stat_type *vsttab[MAX_VMM_STAT_ELEMS];
static MALLOC_DEFINE(M_VMM_STAT, "vmm stat", "vmm stat");
@@ -59,13 +67,15 @@ vmm_stat_init(void *arg)
if (vst->scope == VMM_STAT_SCOPE_AMD && !vmm_is_amd())
return;
- if (vstnum >= MAX_VMM_STAT_TYPES) {
+ if (vst_num_elems + vst->nelems >= MAX_VMM_STAT_ELEMS) {
printf("Cannot accomodate vmm stat type \"%s\"!\n", vst->desc);
return;
}
- vst->index = vstnum;
- vsttab[vstnum++] = vst;
+ vst->index = vst_num_elems;
+ vst_num_elems += vst->nelems;
+
+ vsttab[vst_num_types++] = vst;
}
int
@@ -78,9 +88,9 @@ vmm_stat_copy(struct vm *vm, int vcpu, int *num_stats, uint64_t *buf)
return (EINVAL);
stats = vcpu_stats(vm, vcpu);
- for (i = 0; i < vstnum; i++)
+ for (i = 0; i < vst_num_elems; i++)
buf[i] = stats[i];
- *num_stats = vstnum;
+ *num_stats = vst_num_elems;
return (0);
}
@@ -89,7 +99,7 @@ vmm_stat_alloc(void)
{
u_long size;
- size = vstnum * sizeof(uint64_t);
+ size = vst_num_elems * sizeof(uint64_t);
return (malloc(size, M_VMM_STAT, M_ZERO | M_WAITOK));
}
@@ -100,14 +110,26 @@ vmm_stat_free(void *vp)
free(vp, M_VMM_STAT);
}
-const char *
-vmm_stat_desc(int index)
+int
+vmm_stat_desc_copy(int index, char *buf, int bufsize)
{
+ int i;
+ struct vmm_stat_type *vst;
+
+ for (i = 0; i < vst_num_types; i++) {
+ vst = vsttab[i];
+ if (index >= vst->index && index < vst->index + vst->nelems) {
+ if (vst->nelems > 1) {
+ snprintf(buf, bufsize, "%s[%d]",
+ vst->desc, index - vst->index);
+ } else {
+ strlcpy(buf, vst->desc, bufsize);
+ }
+ return (0); /* found it */
+ }
+ }
- if (index >= 0 && index < vstnum)
- return (vsttab[index]->desc);
- else
- return (NULL);
+ return (EINVAL);
}
/* global statistics */
diff --git a/sys/amd64/vmm/vmm_stat.h b/sys/amd64/vmm/vmm_stat.h
index 93c7e87..bc58113 100644
--- a/sys/amd64/vmm/vmm_stat.h
+++ b/sys/amd64/vmm/vmm_stat.h
@@ -34,7 +34,7 @@
struct vm;
-#define MAX_VMM_STAT_TYPES 64 /* arbitrary */
+#define MAX_VMM_STAT_ELEMS 64 /* arbitrary */
enum vmm_stat_scope {
VMM_STAT_SCOPE_ANY,
@@ -44,15 +44,16 @@ enum vmm_stat_scope {
struct vmm_stat_type {
int index; /* position in the stats buffer */
+ int nelems; /* standalone or array */
const char *desc; /* description of statistic */
enum vmm_stat_scope scope;
};
void vmm_stat_init(void *arg);
-#define VMM_STAT_DEFINE(type, desc, scope) \
+#define VMM_STAT_DEFINE(type, nelems, desc, scope) \
struct vmm_stat_type type[1] = { \
- { -1, desc, scope } \
+ { -1, nelems, desc, scope } \
}; \
SYSINIT(type##_stat, SI_SUB_KLD, SI_ORDER_ANY, vmm_stat_init, type)
@@ -60,11 +61,14 @@ void vmm_stat_init(void *arg);
extern struct vmm_stat_type type[1]
#define VMM_STAT(type, desc) \
- VMM_STAT_DEFINE(type, desc, VMM_STAT_SCOPE_ANY)
+ VMM_STAT_DEFINE(type, 1, desc, VMM_STAT_SCOPE_ANY)
#define VMM_STAT_INTEL(type, desc) \
- VMM_STAT_DEFINE(type, desc, VMM_STAT_SCOPE_INTEL)
+ VMM_STAT_DEFINE(type, 1, desc, VMM_STAT_SCOPE_INTEL)
#define VMM_STAT_AMD(type, desc) \
- VMM_STAT_DEFINE(type, desc, VMM_STAT_SCOPE_AMD)
+ VMM_STAT_DEFINE(type, 1, desc, VMM_STAT_SCOPE_AMD)
+
+#define VMM_STAT_ARRAY(type, nelems, desc) \
+ VMM_STAT_DEFINE(type, nelems, desc, VMM_STAT_SCOPE_ANY)
void *vmm_stat_alloc(void);
void vmm_stat_free(void *vp);
@@ -73,15 +77,29 @@ void vmm_stat_free(void *vp);
* 'buf' should be at least fit 'MAX_VMM_STAT_TYPES' entries
*/
int vmm_stat_copy(struct vm *vm, int vcpu, int *num_stats, uint64_t *buf);
-const char *vmm_stat_desc(int index);
+int vmm_stat_desc_copy(int index, char *buf, int buflen);
+
+static void __inline
+vmm_stat_array_incr(struct vm *vm, int vcpu, struct vmm_stat_type *vst,
+ int statidx, uint64_t x)
+{
+#ifdef VMM_KEEP_STATS
+ uint64_t *stats;
+
+ stats = vcpu_stats(vm, vcpu);
+
+ if (vst->index >= 0 && statidx < vst->nelems)
+ stats[vst->index + statidx] += x;
+#endif
+}
+
static void __inline
vmm_stat_incr(struct vm *vm, int vcpu, struct vmm_stat_type *vst, uint64_t x)
{
-#ifdef VMM_KEEP_STATS
- uint64_t *stats = vcpu_stats(vm, vcpu);
- if (vst->index >= 0)
- stats[vst->index] += x;
+
+#ifdef VMM_KEEP_STATS
+ vmm_stat_array_incr(vm, vcpu, vst, 0, x);
#endif
}
OpenPOWER on IntegriCloud