Date: Fri, 24 Apr 2026 16:24:41 +0000 From: Warner Losh <imp@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Ali Mashtizadeh <ali@mashtizadeh.com> Subject: git: 70ae0c4524d2 - main - i386: Remove perfmon performance monitoring facility Message-ID: <69eb9949.3a5d2.72b91820@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=70ae0c4524d2c5d0aae3339e95f6bd4f3c480b6e commit 70ae0c4524d2c5d0aae3339e95f6bd4f3c480b6e Author: Ali Mashtizadeh <ali@mashtizadeh.com> AuthorDate: 2026-04-20 22:06:30 +0000 Commit: Warner Losh <imp@FreeBSD.org> CommitDate: 2026-04-24 16:23:05 +0000 i386: Remove perfmon performance monitoring facility Remove the perfmon performance monitoring facility that was for Intel Pentium and Pentium Pro processors. Reviewed by: imp,mhorne,emaste Pull Request: https://github.com/freebsd/freebsd-src/pull/2155 --- ObsoleteFiles.inc | 8 + etc/mtree/BSD.usr.dist | 2 - share/examples/Makefile | 7 - share/examples/perfmon/Makefile | 8 - share/examples/perfmon/README | 23 -- share/examples/perfmon/perfmon.c | 191 --------------- share/man/man4/man4.i386/Makefile | 1 - share/man/man4/man4.i386/perfmon.4 | 211 ---------------- share/man/man7/clocks.7 | 4 - sys/conf/files.i386 | 1 - sys/i386/conf/NOTES | 6 - sys/i386/i386/machdep.c | 7 - sys/i386/i386/perfmon.c | 402 ------------------------------- sys/i386/include/perfmon.h | 253 ------------------- tools/build/mk/OptionalObsoleteFiles.inc | 4 - 15 files changed, 8 insertions(+), 1120 deletions(-) diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index a4fdac95bf5a..465508bf40a3 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -51,6 +51,14 @@ # xargs -n1 | sort | uniq -d; # done +# 20260420: remove perfmon +OLD_FILES+=boot/kernel/perfmon.ko +OLD_FILES+=usr/share/man/man4/perfmon.4.gz +OLD_FILES+=usr/share/examples/perfmon/Makefile +OLD_FILES+=usr/share/examples/perfmon/README +OLD_FILES+=usr/share/examples/perfmon/perfmon.c +OLD_DIRS+=usr/share/examples/perfmon + # 20260402: posix_spawn_file_actions_addchdir lost _np suffix OLD_FILES+=usr/share/man/man3/posix_spawn_file_actions_addchdir_np.3.gz OLD_FILES+=usr/share/man/man3/posix_spawn_file_actions_addfchdir_np.3.gz diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist index b281a368861d..120b961d230c 100644 --- a/etc/mtree/BSD.usr.dist +++ b/etc/mtree/BSD.usr.dist @@ -346,8 +346,6 @@ .. netgraph .. - perfmon - .. pf .. ppi diff --git a/share/examples/Makefile b/share/examples/Makefile index d977f2e5a0da..dae84f27d9dc 100644 --- a/share/examples/Makefile +++ b/share/examples/Makefile @@ -22,7 +22,6 @@ LDIRS= BSD_daemon \ mdoc \ netgraph \ oci \ - perfmon \ ppi \ ppp \ ses \ @@ -202,12 +201,6 @@ SE_OCI= \ README \ Containerfile.pkg -SE_DIRS+= perfmon -SE_PERFMON= \ - Makefile \ - README \ - perfmon.c \ - .if ${MK_PF} != "no" SE_DIRS+= pf .if ${MK_STAGING} == "no" diff --git a/share/examples/perfmon/Makefile b/share/examples/perfmon/Makefile deleted file mode 100644 index 96712dee88e3..000000000000 --- a/share/examples/perfmon/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -PACKAGE=examples -FILESDIR=${SHAREDIR}/examples/${PROG} -PROG= perfmon -MAN= - -install: - -.include <bsd.prog.mk> diff --git a/share/examples/perfmon/README b/share/examples/perfmon/README deleted file mode 100644 index 25452813f3db..000000000000 --- a/share/examples/perfmon/README +++ /dev/null @@ -1,23 +0,0 @@ -`perfmon' is a sample program to access the performance-monitoring -counters on Pentium and Pentium Pro CPUs. See perfmon(4) for a -description of this facility. - -The program takes the following options: - - -u count events in user mode - -o count events in kernel mode - (these two can be combined) - - -e count events, not duration - -l n run `n' loops (default 50) - -s n sleep `n' seconds between loop iterations (default 0) - -The following options are not implemented on Pentium CPUs: - - -m n use count mask `n' - -i invert sense of count mask comparison - -U n use unit mask `n' - -There is one mandatory argument, which is the event number to be -monitored, defined in <machine/perfmon.h>. All numbers can be -specified in any format acceptable to strtol(3). diff --git a/share/examples/perfmon/perfmon.c b/share/examples/perfmon/perfmon.c deleted file mode 100644 index 1b7afad9d69e..000000000000 --- a/share/examples/perfmon/perfmon.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 1996 Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby - * granted, provided that both the above copyright notice and this - * permission notice appear in all copies, that both the above - * copyright notice and this permission notice appear in all - * supporting documentation, and that the name of M.I.T. not be used - * in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. M.I.T. makes - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS - * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT - * SHALL M.I.T. 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/types.h> -#include <sys/ioctl.h> - -#include <machine/cpu.h> -#include <machine/perfmon.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <err.h> -#include <unistd.h> -#include <fcntl.h> -#include <limits.h> -#include <errno.h> - -static int getnum(const char *, int, int); -static void usage(const char *) __dead2; - -int -main(int argc, char **argv) -{ - int c, fd, num; - int loops, i, sleeptime; - char *cmd; - struct pmc pmc; - struct pmc_tstamp then, now; - struct pmc_data value; - quad_t *buf; - double total; - - pmc.pmc_num = 0; - pmc.pmc_event = 0; - pmc.pmc_unit = 0; - pmc.pmc_flags = 0; - pmc.pmc_mask = 0; - cmd = NULL; - loops = 50; - sleeptime = 0; - - while ((c = getopt(argc, argv, "s:l:uoeiU:m:c:")) != -1) { - switch(c) { - case 'u': - pmc.pmc_flags |= PMCF_USR; - break; - case 'o': - pmc.pmc_flags |= PMCF_OS; - break; - case 'e': - pmc.pmc_flags |= PMCF_E; - break; - case 'i': - pmc.pmc_flags |= PMCF_INV; - break; - case 'U': - pmc.pmc_unit = getnum(optarg, 0, 256); - break; - case 'm': - pmc.pmc_mask = getnum(optarg, 0, 256); - break; - case 'l': - loops = getnum(optarg, 1, INT_MAX - 1); - break; - case 's': - sleeptime = getnum(optarg, 0, INT_MAX - 1); - break; - case 'c': - cmd = optarg; - break; - default: - usage(argv[0]); - } - } - - if (argc - optind != 1) - usage(argv[0]); - - pmc.pmc_event = getnum(argv[optind], 0, 255); - - buf = malloc((loops + 1) * sizeof *buf); - if (!buf) - err(1, "malloc(%lu)", (unsigned long)(loops +1) * sizeof *buf); - - fd = open(_PATH_PERFMON, O_RDWR, 0); - if (fd < 0) - err(1, "open: " _PATH_PERFMON); - - if (ioctl(fd, PMIOSETUP, &pmc) < 0) - err(1, "ioctl(PMIOSETUP)"); - - if (ioctl(fd, PMIOTSTAMP, &then) < 0) - err(1, "ioctl(PMIOTSTAMP)"); - - num = 0; - if (ioctl(fd, PMIOSTART, &num) < 0) - err(1, "ioctl(PMIOSTART)"); - - value.pmcd_num = 0; - for (i = 0; i < loops; i++) { - if (ioctl(fd, PMIOSTOP, &num) < 0) - err(1, "ioctl(PMIOSTOP)"); - if (ioctl(fd, PMIOREAD, &value) < 0) - err(1, "ioctl(PMIOREAD)"); - buf[i] = value.pmcd_value; - if (ioctl(fd, PMIORESET, &value.pmcd_num) < 0) - err(1, "ioctl(PMIORESET)"); - if (ioctl(fd, PMIOSTART, &num) < 0) - err(1, "ioctl(PMIOSTART)"); - if (sleeptime) - sleep(sleeptime); - if (cmd) - system(cmd); - } - - if (ioctl(fd, PMIOSTOP, &num) < 0) - err(1, "ioctl(PMIOSTOP)"); - if (ioctl(fd, PMIOREAD, &value) < 0) - err(1, "ioctl(PMIOREAD)"); - buf[i] = value.pmcd_value; - if (ioctl(fd, PMIOTSTAMP, &now) < 0) - err(1, "ioctl(PMIOTSTAMP)"); - - total = 0; - for (i = 1; i <= loops; i++) { - printf("%d: %qd\n", i, buf[i]); - total += buf[i]; - } - printf("total: %f\nmean: %f\n", total, total / loops); - - printf("clocks (at %d-MHz): %qd\n", now.pmct_rate, - now.pmct_value - then.pmct_value); - - return 0; -} - -static int -getnum(const char *buf, int min, int max) -{ - char *ep; - long l; - - errno = 0; - l = strtol(buf, &ep, 0); - if (*buf && !*ep && !errno) { - if (l < min || l > max) { - errx(1, "%s: must be between %d and %d", - buf, min, max); - } - return (int)l; - } - - errx(1, "%s: parameter must be an integer", buf); -} - -static void -usage(const char *pname) -{ - fprintf(stderr, - "usage: %s [-eiou] [-c command] [-l nloops] [-m mask] [-s sleeptime]\n" - " [-U unit] counter\n", - pname); - exit(1); -} diff --git a/share/man/man4/man4.i386/Makefile b/share/man/man4/man4.i386/Makefile index ad9b3a01828c..1136de341947 100644 --- a/share/man/man4/man4.i386/Makefile +++ b/share/man/man4/man4.i386/Makefile @@ -6,7 +6,6 @@ MAN= apm.4 \ npx.4 \ pae.4 \ pbio.4 \ - perfmon.4 \ pnp.4 \ pnpbios.4 \ sbni.4 \ diff --git a/share/man/man4/man4.i386/perfmon.4 b/share/man/man4/man4.i386/perfmon.4 deleted file mode 100644 index 7a899e863f1b..000000000000 --- a/share/man/man4/man4.i386/perfmon.4 +++ /dev/null @@ -1,211 +0,0 @@ -.\" -.\" Copyright 1996 Massachusetts Institute of Technology -.\" -.\" Permission to use, copy, modify, and distribute this software and -.\" its documentation for any purpose and without fee is hereby -.\" granted, provided that both the above copyright notice and this -.\" permission notice appear in all copies, that both the above -.\" copyright notice and this permission notice appear in all -.\" supporting documentation, and that the name of M.I.T. not be used -.\" in advertising or publicity pertaining to distribution of the -.\" software without specific, written prior permission. M.I.T. makes -.\" no representations about the suitability of this software for any -.\" purpose. It is provided "as is" without express or implied -.\" warranty. -.\" -.\" THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS -.\" ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, -.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT -.\" SHALL M.I.T. 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. -.Dd March 26, 1996 -.Dt PERFMON 4 i386 -.Os -.Sh NAME -.Nm perfmon -.Nd CPU performance-monitoring interface -.Sh SYNOPSIS -.Cd cpu I586_CPU -.Cd cpu I686_CPU -.Cd options PERFMON -.Sh DESCRIPTION -The -.Nm -driver provides access to the internal performance-monitoring -capabilities of the -.Tn Intel -.Tn Pentium -and -.Tn "Pentium Pro" -CPUs. -These processors implement two internal counters which can be -configured to measure a variety of events for either count or duration -(in CPU cycles), as well as a cycle counter which counts clock cycles. -The -.Nm -driver provides a device-style interface to these capabilities. -.Pp -All access to the performance-monitoring counters is performed through -the special device file -.Dq Pa /dev/perfmon . -This device supports a number of -.Xr ioctl 2 -requests, defined in -.In machine/perfmon.h -along with the definitions of the various counters for both -.Tn Pentium -and -.Tn "Pentium Pro" -processors. -.Pp -.Sy NOTA BENE : -The set of available events differs from processor to processor. -It -is the responsibility of the programmer to ensure that the event -numbers used are the correct ones for the CPU type being measured. -.Pp -The following -.Xr ioctl 2 -requests are defined: -.Bl -tag -width PMIOTSTAMP -.It Dv PMIOSETUP -.Pq Li "struct pmc" -Set up a counter with parameters and flags defined in the structure. -The following fields are defined in -.Li struct pmc : -.Bl -tag -width "u_char pmc_eventx" -.It Li "int pmc_num" -the number of the counter in question; must be less than -.Dv NPMC -(currently 2). -.It Li "u_char pmc_event" -the particular event number to be monitored, as defined in -.In machine/perfmon.h . -.It Li "u_char pmc_unit" -the unit mask value, specific to the event type (see the -.Tn Intel -documentation). -.It Li "u_char pmc_flags" -flags modifying the operation of the counter (see below). -.It Li "u_char pmc_mask" -the counter mask value; essentially, this is a threshold used to -restrict the count to events lasting more (or less) than the specified -number of clocks. -.El -.Pp -The following -.Li pmc_flags -values are defined: -.Bl -tag -compact -width PMCF_USRxx -.It Dv PMCF_USR -count events in user mode -.It Dv PMCF_OS -count events in kernel mode -.It Dv PMCF_E -count number of events rather than their duration -.It Dv PMCF_INV -invert the sense of the counter mask comparison -.El -.It Dv PMIOGET -.Pq Li "struct pmc" -returns the current configuration of the specified counter. -.It Dv PMIOSTART -.It Dv PMIOSTOP -.Pq Li int -starts (stops) the specified counter. -Due to hardware deficiencies, -counters must be started and stopped in numerical order. -(That is to -say, counter 0 can never be stopped without first stopping counter 1.) -The driver will -.Em not -enforce this restriction (since it may not be present in future CPUs). -.It Dv PMIORESET -.Pq Li int -reset the specified counter to zero. -The counter should be stopped -with -.Dv PMIOSTOP -before it is reset. -All counters are automatically reset by -.Dv PMIOSETUP . -.It Dv PMIOREAD -.Pq Li "struct pmc_data" -get the current value of the counter. -The -.Li pmc_data -structure defines two fields: -.Pp -.Bl -tag -compact -width "quad_t pmcd_value" -.It Li "int pmcd_num" -the number of the counter to read -.It Li "quad_t pmcd_value" -the resulting value as a 64-bit signed integer -.El -.Pp -In the future, it may be possible to use the -.Li RDPMC -instruction on -.Tn "Pentium Pro" -processors to read the counters directly. -.It Dv PMIOTSTAMP -.Pq Li "struct pmc_tstamp" -read the time stamp counter. -The -.Li pmc_tstamp -structure defines two fields: -.Pp -.Bl -tag -compact -width "quad_t pmct_value" -.It Li "int pmct_rate" -the approximate rate of the counter, in MHz -.It Li "quad_t pmct_value" -the current value of the counter as a 64-bit integer -.El -.Pp -It is important to note that the counter rate, as provided in the -.Li pmct_rate -field, is often incorrect because of calibration difficulties and -non-integral clock rates. -This field should be considered more of a -hint or sanity-check than an actual representation of the rate of -clock ticks. -.El -.Sh FILES -.Bl -tag -compact -width "/usr/include/machine/perfmon.h" -.It Pa /dev/perfmon -character device interface to counters -.It Pa /usr/include/machine/perfmon.h -include file with definitions of structures and event types -.It Pa /usr/share/examples/perfmon -sample source code demonstrating use of all the -.Fn ioctl -commands -.El -.Sh SEE ALSO -.Xr ioctl 2 , -.Xr hwpmc 4 -.Rs -.%A Intel Corporation -.%B Pentium Pro Family Developer's Manual -.%D January 1996 -.%V vol. 3 -.%O Operating System Writer's Manual -.Re -.Sh HISTORY -The -.Nm -device first appeared in -.Fx 2.2 . -.Sh AUTHORS -The -.Nm -driver was written by -.An Garrett A. Wollman , -MIT Laboratory for Computer Science. diff --git a/share/man/man7/clocks.7 b/share/man/man7/clocks.7 index 3a218f844450..26283909f06d 100644 --- a/share/man/man7/clocks.7 +++ b/share/man/man7/clocks.7 @@ -141,10 +141,6 @@ Its frequency can be found using the .Va machdep.tsc_freq sysctl, if it is available. It is used to interpolate between values of the scheduling clock. -It can be accessed using the -.Dv PMIOTSTAMP -request of -.Xr perfmon 4 . .It The ACPI clock. This is a real clock/timer with a nominal frequency of 3579545. diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index e6c2089e2c1e..0e7a1f24be7e 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -91,7 +91,6 @@ i386/i386/mp_clock.c optional smp i386/i386/mp_machdep.c optional smp i386/i386/mpboot.S optional smp i386/i386/npx.c standard -i386/i386/perfmon.c optional perfmon i386/i386/pmap_base.c standard i386/i386/pmap_nopae.c standard i386/i386/pmap_pae.c standard diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index fbcea76527db..25bfb99c1fef 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -177,12 +177,6 @@ options CYRIX_CACHE_REALLY_WORKS # Debug options options NPX_DEBUG # enable npx debugging -# -# PERFMON causes the driver for Pentium/Pentium Pro performance counters -# to be compiled. See perfmon(4) for more information. -# -options PERFMON - # # Hints for the non-optional Numeric Processing eXtension driver. envvar hint.npx.0.flags="0x0" diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 7dbaded419e6..f9afb9afe45f 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -50,7 +50,6 @@ #include "opt_isa.h" #include "opt_kstack_pages.h" #include "opt_maxmem.h" -#include "opt_perfmon.h" #include "opt_platform.h" #include <sys/param.h> @@ -133,9 +132,6 @@ #include <x86/ucode.h> #include <machine/vm86.h> #include <x86/init.h> -#ifdef PERFMON -#include <machine/perfmon.h> -#endif #ifdef SMP #include <machine/smp.h> #endif @@ -245,9 +241,6 @@ cpu_startup(void *dummy) startrtclock(); printcpuinfo(); panicifcpuunsupported(); -#ifdef PERFMON - perfmon_init(); -#endif /* * Display physical memory if SMBIOS reports reasonable amount. diff --git a/sys/i386/i386/perfmon.c b/sys/i386/i386/perfmon.c deleted file mode 100644 index 5e6d37d7f5ed..000000000000 --- a/sys/i386/i386/perfmon.c +++ /dev/null @@ -1,402 +0,0 @@ -/*- - * Copyright 1996 Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby - * granted, provided that both the above copyright notice and this - * permission notice appear in all copies, that both the above - * copyright notice and this permission notice appear in all - * supporting documentation, and that the name of M.I.T. not be used - * in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. M.I.T. makes - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS - * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT - * SHALL M.I.T. 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/systm.h> -#include <sys/conf.h> -#include <sys/fcntl.h> -#include <sys/kernel.h> - -#ifndef SMP -#include <machine/cputypes.h> -#endif -#include <machine/clock.h> -#include <machine/perfmon.h> -#include <machine/specialreg.h> - -static int perfmon_inuse; -static int perfmon_cpuok; -#ifndef SMP -static int msr_ctl[NPMC]; -#endif -static int msr_pmc[NPMC]; -static unsigned int ctl_shadow[NPMC]; -static quad_t pmc_shadow[NPMC]; /* used when ctr is stopped on P5 */ -static int (*writectl)(int); -#ifndef SMP -static int writectl5(int); -static int writectl6(int); -#endif - -static d_close_t perfmon_close; -static d_open_t perfmon_open; -static d_ioctl_t perfmon_ioctl; - -/* - * XXX perfmon_init_dev(void *) is a split from the perfmon_init() function. - * This solves a problem for DEVFS users. It loads the "perfmon" driver after - * the DEVFS subsystem has been kicked into action. The SI_ORDER_ANY is to - * assure that it is the most lowest priority task which, guarantees the - * above. - */ -static void perfmon_init_dev(void *); -SYSINIT(cpu, SI_SUB_DRIVERS, SI_ORDER_ANY, perfmon_init_dev, NULL); - -static struct cdevsw perfmon_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = perfmon_open, - .d_close = perfmon_close, - .d_ioctl = perfmon_ioctl, - .d_name = "perfmon", -}; - -/* - * Must be called after cpu_class is set up. - */ -void -perfmon_init(void) -{ -#ifndef SMP - switch(cpu_class) { - case CPUCLASS_586: - perfmon_cpuok = 1; - msr_ctl[0] = MSR_P5_CESR; - msr_ctl[1] = MSR_P5_CESR; - msr_pmc[0] = MSR_P5_CTR0; - msr_pmc[1] = MSR_P5_CTR1; - writectl = writectl5; - break; - case CPUCLASS_686: - perfmon_cpuok = 1; - msr_ctl[0] = MSR_EVNTSEL0; - msr_ctl[1] = MSR_EVNTSEL1; - msr_pmc[0] = MSR_PERFCTR0; - msr_pmc[1] = MSR_PERFCTR1; - writectl = writectl6; - break; - - default: - perfmon_cpuok = 0; - break; - } -#endif /* SMP */ -} - -static void -perfmon_init_dev(void *dummy) -{ - make_dev(&perfmon_cdevsw, 32, UID_ROOT, GID_KMEM, 0640, "perfmon"); -} - -int -perfmon_avail(void) -{ - return perfmon_cpuok; -} - -int -perfmon_setup(int pmc, unsigned int control) -{ - register_t saveintr; - - if (pmc < 0 || pmc >= NPMC) - return EINVAL; - - perfmon_inuse |= (1 << pmc); - control &= ~(PMCF_SYS_FLAGS << 16); - saveintr = intr_disable(); - ctl_shadow[pmc] = control; - writectl(pmc); - wrmsr(msr_pmc[pmc], pmc_shadow[pmc] = 0); - intr_restore(saveintr); - return 0; -} - -int -perfmon_get(int pmc, unsigned int *control) -{ - if (pmc < 0 || pmc >= NPMC) - return EINVAL; - - if (perfmon_inuse & (1 << pmc)) { - *control = ctl_shadow[pmc]; - return 0; - } - return EBUSY; /* XXX reversed sense */ -} - -int -perfmon_fini(int pmc) -{ - if (pmc < 0 || pmc >= NPMC) - return EINVAL; - - if (perfmon_inuse & (1 << pmc)) { - perfmon_stop(pmc); - ctl_shadow[pmc] = 0; - perfmon_inuse &= ~(1 << pmc); - return 0; - } - return EBUSY; /* XXX reversed sense */ -} - -int -perfmon_start(int pmc) -{ - register_t saveintr; - - if (pmc < 0 || pmc >= NPMC) - return EINVAL; - - if (perfmon_inuse & (1 << pmc)) { - saveintr = intr_disable(); - ctl_shadow[pmc] |= (PMCF_EN << 16); - wrmsr(msr_pmc[pmc], pmc_shadow[pmc]); - writectl(pmc); - intr_restore(saveintr); - return 0; - } - return EBUSY; -} - -int -perfmon_stop(int pmc) -{ - register_t saveintr; - - if (pmc < 0 || pmc >= NPMC) - return EINVAL; - - if (perfmon_inuse & (1 << pmc)) { - saveintr = intr_disable(); - pmc_shadow[pmc] = rdmsr(msr_pmc[pmc]) & 0xffffffffffULL; - ctl_shadow[pmc] &= ~(PMCF_EN << 16); - writectl(pmc); - intr_restore(saveintr); - return 0; - } - return EBUSY; -} - -int -perfmon_read(int pmc, quad_t *val) -{ - if (pmc < 0 || pmc >= NPMC) - return EINVAL; - - if (perfmon_inuse & (1 << pmc)) { - if (ctl_shadow[pmc] & (PMCF_EN << 16)) - *val = rdmsr(msr_pmc[pmc]) & 0xffffffffffULL; - else - *val = pmc_shadow[pmc]; - return 0; - } - - return EBUSY; -} - -int -perfmon_reset(int pmc) -{ - if (pmc < 0 || pmc >= NPMC) - return EINVAL; - - if (perfmon_inuse & (1 << pmc)) { - wrmsr(msr_pmc[pmc], pmc_shadow[pmc] = 0); - return 0; - } - return EBUSY; -} - -#ifndef SMP -/* - * Unfortunately, the performance-monitoring registers are laid out - * differently in the P5 and P6. We keep everything in P6 format - * internally (except for the event code), and convert to P5 - * format as needed on those CPUs. The writectl function pointer - * is set up to point to one of these functions by perfmon_init(). - */ -int -writectl6(int pmc) -{ - if (pmc > 0 && !(ctl_shadow[pmc] & (PMCF_EN << 16))) { - wrmsr(msr_ctl[pmc], 0); - } else { - wrmsr(msr_ctl[pmc], ctl_shadow[pmc]); - } - return 0; -} - -#define P5FLAG_P 0x200 -#define P5FLAG_E 0x100 -#define P5FLAG_USR 0x80 -#define P5FLAG_OS 0x40 - -int -writectl5(int pmc) -{ - quad_t newval = 0; - - if (ctl_shadow[1] & (PMCF_EN << 16)) { - if (ctl_shadow[1] & (PMCF_USR << 16)) - newval |= P5FLAG_USR << 16; - if (ctl_shadow[1] & (PMCF_OS << 16)) - newval |= P5FLAG_OS << 16; - if (!(ctl_shadow[1] & (PMCF_E << 16))) - newval |= P5FLAG_E << 16; - newval |= (ctl_shadow[1] & 0x3f) << 16; - } - if (ctl_shadow[0] & (PMCF_EN << 16)) { - if (ctl_shadow[0] & (PMCF_USR << 16)) - newval |= P5FLAG_USR; - if (ctl_shadow[0] & (PMCF_OS << 16)) - newval |= P5FLAG_OS; - if (!(ctl_shadow[0] & (PMCF_E << 16))) - newval |= P5FLAG_E; - newval |= ctl_shadow[0] & 0x3f; - } - - wrmsr(msr_ctl[0], newval); - return 0; /* XXX should check for unimplemented bits */ -} -#endif /* !SMP */ - -/* - * Now the user-mode interface, called from a subdevice of mem.c. - */ -static int writer; -static int writerpmc; - -static int -perfmon_open(struct cdev *dev, int flags, int fmt, struct thread *td) -{ - if (!perfmon_cpuok) - return ENXIO; - - if (flags & FWRITE) { - if (writer) { - return EBUSY; - } else { - writer = 1; - writerpmc = 0; - } - } - return 0; -} - -static int -perfmon_close(struct cdev *dev, int flags, int fmt, struct thread *td) -{ - if (flags & FWRITE) { - int i; - - for (i = 0; i < NPMC; i++) { - if (writerpmc & (1 << i)) - perfmon_fini(i); - } - writer = 0; - } - return 0; -} - -static int -perfmon_ioctl(struct cdev *dev, u_long cmd, caddr_t param, int flags, struct thread *td) -{ - struct pmc *pmc; - struct pmc_data *pmcd; - struct pmc_tstamp *pmct; - uint64_t freq; - int *ip; - int rv; - - switch(cmd) { - case PMIOSETUP: - if (!(flags & FWRITE)) - return EPERM; - pmc = (struct pmc *)param; *** 340 LINES SKIPPED ***home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69eb9949.3a5d2.72b91820>
