vmm_stat.c revision 270071
1117632Sharti/*-
2117632Sharti * Copyright (c) 2011 NetApp, Inc.
3117632Sharti * All rights reserved.
4117632Sharti *
5117632Sharti * Redistribution and use in source and binary forms, with or without
6117632Sharti * modification, are permitted provided that the following conditions
7117632Sharti * are met:
8117632Sharti * 1. Redistributions of source code must retain the above copyright
9117632Sharti *    notice, this list of conditions and the following disclaimer.
10117632Sharti * 2. Redistributions in binary form must reproduce the above copyright
11117632Sharti *    notice, this list of conditions and the following disclaimer in the
12117632Sharti *    documentation and/or other materials provided with the distribution.
13117632Sharti *
14117632Sharti * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
15117632Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16117632Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17117632Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
18117632Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19117632Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20117632Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21117632Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22117632Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23117632Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24117632Sharti * SUCH DAMAGE.
25117632Sharti *
26117632Sharti * $FreeBSD: stable/10/sys/amd64/vmm/vmm_stat.c 270071 2014-08-17 01:00:42Z grehan $
27117632Sharti */
28117632Sharti
29117632Sharti#include <sys/cdefs.h>
30117632Sharti__FBSDID("$FreeBSD: stable/10/sys/amd64/vmm/vmm_stat.c 270071 2014-08-17 01:00:42Z grehan $");
31117632Sharti
32117632Sharti#include <sys/param.h>
33117632Sharti#include <sys/kernel.h>
34117632Sharti#include <sys/systm.h>
35117632Sharti#include <sys/malloc.h>
36117632Sharti#include <sys/smp.h>
37117632Sharti
38117632Sharti#include <machine/vmm.h>
39117632Sharti#include "vmm_util.h"
40117632Sharti#include "vmm_stat.h"
41117632Sharti
42117632Sharti/*
43117632Sharti * 'vst_num_elems' is the total number of addressable statistic elements
44117632Sharti * 'vst_num_types' is the number of unique statistic types
45117632Sharti *
46117632Sharti * It is always true that 'vst_num_elems' is greater than or equal to
47117632Sharti * 'vst_num_types'. This is because a stat type may represent more than
48117632Sharti * one element (for e.g. VMM_STAT_ARRAY).
49117632Sharti */
50117632Shartistatic int vst_num_elems, vst_num_types;
51117632Shartistatic struct vmm_stat_type *vsttab[MAX_VMM_STAT_ELEMS];
52117632Sharti
53117632Shartistatic MALLOC_DEFINE(M_VMM_STAT, "vmm stat", "vmm stat");
54117632Sharti
55117632Sharti#define	vst_size	((size_t)vst_num_elems * sizeof(uint64_t))
56117632Sharti
57117632Shartivoid
58117632Shartivmm_stat_register(void *arg)
59117632Sharti{
60117632Sharti	struct vmm_stat_type *vst = arg;
61117632Sharti
62117632Sharti	/* We require all stats to identify themselves with a description */
63117632Sharti	if (vst->desc == NULL)
64117632Sharti		return;
65117632Sharti
66117632Sharti	if (vst->scope == VMM_STAT_SCOPE_INTEL && !vmm_is_intel())
67117632Sharti		return;
68117632Sharti
69117632Sharti	if (vst->scope == VMM_STAT_SCOPE_AMD && !vmm_is_amd())
70117632Sharti		return;
71117632Sharti
72117632Sharti	if (vst_num_elems + vst->nelems >= MAX_VMM_STAT_ELEMS) {
73117632Sharti		printf("Cannot accomodate vmm stat type \"%s\"!\n", vst->desc);
74117632Sharti		return;
75117632Sharti	}
76117632Sharti
77117632Sharti	vst->index = vst_num_elems;
78117632Sharti	vst_num_elems += vst->nelems;
79117632Sharti
80117632Sharti	vsttab[vst_num_types++] = vst;
81117632Sharti}
82117632Sharti
83117632Shartiint
84117632Shartivmm_stat_copy(struct vm *vm, int vcpu, int *num_stats, uint64_t *buf)
85117632Sharti{
86117632Sharti	int i;
87117632Sharti	uint64_t *stats;
88117632Sharti
89117632Sharti	if (vcpu < 0 || vcpu >= VM_MAXCPU)
90117632Sharti		return (EINVAL);
91117632Sharti
92117632Sharti	stats = vcpu_stats(vm, vcpu);
93117632Sharti	for (i = 0; i < vst_num_elems; i++)
94117632Sharti		buf[i] = stats[i];
95117632Sharti	*num_stats = vst_num_elems;
96117632Sharti	return (0);
97117632Sharti}
98117632Sharti
99117632Shartivoid *
100117632Shartivmm_stat_alloc(void)
101117632Sharti{
102117632Sharti
103117632Sharti	return (malloc(vst_size, M_VMM_STAT, M_WAITOK));
104117632Sharti}
105117632Sharti
106117632Shartivoid
107117632Shartivmm_stat_init(void *vp)
108117632Sharti{
109117632Sharti
110117632Sharti	bzero(vp, vst_size);
111117632Sharti}
112117632Sharti
113117632Shartivoid
114117632Shartivmm_stat_free(void *vp)
115117632Sharti{
116117632Sharti	free(vp, M_VMM_STAT);
117117632Sharti}
118117632Sharti
119117632Shartiint
120117632Shartivmm_stat_desc_copy(int index, char *buf, int bufsize)
121117632Sharti{
122117632Sharti	int i;
123117632Sharti	struct vmm_stat_type *vst;
124117632Sharti
125117632Sharti	for (i = 0; i < vst_num_types; i++) {
126117632Sharti		vst = vsttab[i];
127117632Sharti		if (index >= vst->index && index < vst->index + vst->nelems) {
128117632Sharti			if (vst->nelems > 1) {
129117632Sharti				snprintf(buf, bufsize, "%s[%d]",
130117632Sharti					 vst->desc, index - vst->index);
131117632Sharti			} else {
132117632Sharti				strlcpy(buf, vst->desc, bufsize);
133117632Sharti			}
134117632Sharti			return (0);	/* found it */
135117632Sharti		}
136117632Sharti	}
137117632Sharti
138117632Sharti	return (EINVAL);
139117632Sharti}
140117632Sharti
141117632Sharti/* global statistics */
142117632ShartiVMM_STAT(VCPU_MIGRATIONS, "vcpu migration across host cpus");
143117632ShartiVMM_STAT(VMEXIT_COUNT, "total number of vm exits");
144117632ShartiVMM_STAT(VMEXIT_EXTINT, "vm exits due to external interrupt");
145117632ShartiVMM_STAT(VMEXIT_HLT, "number of times hlt was intercepted");
146117632ShartiVMM_STAT(VMEXIT_CR_ACCESS, "number of times %cr access was intercepted");
147117632ShartiVMM_STAT(VMEXIT_RDMSR, "number of times rdmsr was intercepted");
148117632ShartiVMM_STAT(VMEXIT_WRMSR, "number of times wrmsr was intercepted");
149117632ShartiVMM_STAT(VMEXIT_MTRAP, "number of monitor trap exits");
150117632ShartiVMM_STAT(VMEXIT_PAUSE, "number of times pause was intercepted");
151117632ShartiVMM_STAT(VMEXIT_INTR_WINDOW, "vm exits due to interrupt window opening");
152117632ShartiVMM_STAT(VMEXIT_NMI_WINDOW, "vm exits due to nmi window opening");
153117632ShartiVMM_STAT(VMEXIT_INOUT, "number of times in/out was intercepted");
154117632ShartiVMM_STAT(VMEXIT_CPUID, "number of times cpuid was intercepted");
155117632ShartiVMM_STAT(VMEXIT_NESTED_FAULT, "vm exits due to nested page fault");
156117632ShartiVMM_STAT(VMEXIT_INST_EMUL, "vm exits for instruction emulation");
157117632ShartiVMM_STAT(VMEXIT_UNKNOWN, "number of vm exits for unknown reason");
158117632ShartiVMM_STAT(VMEXIT_ASTPENDING, "number of times astpending at exit");
159117632ShartiVMM_STAT(VMEXIT_USERSPACE, "number of vm exits handled in userspace");
160117632ShartiVMM_STAT(VMEXIT_RENDEZVOUS, "number of times rendezvous pending at exit");
161117632ShartiVMM_STAT(VMEXIT_EXCEPTION, "number of vm exits due to exceptions");
162117632Sharti