git: 93e81baa1c1b - main - vmm: Move duplicated stats code into a generic file
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 26 Aug 2024 18:58:30 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=93e81baa1c1baccf4eca9e3dbfe5ac9378e9623a
commit 93e81baa1c1baccf4eca9e3dbfe5ac9378e9623a
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-08-26 18:41:14 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-08-26 18:41:14 +0000
vmm: Move duplicated stats code into a generic file
There is a small difference between the arm64 and amd64 implementations:
the latter makes use of a "scope" to exclude AMD-specific stats on Intel
systems and vice-versa. Replace this with a more generic predicate
callback which can be used for the same purpose.
No functional change intended.
Reviewed by: corvink, jhb
Differential Revision: https://reviews.freebsd.org/D46430
---
sys/amd64/vmm/vmm.c | 23 +++++
sys/amd64/vmm/vmm_stat.c | 177 --------------------------------------
sys/amd64/vmm/vmm_stat.h | 109 ++---------------------
sys/arm64/vmm/vmm.c | 19 +++-
sys/arm64/vmm/vmm_stat.h | 98 +--------------------
sys/conf/files.arm64 | 2 +-
sys/{arm64 => dev}/vmm/vmm_stat.c | 26 ++----
sys/dev/vmm/vmm_stat.h | 135 +++++++++++++++++++++++++++++
sys/modules/vmm/Makefile | 7 +-
9 files changed, 196 insertions(+), 400 deletions(-)
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index b0465ea84fcb..d0259b3b125f 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -297,6 +297,29 @@ static void vm_free_memmap(struct vm *vm, int ident);
static bool sysmem_mapping(struct vm *vm, struct mem_map *mm);
static void vcpu_notify_event_locked(struct vcpu *vcpu, bool lapic_intr);
+/* global statistics */
+VMM_STAT(VCPU_MIGRATIONS, "vcpu migration across host cpus");
+VMM_STAT(VMEXIT_COUNT, "total number of vm exits");
+VMM_STAT(VMEXIT_EXTINT, "vm exits due to external interrupt");
+VMM_STAT(VMEXIT_HLT, "number of times hlt was intercepted");
+VMM_STAT(VMEXIT_CR_ACCESS, "number of times %cr access was intercepted");
+VMM_STAT(VMEXIT_RDMSR, "number of times rdmsr was intercepted");
+VMM_STAT(VMEXIT_WRMSR, "number of times wrmsr was intercepted");
+VMM_STAT(VMEXIT_MTRAP, "number of monitor trap exits");
+VMM_STAT(VMEXIT_PAUSE, "number of times pause was intercepted");
+VMM_STAT(VMEXIT_INTR_WINDOW, "vm exits due to interrupt window opening");
+VMM_STAT(VMEXIT_NMI_WINDOW, "vm exits due to nmi window opening");
+VMM_STAT(VMEXIT_INOUT, "number of times in/out was intercepted");
+VMM_STAT(VMEXIT_CPUID, "number of times cpuid was intercepted");
+VMM_STAT(VMEXIT_NESTED_FAULT, "vm exits due to nested page fault");
+VMM_STAT(VMEXIT_INST_EMUL, "vm exits for instruction emulation");
+VMM_STAT(VMEXIT_UNKNOWN, "number of vm exits for unknown reason");
+VMM_STAT(VMEXIT_ASTPENDING, "number of times astpending at exit");
+VMM_STAT(VMEXIT_REQIDLE, "number of times idle requested at exit");
+VMM_STAT(VMEXIT_USERSPACE, "number of vm exits handled in userspace");
+VMM_STAT(VMEXIT_RENDEZVOUS, "number of times rendezvous pending at exit");
+VMM_STAT(VMEXIT_EXCEPTION, "number of vm exits due to exceptions");
+
/*
* Upper limit on vm_maxcpu. Limited by use of uint16_t types for CPU
* counts as well as range of vpid values for VT-x and by the capacity
diff --git a/sys/amd64/vmm/vmm_stat.c b/sys/amd64/vmm/vmm_stat.c
deleted file mode 100644
index eb394418b4a9..000000000000
--- a/sys/amd64/vmm/vmm_stat.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2011 NetApp, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-
-#include <machine/vmm.h>
-#include "vmm_util.h"
-#include "vmm_stat.h"
-
-/*
- * '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");
-
-#define vst_size ((size_t)vst_num_elems * sizeof(uint64_t))
-
-void
-vmm_stat_register(void *arg)
-{
- struct vmm_stat_type *vst = arg;
-
- /* We require all stats to identify themselves with a description */
- if (vst->desc == NULL)
- return;
-
- if (vst->scope == VMM_STAT_SCOPE_INTEL && !vmm_is_intel())
- return;
-
- if (vst->scope == VMM_STAT_SCOPE_AMD && !vmm_is_svm())
- return;
-
- if (vst_num_elems + vst->nelems >= MAX_VMM_STAT_ELEMS) {
- printf("Cannot accommodate vmm stat type \"%s\"!\n", vst->desc);
- return;
- }
-
- vst->index = vst_num_elems;
- vst_num_elems += vst->nelems;
-
- vsttab[vst_num_types++] = vst;
-}
-
-int
-vmm_stat_copy(struct vcpu *vcpu, int index, int count, int *num_stats,
- uint64_t *buf)
-{
- struct vmm_stat_type *vst;
- uint64_t *stats;
- int i, tocopy;
-
- if (index < 0 || count < 0)
- return (EINVAL);
-
- if (index > vst_num_elems)
- return (ENOENT);
-
- if (index == vst_num_elems) {
- *num_stats = 0;
- return (0);
- }
-
- tocopy = min(vst_num_elems - index, count);
-
- /* Let stats functions update their counters */
- for (i = 0; i < vst_num_types; i++) {
- vst = vsttab[i];
- if (vst->func != NULL)
- (*vst->func)(vcpu, vst);
- }
-
- /* Copy over the stats */
- stats = vcpu_stats(vcpu);
- memcpy(buf, stats + index, tocopy * sizeof(stats[0]));
- *num_stats = tocopy;
- return (0);
-}
-
-void *
-vmm_stat_alloc(void)
-{
-
- return (malloc(vst_size, M_VMM_STAT, M_WAITOK));
-}
-
-void
-vmm_stat_init(void *vp)
-{
-
- bzero(vp, vst_size);
-}
-
-void
-vmm_stat_free(void *vp)
-{
- free(vp, M_VMM_STAT);
-}
-
-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 */
- }
- }
-
- return (EINVAL);
-}
-
-/* global statistics */
-VMM_STAT(VCPU_MIGRATIONS, "vcpu migration across host cpus");
-VMM_STAT(VMEXIT_COUNT, "total number of vm exits");
-VMM_STAT(VMEXIT_EXTINT, "vm exits due to external interrupt");
-VMM_STAT(VMEXIT_HLT, "number of times hlt was intercepted");
-VMM_STAT(VMEXIT_CR_ACCESS, "number of times %cr access was intercepted");
-VMM_STAT(VMEXIT_RDMSR, "number of times rdmsr was intercepted");
-VMM_STAT(VMEXIT_WRMSR, "number of times wrmsr was intercepted");
-VMM_STAT(VMEXIT_MTRAP, "number of monitor trap exits");
-VMM_STAT(VMEXIT_PAUSE, "number of times pause was intercepted");
-VMM_STAT(VMEXIT_INTR_WINDOW, "vm exits due to interrupt window opening");
-VMM_STAT(VMEXIT_NMI_WINDOW, "vm exits due to nmi window opening");
-VMM_STAT(VMEXIT_INOUT, "number of times in/out was intercepted");
-VMM_STAT(VMEXIT_CPUID, "number of times cpuid was intercepted");
-VMM_STAT(VMEXIT_NESTED_FAULT, "vm exits due to nested page fault");
-VMM_STAT(VMEXIT_INST_EMUL, "vm exits for instruction emulation");
-VMM_STAT(VMEXIT_UNKNOWN, "number of vm exits for unknown reason");
-VMM_STAT(VMEXIT_ASTPENDING, "number of times astpending at exit");
-VMM_STAT(VMEXIT_REQIDLE, "number of times idle requested at exit");
-VMM_STAT(VMEXIT_USERSPACE, "number of vm exits handled in userspace");
-VMM_STAT(VMEXIT_RENDEZVOUS, "number of times rendezvous pending at exit");
-VMM_STAT(VMEXIT_EXCEPTION, "number of vm exits due to exceptions");
diff --git a/sys/amd64/vmm/vmm_stat.h b/sys/amd64/vmm/vmm_stat.h
index 7d3a4044dcce..cf3895001528 100644
--- a/sys/amd64/vmm/vmm_stat.h
+++ b/sys/amd64/vmm/vmm_stat.h
@@ -32,108 +32,9 @@
#ifndef _VMM_STAT_H_
#define _VMM_STAT_H_
-struct vm;
+#include <dev/vmm/vmm_stat.h>
-#define MAX_VMM_STAT_ELEMS 64 /* arbitrary */
-
-enum vmm_stat_scope {
- VMM_STAT_SCOPE_ANY,
- VMM_STAT_SCOPE_INTEL, /* Intel VMX specific statistic */
- VMM_STAT_SCOPE_AMD, /* AMD SVM specific statistic */
-};
-
-struct vmm_stat_type;
-typedef void (*vmm_stat_func_t)(struct vcpu *vcpu,
- struct vmm_stat_type *stat);
-
-struct vmm_stat_type {
- int index; /* position in the stats buffer */
- int nelems; /* standalone or array */
- const char *desc; /* description of statistic */
- vmm_stat_func_t func;
- enum vmm_stat_scope scope;
-};
-
-void vmm_stat_register(void *arg);
-
-#define VMM_STAT_FDEFINE(type, nelems, desc, func, scope) \
- struct vmm_stat_type type[1] = { \
- { -1, nelems, desc, func, scope } \
- }; \
- SYSINIT(type##_stat, SI_SUB_KLD, SI_ORDER_ANY, vmm_stat_register, type)
-
-#define VMM_STAT_DEFINE(type, nelems, desc, scope) \
- VMM_STAT_FDEFINE(type, nelems, desc, NULL, scope)
-
-#define VMM_STAT_DECLARE(type) \
- extern struct vmm_stat_type type[1]
-
-#define VMM_STAT(type, desc) \
- VMM_STAT_DEFINE(type, 1, desc, VMM_STAT_SCOPE_ANY)
-#define VMM_STAT_INTEL(type, desc) \
- VMM_STAT_DEFINE(type, 1, desc, VMM_STAT_SCOPE_INTEL)
-#define VMM_STAT_AMD(type, desc) \
- VMM_STAT_DEFINE(type, 1, desc, VMM_STAT_SCOPE_AMD)
-
-#define VMM_STAT_FUNC(type, desc, func) \
- VMM_STAT_FDEFINE(type, 1, desc, func, VMM_STAT_SCOPE_ANY)
-
-#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_init(void *vp);
-void vmm_stat_free(void *vp);
-
-int vmm_stat_copy(struct vcpu *vcpu, int index, int count,
- int *num_stats, uint64_t *buf);
-int vmm_stat_desc_copy(int index, char *buf, int buflen);
-
-static void __inline
-vmm_stat_array_incr(struct vcpu *vcpu, struct vmm_stat_type *vst, int statidx,
- uint64_t x)
-{
-#ifdef VMM_KEEP_STATS
- uint64_t *stats;
-
- stats = vcpu_stats(vcpu);
-
- if (vst->index >= 0 && statidx < vst->nelems)
- stats[vst->index + statidx] += x;
-#endif
-}
-
-static void __inline
-vmm_stat_array_set(struct vcpu *vcpu, struct vmm_stat_type *vst, int statidx,
- uint64_t val)
-{
-#ifdef VMM_KEEP_STATS
- uint64_t *stats;
-
- stats = vcpu_stats(vcpu);
-
- if (vst->index >= 0 && statidx < vst->nelems)
- stats[vst->index + statidx] = val;
-#endif
-}
-
-static void __inline
-vmm_stat_incr(struct vcpu *vcpu, struct vmm_stat_type *vst, uint64_t x)
-{
-
-#ifdef VMM_KEEP_STATS
- vmm_stat_array_incr(vcpu, vst, 0, x);
-#endif
-}
-
-static void __inline
-vmm_stat_set(struct vcpu *vcpu, struct vmm_stat_type *vst, uint64_t val)
-{
-
-#ifdef VMM_KEEP_STATS
- vmm_stat_array_set(vcpu, vst, 0, val);
-#endif
-}
+#include "vmm_util.h"
VMM_STAT_DECLARE(VCPU_MIGRATIONS);
VMM_STAT_DECLARE(VMEXIT_COUNT);
@@ -156,4 +57,10 @@ VMM_STAT_DECLARE(VMEXIT_USERSPACE);
VMM_STAT_DECLARE(VMEXIT_RENDEZVOUS);
VMM_STAT_DECLARE(VMEXIT_EXCEPTION);
VMM_STAT_DECLARE(VMEXIT_REQIDLE);
+
+#define VMM_STAT_INTEL(type, desc) \
+ VMM_STAT_DEFINE(type, 1, desc, vmm_is_intel)
+#define VMM_STAT_AMD(type, desc) \
+ VMM_STAT_DEFINE(type, 1, desc, vmm_is_svm)
+
#endif
diff --git a/sys/arm64/vmm/vmm.c b/sys/arm64/vmm/vmm.c
index f5173c4152bd..425e44f81500 100644
--- a/sys/arm64/vmm/vmm.c
+++ b/sys/arm64/vmm/vmm.c
@@ -65,8 +65,8 @@
#include <dev/pci/pcireg.h>
#include <dev/vmm/vmm_ktr.h>
+#include <dev/vmm/vmm_stat.h>
-#include "vmm_stat.h"
#include "arm64.h"
#include "mmu.h"
@@ -239,6 +239,23 @@ static void vm_free_memmap(struct vm *vm, int ident);
static bool sysmem_mapping(struct vm *vm, struct mem_map *mm);
static void vcpu_notify_event_locked(struct vcpu *vcpu);
+/* global statistics */
+VMM_STAT(VMEXIT_COUNT, "total number of vm exits");
+VMM_STAT(VMEXIT_UNKNOWN, "number of vmexits for the unknown exception");
+VMM_STAT(VMEXIT_WFI, "number of times wfi was intercepted");
+VMM_STAT(VMEXIT_WFE, "number of times wfe was intercepted");
+VMM_STAT(VMEXIT_HVC, "number of times hvc was intercepted");
+VMM_STAT(VMEXIT_MSR, "number of times msr/mrs was intercepted");
+VMM_STAT(VMEXIT_DATA_ABORT, "number of vmexits for a data abort");
+VMM_STAT(VMEXIT_INSN_ABORT, "number of vmexits for an instruction abort");
+VMM_STAT(VMEXIT_UNHANDLED_SYNC, "number of vmexits for an unhandled synchronous exception");
+VMM_STAT(VMEXIT_IRQ, "number of vmexits for an irq");
+VMM_STAT(VMEXIT_FIQ, "number of vmexits for an interrupt");
+VMM_STAT(VMEXIT_BRK, "number of vmexits for a breakpoint exception");
+VMM_STAT(VMEXIT_SS, "number of vmexits for a single-step exception");
+VMM_STAT(VMEXIT_UNHANDLED_EL2, "number of vmexits for an unhandled EL2 exception");
+VMM_STAT(VMEXIT_UNHANDLED, "number of vmexits for an unhandled exception");
+
/*
* Upper limit on vm_maxcpu. We could increase this to 28 bits, but this
* is a safe value for now.
diff --git a/sys/arm64/vmm/vmm_stat.h b/sys/arm64/vmm/vmm_stat.h
index 402fa2f1b1e4..0dc3eeced603 100644
--- a/sys/arm64/vmm/vmm_stat.h
+++ b/sys/arm64/vmm/vmm_stat.h
@@ -32,102 +32,7 @@
#ifndef _VMM_STAT_H_
#define _VMM_STAT_H_
-struct vm;
-
-#define MAX_VMM_STAT_ELEMS 64 /* arbitrary */
-
-enum vmm_stat_scope {
- VMM_STAT_SCOPE_ANY,
-};
-
-struct vmm_stat_type;
-typedef void (*vmm_stat_func_t)(struct vcpu *vcpu,
- struct vmm_stat_type *stat);
-
-struct vmm_stat_type {
- int index; /* position in the stats buffer */
- int nelems; /* standalone or array */
- const char *desc; /* description of statistic */
- vmm_stat_func_t func;
- enum vmm_stat_scope scope;
-};
-
-void vmm_stat_register(void *arg);
-
-#define VMM_STAT_FDEFINE(type, nelems, desc, func, scope) \
- struct vmm_stat_type type[1] = { \
- { -1, nelems, desc, func, scope } \
- }; \
- SYSINIT(type##_stat, SI_SUB_KLD, SI_ORDER_ANY, vmm_stat_register, type)
-
-#define VMM_STAT_DEFINE(type, nelems, desc, scope) \
- VMM_STAT_FDEFINE(type, nelems, desc, NULL, scope)
-
-#define VMM_STAT_DECLARE(type) \
- extern struct vmm_stat_type type[1]
-
-#define VMM_STAT(type, desc) \
- VMM_STAT_DEFINE(type, 1, desc, VMM_STAT_SCOPE_ANY)
-
-#define VMM_STAT_FUNC(type, desc, func) \
- VMM_STAT_FDEFINE(type, 1, desc, func, VMM_STAT_SCOPE_ANY)
-
-#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_init(void *vp);
-void vmm_stat_free(void *vp);
-
-int vmm_stat_copy(struct vcpu *vcpu, int index, int count,
- int *num_stats, uint64_t *buf);
-int vmm_stat_desc_copy(int index, char *buf, int buflen);
-
-static void __inline
-vmm_stat_array_incr(struct vcpu *vcpu, struct vmm_stat_type *vst, int statidx,
- uint64_t x)
-{
-#ifdef VMM_KEEP_STATS
- uint64_t *stats;
-
- stats = vcpu_stats(vcpu);
-
- if (vst->index >= 0 && statidx < vst->nelems)
- stats[vst->index + statidx] += x;
-#endif
-}
-
-static void __inline
-vmm_stat_array_set(struct vcpu *vcpu, struct vmm_stat_type *vst, int statidx,
- uint64_t val)
-{
-#ifdef VMM_KEEP_STATS
- uint64_t *stats;
-
- stats = vcpu_stats(vcpu);
-
- if (vst->index >= 0 && statidx < vst->nelems)
- stats[vst->index + statidx] = val;
-#endif
-}
-
-static void __inline
-vmm_stat_incr(struct vcpu *vcpu, struct vmm_stat_type *vst, uint64_t x)
-{
-
-#ifdef VMM_KEEP_STATS
- vmm_stat_array_incr(vcpu, vst, 0, x);
-#endif
-}
-
-static void __inline
-vmm_stat_set(struct vcpu *vcpu, struct vmm_stat_type *vst, uint64_t val)
-{
-
-#ifdef VMM_KEEP_STATS
- vmm_stat_array_set(vcpu, vst, 0, val);
-#endif
-}
+#include <dev/vmm/vmm_stat.h>
VMM_STAT_DECLARE(VMEXIT_COUNT);
VMM_STAT_DECLARE(VMEXIT_UNKNOWN);
@@ -144,4 +49,5 @@ VMM_STAT_DECLARE(VMEXIT_BRK);
VMM_STAT_DECLARE(VMEXIT_SS);
VMM_STAT_DECLARE(VMEXIT_UNHANDLED_EL2);
VMM_STAT_DECLARE(VMEXIT_UNHANDLED);
+
#endif
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index 1c863ff98998..3a8818340f75 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -119,7 +119,6 @@ dev/iommu/iommu_gas.c optional iommu
arm64/vmm/vmm.c optional vmm
arm64/vmm/vmm_dev.c optional vmm
arm64/vmm/vmm_instruction_emul.c optional vmm
-arm64/vmm/vmm_stat.c optional vmm
arm64/vmm/vmm_arm64.c optional vmm
arm64/vmm/vmm_reset.c optional vmm
arm64/vmm/vmm_handlers.c optional vmm
@@ -151,6 +150,7 @@ arm64/vmm/io/vgic.c optional vmm
arm64/vmm/io/vgic_v3.c optional vmm
arm64/vmm/io/vgic_if.m optional vmm
arm64/vmm/io/vtimer.c optional vmm
+dev/vmm/vmm_stat.c optional vmm
crypto/armv8/armv8_crypto.c optional armv8crypto
armv8_crypto_wrap.o optional armv8crypto \
diff --git a/sys/arm64/vmm/vmm_stat.c b/sys/dev/vmm/vmm_stat.c
similarity index 77%
rename from sys/arm64/vmm/vmm_stat.c
rename to sys/dev/vmm/vmm_stat.c
index 05ece6f30579..44edd6af85dd 100644
--- a/sys/arm64/vmm/vmm_stat.c
+++ b/sys/dev/vmm/vmm_stat.c
@@ -26,16 +26,14 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/malloc.h>
-#include <machine/machdep.h>
#include <machine/vmm.h>
-#include "vmm_stat.h"
+
+#include <dev/vmm/vmm_stat.h>
/*
* 'vst_num_elems' is the total number of addressable statistic elements
@@ -61,6 +59,9 @@ vmm_stat_register(void *arg)
if (vst->desc == NULL)
return;
+ if (vst->pred != NULL && !vst->pred())
+ return;
+
if (vst_num_elems + vst->nelems >= MAX_VMM_STAT_ELEMS) {
printf("Cannot accommodate vmm stat type \"%s\"!\n", vst->desc);
return;
@@ -148,20 +149,3 @@ vmm_stat_desc_copy(int index, char *buf, int bufsize)
return (EINVAL);
}
-
-/* global statistics */
-VMM_STAT(VMEXIT_COUNT, "total number of vm exits");
-VMM_STAT(VMEXIT_UNKNOWN, "number of vmexits for the unknown exception");
-VMM_STAT(VMEXIT_WFI, "number of times wfi was intercepted");
-VMM_STAT(VMEXIT_WFE, "number of times wfe was intercepted");
-VMM_STAT(VMEXIT_HVC, "number of times hvc was intercepted");
-VMM_STAT(VMEXIT_MSR, "number of times msr/mrs was intercepted");
-VMM_STAT(VMEXIT_DATA_ABORT, "number of vmexits for a data abort");
-VMM_STAT(VMEXIT_INSN_ABORT, "number of vmexits for an instruction abort");
-VMM_STAT(VMEXIT_UNHANDLED_SYNC, "number of vmexits for an unhandled synchronous exception");
-VMM_STAT(VMEXIT_IRQ, "number of vmexits for an irq");
-VMM_STAT(VMEXIT_FIQ, "number of vmexits for an interrupt");
-VMM_STAT(VMEXIT_BRK, "number of vmexits for a breakpoint exception");
-VMM_STAT(VMEXIT_SS, "number of vmexits for a single-step exception");
-VMM_STAT(VMEXIT_UNHANDLED_EL2, "number of vmexits for an unhandled EL2 exception");
-VMM_STAT(VMEXIT_UNHANDLED, "number of vmexits for an unhandled exception");
diff --git a/sys/dev/vmm/vmm_stat.h b/sys/dev/vmm/vmm_stat.h
new file mode 100644
index 000000000000..471afd0dd827
--- /dev/null
+++ b/sys/dev/vmm/vmm_stat.h
@@ -0,0 +1,135 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _DEV_VMM_STAT_H_
+#define _DEV_VMM_STAT_H_
+
+struct vm;
+
+#define MAX_VMM_STAT_ELEMS 64 /* arbitrary */
+
+struct vmm_stat_type;
+typedef void (*vmm_stat_func_t)(struct vcpu *vcpu,
+ struct vmm_stat_type *stat);
+typedef bool (*vmm_stat_func_pred_t)(void);
+
+struct vmm_stat_type {
+ int index; /* position in the stats buffer */
+ int nelems; /* standalone or array */
+ const char *desc; /* description of statistic */
+ vmm_stat_func_t func;
+ vmm_stat_func_pred_t pred; /* predicate to check during registration */
+};
+
+void vmm_stat_register(void *arg);
+
+#define VMM_STAT_FDEFINE(type, _nelems, _desc, _func, _pred) \
+ struct vmm_stat_type type[1] = { \
+ { \
+ .index = -1, \
+ .nelems = _nelems, \
+ .desc = _desc, \
+ .func = _func, \
+ .pred = _pred, \
+ } \
+ }; \
+ SYSINIT(type##_stat, SI_SUB_KLD, SI_ORDER_ANY, vmm_stat_register, type)
+
+#define VMM_STAT_DEFINE(type, nelems, desc, pred) \
+ VMM_STAT_FDEFINE(type, nelems, desc, NULL, pred)
+
+#define VMM_STAT_DECLARE(type) \
+ extern struct vmm_stat_type type[1]
+
+#define VMM_STAT(type, desc) \
+ VMM_STAT_DEFINE(type, 1, desc, NULL)
+
+#define VMM_STAT_FUNC(type, desc, func) \
+ VMM_STAT_FDEFINE(type, 1, desc, func, NULL)
+
+#define VMM_STAT_ARRAY(type, nelems, desc) \
+ VMM_STAT_DEFINE(type, nelems, desc, NULL)
+
+void *vmm_stat_alloc(void);
+void vmm_stat_init(void *vp);
+void vmm_stat_free(void *vp);
+
+int vmm_stat_copy(struct vcpu *vcpu, int index, int count,
+ int *num_stats, uint64_t *buf);
+int vmm_stat_desc_copy(int index, char *buf, int buflen);
+
+static void __inline
+vmm_stat_array_incr(struct vcpu *vcpu, struct vmm_stat_type *vst, int statidx,
+ uint64_t x)
+{
+#ifdef VMM_KEEP_STATS
+ uint64_t *stats;
+
+ stats = vcpu_stats(vcpu);
+
+ if (vst->index >= 0 && statidx < vst->nelems)
+ stats[vst->index + statidx] += x;
+#endif
+}
+
+static void __inline
+vmm_stat_array_set(struct vcpu *vcpu, struct vmm_stat_type *vst, int statidx,
+ uint64_t val)
+{
+#ifdef VMM_KEEP_STATS
+ uint64_t *stats;
+
+ stats = vcpu_stats(vcpu);
+
+ if (vst->index >= 0 && statidx < vst->nelems)
+ stats[vst->index + statidx] = val;
+#endif
+}
+
+static void __inline
+vmm_stat_incr(struct vcpu *vcpu, struct vmm_stat_type *vst, uint64_t x)
+{
+
+#ifdef VMM_KEEP_STATS
+ vmm_stat_array_incr(vcpu, vst, 0, x);
+#endif
+}
+
+static void __inline
+vmm_stat_set(struct vcpu *vcpu, struct vmm_stat_type *vst, uint64_t val)
+{
+
+#ifdef VMM_KEEP_STATS
+ vmm_stat_array_set(vcpu, vst, 0, val);
+#endif
+}
+
+#endif /* !_DEV_VMM_STAT_H_ */
diff --git a/sys/modules/vmm/Makefile b/sys/modules/vmm/Makefile
index 0604a34690e5..92986a364883 100644
--- a/sys/modules/vmm/Makefile
+++ b/sys/modules/vmm/Makefile
@@ -15,9 +15,10 @@ CFLAGS+= -I${SRCTOP}/sys/${MACHINE}/vmm
CFLAGS+= -I${SRCTOP}/sys/${MACHINE}/vmm/io
# generic vmm support
-.PATH: ${SRCTOP}/sys/${MACHINE}/vmm
-SRCS+= vmm.c \
- vmm_dev.c \
+.PATH: ${SRCTOP}/sys/dev/vmm ${SRCTOP}/sys/${MACHINE}/vmm
+
+SRCS+= vmm.c \
+ vmm_dev.c \
vmm_instruction_emul.c \
vmm_stat.c