17c8c0b82SPatrick Mooney /*- 27c8c0b82SPatrick Mooney * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 37c8c0b82SPatrick Mooney * 47c8c0b82SPatrick Mooney * Copyright (c) 2011 NetApp, Inc. 57c8c0b82SPatrick Mooney * All rights reserved. 67c8c0b82SPatrick Mooney * 77c8c0b82SPatrick Mooney * Redistribution and use in source and binary forms, with or without 87c8c0b82SPatrick Mooney * modification, are permitted provided that the following conditions 97c8c0b82SPatrick Mooney * are met: 107c8c0b82SPatrick Mooney * 1. Redistributions of source code must retain the above copyright 117c8c0b82SPatrick Mooney * notice, this list of conditions and the following disclaimer. 127c8c0b82SPatrick Mooney * 2. Redistributions in binary form must reproduce the above copyright 137c8c0b82SPatrick Mooney * notice, this list of conditions and the following disclaimer in the 147c8c0b82SPatrick Mooney * documentation and/or other materials provided with the distribution. 157c8c0b82SPatrick Mooney * 167c8c0b82SPatrick Mooney * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 177c8c0b82SPatrick Mooney * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 187c8c0b82SPatrick Mooney * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 197c8c0b82SPatrick Mooney * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 207c8c0b82SPatrick Mooney * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 217c8c0b82SPatrick Mooney * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 227c8c0b82SPatrick Mooney * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 237c8c0b82SPatrick Mooney * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 247c8c0b82SPatrick Mooney * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 257c8c0b82SPatrick Mooney * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 267c8c0b82SPatrick Mooney * SUCH DAMAGE. 277c8c0b82SPatrick Mooney * 287c8c0b82SPatrick Mooney * $FreeBSD$ 297c8c0b82SPatrick Mooney */ 307c8c0b82SPatrick Mooney 317c8c0b82SPatrick Mooney #include <sys/cdefs.h> 327c8c0b82SPatrick Mooney __FBSDID("$FreeBSD$"); 337c8c0b82SPatrick Mooney 347c8c0b82SPatrick Mooney #include <sys/param.h> 357c8c0b82SPatrick Mooney #include <sys/kernel.h> 367c8c0b82SPatrick Mooney #include <sys/systm.h> 377c8c0b82SPatrick Mooney #include <sys/malloc.h> 387c8c0b82SPatrick Mooney 397c8c0b82SPatrick Mooney #include <machine/vmm.h> 407c8c0b82SPatrick Mooney #include "vmm_util.h" 417c8c0b82SPatrick Mooney #include "vmm_stat.h" 427c8c0b82SPatrick Mooney 437c8c0b82SPatrick Mooney /* 447c8c0b82SPatrick Mooney * 'vst_num_elems' is the total number of addressable statistic elements 457c8c0b82SPatrick Mooney * 'vst_num_types' is the number of unique statistic types 467c8c0b82SPatrick Mooney * 477c8c0b82SPatrick Mooney * It is always true that 'vst_num_elems' is greater than or equal to 487c8c0b82SPatrick Mooney * 'vst_num_types'. This is because a stat type may represent more than 497c8c0b82SPatrick Mooney * one element (for e.g. VMM_STAT_ARRAY). 507c8c0b82SPatrick Mooney */ 517c8c0b82SPatrick Mooney static int vst_num_elems, vst_num_types; 527c8c0b82SPatrick Mooney static struct vmm_stat_type *vsttab[MAX_VMM_STAT_ELEMS]; 537c8c0b82SPatrick Mooney 547c8c0b82SPatrick Mooney static MALLOC_DEFINE(M_VMM_STAT, "vmm stat", "vmm stat"); 557c8c0b82SPatrick Mooney 567c8c0b82SPatrick Mooney #define vst_size ((size_t)vst_num_elems * sizeof (uint64_t)) 577c8c0b82SPatrick Mooney 587c8c0b82SPatrick Mooney void 597c8c0b82SPatrick Mooney vmm_stat_register(void *arg) 607c8c0b82SPatrick Mooney { 617c8c0b82SPatrick Mooney struct vmm_stat_type *vst = arg; 627c8c0b82SPatrick Mooney 637c8c0b82SPatrick Mooney /* We require all stats to identify themselves with a description */ 647c8c0b82SPatrick Mooney if (vst->desc == NULL) 657c8c0b82SPatrick Mooney return; 667c8c0b82SPatrick Mooney 677c8c0b82SPatrick Mooney if (vst->scope == VMM_STAT_SCOPE_INTEL && !vmm_is_intel()) 687c8c0b82SPatrick Mooney return; 697c8c0b82SPatrick Mooney 707c8c0b82SPatrick Mooney if (vst->scope == VMM_STAT_SCOPE_AMD && !vmm_is_svm()) 717c8c0b82SPatrick Mooney return; 727c8c0b82SPatrick Mooney 737c8c0b82SPatrick Mooney if (vst_num_elems + vst->nelems >= MAX_VMM_STAT_ELEMS) { 747c8c0b82SPatrick Mooney printf("Cannot accommodate vmm stat type \"%s\"!\n", vst->desc); 757c8c0b82SPatrick Mooney return; 767c8c0b82SPatrick Mooney } 777c8c0b82SPatrick Mooney 787c8c0b82SPatrick Mooney vst->index = vst_num_elems; 797c8c0b82SPatrick Mooney vst_num_elems += vst->nelems; 807c8c0b82SPatrick Mooney 817c8c0b82SPatrick Mooney vsttab[vst_num_types++] = vst; 827c8c0b82SPatrick Mooney } 837c8c0b82SPatrick Mooney 847c8c0b82SPatrick Mooney int 85*d7b72f7bSAndy Fiddaman vmm_stat_copy(struct vm *vm, int vcpu, int index, int count, int *num_stats, 86*d7b72f7bSAndy Fiddaman uint64_t *buf) 877c8c0b82SPatrick Mooney { 887c8c0b82SPatrick Mooney struct vmm_stat_type *vst; 897c8c0b82SPatrick Mooney uint64_t *stats; 90*d7b72f7bSAndy Fiddaman int i, tocopy; 917c8c0b82SPatrick Mooney 927c8c0b82SPatrick Mooney if (vcpu < 0 || vcpu >= vm_get_maxcpus(vm)) 937c8c0b82SPatrick Mooney return (EINVAL); 947c8c0b82SPatrick Mooney 95*d7b72f7bSAndy Fiddaman if (index < 0 || count < 0) 96*d7b72f7bSAndy Fiddaman return (EINVAL); 97*d7b72f7bSAndy Fiddaman 98*d7b72f7bSAndy Fiddaman if (index > vst_num_elems) 99*d7b72f7bSAndy Fiddaman return (ENOENT); 100*d7b72f7bSAndy Fiddaman 101*d7b72f7bSAndy Fiddaman if (index == vst_num_elems) { 102*d7b72f7bSAndy Fiddaman *num_stats = 0; 103*d7b72f7bSAndy Fiddaman return (0); 104*d7b72f7bSAndy Fiddaman } 105*d7b72f7bSAndy Fiddaman 106*d7b72f7bSAndy Fiddaman tocopy = min(vst_num_elems - index, count); 107*d7b72f7bSAndy Fiddaman 1087c8c0b82SPatrick Mooney /* Let stats functions update their counters */ 1097c8c0b82SPatrick Mooney for (i = 0; i < vst_num_types; i++) { 1107c8c0b82SPatrick Mooney vst = vsttab[i]; 1117c8c0b82SPatrick Mooney if (vst->func != NULL) 1127c8c0b82SPatrick Mooney (*vst->func)(vm, vcpu, vst); 1137c8c0b82SPatrick Mooney } 1147c8c0b82SPatrick Mooney 1157c8c0b82SPatrick Mooney /* Copy over the stats */ 1167c8c0b82SPatrick Mooney stats = vcpu_stats(vm, vcpu); 117*d7b72f7bSAndy Fiddaman memcpy(buf, stats + index, tocopy * sizeof (stats[0])); 118*d7b72f7bSAndy Fiddaman *num_stats = tocopy; 1197c8c0b82SPatrick Mooney return (0); 1207c8c0b82SPatrick Mooney } 1217c8c0b82SPatrick Mooney 1227c8c0b82SPatrick Mooney void * 1237c8c0b82SPatrick Mooney vmm_stat_alloc(void) 1247c8c0b82SPatrick Mooney { 1257c8c0b82SPatrick Mooney 1267c8c0b82SPatrick Mooney return (malloc(vst_size, M_VMM_STAT, M_WAITOK)); 1277c8c0b82SPatrick Mooney } 1287c8c0b82SPatrick Mooney 1297c8c0b82SPatrick Mooney void 1307c8c0b82SPatrick Mooney vmm_stat_init(void *vp) 1317c8c0b82SPatrick Mooney { 1327c8c0b82SPatrick Mooney 1337c8c0b82SPatrick Mooney bzero(vp, vst_size); 1347c8c0b82SPatrick Mooney } 1357c8c0b82SPatrick Mooney 1367c8c0b82SPatrick Mooney void 1377c8c0b82SPatrick Mooney vmm_stat_free(void *vp) 1387c8c0b82SPatrick Mooney { 1397c8c0b82SPatrick Mooney free(vp, M_VMM_STAT); 1407c8c0b82SPatrick Mooney } 1417c8c0b82SPatrick Mooney 1427c8c0b82SPatrick Mooney int 1437c8c0b82SPatrick Mooney vmm_stat_desc_copy(int index, char *buf, int bufsize) 1447c8c0b82SPatrick Mooney { 1457c8c0b82SPatrick Mooney int i; 1467c8c0b82SPatrick Mooney struct vmm_stat_type *vst; 1477c8c0b82SPatrick Mooney 1487c8c0b82SPatrick Mooney for (i = 0; i < vst_num_types; i++) { 1497c8c0b82SPatrick Mooney vst = vsttab[i]; 1507c8c0b82SPatrick Mooney if (index >= vst->index && index < vst->index + vst->nelems) { 1517c8c0b82SPatrick Mooney if (vst->nelems > 1) { 152e0994bd2SPatrick Mooney (void) snprintf(buf, bufsize, "%s[%d]", 1537c8c0b82SPatrick Mooney vst->desc, index - vst->index); 1547c8c0b82SPatrick Mooney } else { 155e0994bd2SPatrick Mooney (void) strlcpy(buf, vst->desc, bufsize); 1567c8c0b82SPatrick Mooney } 1577c8c0b82SPatrick Mooney return (0); /* found it */ 1587c8c0b82SPatrick Mooney } 1597c8c0b82SPatrick Mooney } 1607c8c0b82SPatrick Mooney 1617c8c0b82SPatrick Mooney return (EINVAL); 1627c8c0b82SPatrick Mooney } 1637c8c0b82SPatrick Mooney 1647c8c0b82SPatrick Mooney /* global statistics */ 1657c8c0b82SPatrick Mooney VMM_STAT(VCPU_MIGRATIONS, "vcpu migration across host cpus"); 1667c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_COUNT, "total number of vm exits"); 1677c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_EXTINT, "vm exits due to external interrupt"); 1687c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_HLT, "number of times hlt was intercepted"); 1697c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_CR_ACCESS, "number of times %cr access was intercepted"); 1707c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_RDMSR, "number of times rdmsr was intercepted"); 1717c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_WRMSR, "number of times wrmsr was intercepted"); 1727c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_MTRAP, "number of monitor trap exits"); 1737c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_PAUSE, "number of times pause was intercepted"); 1747c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_INTR_WINDOW, "vm exits due to interrupt window opening"); 1757c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_NMI_WINDOW, "vm exits due to nmi window opening"); 1767c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_INOUT, "number of times in/out was intercepted"); 1777c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_CPUID, "number of times cpuid was intercepted"); 1787c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_NESTED_FAULT, "vm exits due to nested page fault"); 1797c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_MMIO_EMUL, "vm exits for mmio emulation"); 1807c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_UNKNOWN, "number of vm exits for unknown reason"); 1817c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_ASTPENDING, "number of times astpending at exit"); 1827c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_REQIDLE, "number of times idle requested at exit"); 1837c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_EXCEPTION, "number of vm exits due to exceptions"); 1847c8c0b82SPatrick Mooney VMM_STAT(VMEXIT_RUN_STATE, "number of vm exits due to run_state change"); 185