The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=93e81baa1c1baccf4eca9e3dbfe5ac9378e9623a

commit 93e81baa1c1baccf4eca9e3dbfe5ac9378e9623a
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2024-08-26 18:41:14 +0000
Commit:     Mark Johnston <ma...@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
 

Reply via email to