Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Switch to per-CPU PMC results, and completely rewrite the pm...
details: https://anonhg.NetBSD.org/src/rev/6ec946443dab
branches: trunk
changeset: 352010:6ec946443dab
user: maxv <maxv%NetBSD.org@localhost>
date: Fri Mar 10 13:09:11 2017 +0000
description:
Switch to per-CPU PMC results, and completely rewrite the pmc(1) tool. Now
the PMCs are system-wide, fine-grained and more tunable by the user.
We don't do application tracking, since it would require to store the PMC
values in mdproc and starting/stopping the counters on each context switch.
While this doesn't seem to be particularly difficult to achieve, I don't
think it is really interesting; and if someone really wants to measure
the performance of an application, they can simply schedctl it to a cpu
and look at the PMC results for this cpu.
Note that several options are implemented but not yet used.
diffstat:
sys/arch/i386/i386/pmc.c | 49 ++--
sys/arch/x86/include/sysarch.h | 15 +-
usr.bin/pmc/pmc.1 | 133 +++++++++-----
usr.bin/pmc/pmc.c | 383 ++++++++++++++++++++++++----------------
4 files changed, 352 insertions(+), 228 deletions(-)
diffs (truncated from 832 to 300 lines):
diff -r ca6249ee1fd0 -r 6ec946443dab sys/arch/i386/i386/pmc.c
--- a/sys/arch/i386/i386/pmc.c Fri Mar 10 09:13:49 2017 +0000
+++ b/sys/arch/i386/i386/pmc.c Fri Mar 10 13:09:11 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmc.c,v 1.24 2017/03/08 16:42:27 maxv Exp $ */
+/* $NetBSD: pmc.c,v 1.25 2017/03/10 13:09:11 maxv Exp $ */
/*
* Copyright (c) 2017 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmc.c,v 1.24 2017/03/08 16:42:27 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmc.c,v 1.25 2017/03/10 13:09:11 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -88,17 +88,15 @@
uint32_t evtmsr; /* event selector MSR */
uint64_t evtval; /* event selector value */
uint32_t ctrmsr; /* counter MSR */
- uint64_t ctrval; /* counter value */
- uint64_t tsc;
+ uint64_t ctrval; /* initial counter value */
} pmc_state_t;
-static uint64_t pmc_val_cpus[MAXCPUS] __aligned(CACHE_LINE_SIZE);
+static x86_pmc_cpuval_t pmc_val_cpus[MAXCPUS] __aligned(CACHE_LINE_SIZE);
static kmutex_t pmc_lock;
static pmc_state_t pmc_state[PMC_NCOUNTERS];
static int pmc_ncounters __read_mostly;
static int pmc_type __read_mostly;
-static int pmc_flags __read_mostly;
static void
pmc_read_cpu(void *arg1, void *arg2)
@@ -106,29 +104,25 @@
pmc_state_t *pmc = (pmc_state_t *)arg1;
struct cpu_info *ci = curcpu();
- pmc_val_cpus[cpu_index(ci)] = rdmsr(pmc->ctrmsr) & 0xffffffffffULL;
+ pmc_val_cpus[cpu_index(ci)].ctrval =
+ rdmsr(pmc->ctrmsr) & 0xffffffffffULL;
+ pmc_val_cpus[cpu_index(ci)].overfl = 0;
}
static void
pmc_read(pmc_state_t *pmc)
{
uint64_t xc;
- size_t i;
xc = xc_broadcast(0, pmc_read_cpu, pmc, NULL);
xc_wait(xc);
-
- pmc->ctrval = 0;
- for (i = 0; i < ncpu; i++) {
- /* XXX: really shitty */
- pmc->ctrval += pmc_val_cpus[i];
- }
}
static void
pmc_apply_cpu(void *arg1, void *arg2)
{
pmc_state_t *pmc = (pmc_state_t *)arg1;
+ struct cpu_info *ci = curcpu();
wrmsr(pmc->ctrmsr, pmc->ctrval);
switch (pmc_type) {
@@ -142,6 +136,9 @@
wrmsr(pmc->evtmsr, pmc->evtval);
break;
}
+
+ pmc_val_cpus[cpu_index(ci)].ctrval = 0;
+ pmc_val_cpus[cpu_index(ci)].overfl = 0;
}
static void
@@ -210,6 +207,7 @@
{
pmc->running = false;
pmc->evtval = 0;
+ pmc->ctrval = 0;
pmc_apply(pmc);
}
@@ -262,9 +260,6 @@
break;
}
- if (pmc_type != PMC_TYPE_NONE && cpu_hascounter())
- pmc_flags |= PMC_INFO_HASTSC;
-
mutex_init(&pmc_lock, MUTEX_DEFAULT, IPL_NONE);
}
@@ -277,7 +272,7 @@
rv.vers = PMC_VERSION;
rv.type = pmc_type;
- rv.flags = pmc_flags;
+ rv.nctrs = pmc_ncounters;
return copyout(&rv, uargs, sizeof(rv));
}
@@ -330,6 +325,7 @@
{
struct x86_pmc_read_args args;
pmc_state_t *pmc;
+ size_t nval;
int error;
if (pmc_type == PMC_TYPE_NONE)
@@ -341,20 +337,27 @@
if (args.counter >= pmc_ncounters)
return EINVAL;
+ if (args.values == NULL)
+ return EINVAL;
+ nval = MIN(ncpu, args.nval);
+
pmc = &pmc_state[args.counter];
mutex_enter(&pmc_lock);
if (pmc->running) {
pmc_read(pmc);
- if (pmc_flags & PMC_INFO_HASTSC)
- pmc->tsc = cpu_counter();
+ error = copyout(&pmc_val_cpus, args.values,
+ nval * sizeof(x86_pmc_cpuval_t));
+ args.nval = nval;
+ } else {
+ error = ENOENT;
}
- args.val = pmc->ctrval;
- args.time = pmc->tsc;
-
mutex_exit(&pmc_lock);
+ if (error)
+ return error;
+
return copyout(&args, uargs, sizeof(args));
}
diff -r ca6249ee1fd0 -r 6ec946443dab sys/arch/x86/include/sysarch.h
--- a/sys/arch/x86/include/sysarch.h Fri Mar 10 09:13:49 2017 +0000
+++ b/sys/arch/x86/include/sysarch.h Fri Mar 10 13:09:11 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sysarch.h,v 1.10 2017/03/08 16:42:27 maxv Exp $ */
+/* $NetBSD: sysarch.h,v 1.11 2017/03/10 13:09:11 maxv Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -133,7 +133,7 @@
struct _X86_SYSARCH_L(pmc_info_args) {
int vers;
int type;
- int flags;
+ uint32_t nctrs;
};
#define PMC_VERSION 1
@@ -162,10 +162,15 @@
#define PMC_SETUP_EDGE 0x04
#define PMC_SETUP_INV 0x08
+typedef struct {
+ uint64_t ctrval;
+ uint32_t overfl;
+} x86_pmc_cpuval_t;
+
struct _X86_SYSARCH_L(pmc_read_args) {
- int counter;
- uint64_t val;
- uint64_t time;
+ uint32_t counter;
+ x86_pmc_cpuval_t *values;
+ uint32_t nval;
};
struct mtrr;
diff -r ca6249ee1fd0 -r 6ec946443dab usr.bin/pmc/pmc.1
--- a/usr.bin/pmc/pmc.1 Fri Mar 10 09:13:49 2017 +0000
+++ b/usr.bin/pmc/pmc.1 Fri Mar 10 13:09:11 2017 +0000
@@ -1,4 +1,31 @@
-.\" $NetBSD: pmc.1,v 1.9 2014/03/18 18:20:45 riastradh Exp $
+.\" $NetBSD: pmc.1,v 1.10 2017/03/10 13:09:11 maxv Exp $
+.\"
+.\" Copyright (c) 2017 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Maxime Villard.
+.\"
+.\" 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 THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
.\"
.\" Copyright (c) 2000 Zembu Labs, Inc.
.\" All rights reserved.
@@ -31,77 +58,87 @@
.\" (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 October 24, 2000
+.Dd March 10, 2017
.Dt PMC 1
.Os
.Sh NAME
.Nm pmc
-.Nd performance-monitoring counter interface for command execution
+.Nd performance-monitoring counter interface
.Sh SYNOPSIS
-.Nm
-.Fl h
-.Nm
-.Fl C
-.Nm
-.Fl c
-.Ar event
+.Nm pmc
.Ar command
-.Oo
-.Ar options
-.Ar ...
-.Oc
+.Op Ar arguments
.Sh DESCRIPTION
+The
.Nm
-is a means of using a processor's performance-monitoring counter (PMC)
-facility to measure various aspects of a program's execution.
-It is
-meant to be used in a fashion similar to
-.Xr time 1 .
+command can be used to control and inspect the state of CPUs in the system.
.Pp
-The arguments are as follows:
-.Bl -tag -width indent
-.It Fl h
-Display a list of performance counter events available on
-the system.
-.It Fl C
-Cancel any performance counters that are currently running.
-.It Fl c Ar event
-Count the event specified by
-.Ar event
-while running the command.
+The first argument,
+.Ar command ,
+specifies the action to take.
+Valid commands are:
+.Bl -tag -width offline
+.It list
+Display a list of performance counter events available on the system.
+.It start Ar name:option Op Ar name:option ...
+Start one or several counters.
+.Ar name
+specifies the name of the event to count; it must be taken from the list of
+available events.
+.Ar option
+specifies the source of the event; it must be a combination of
+.Ar u
+(userland) and
+.Ar k
+(kernel).
+.It stop
+Stop any performance counters that are currently running, and display the
+values of these counters.
.El
+.Sh EXAMPLES
+.Pp
+The following command prints the available counters.
+.Dl $ pmc list
+.Pp
+The following command starts two counters.
+The former will count the 'l2cache-access' events that are triggered from
Home |
Main Index |
Thread Index |
Old Index