Module Name:    src
Committed By:   maxv
Date:           Fri Mar 10 14:40:56 UTC 2017

Modified Files:
        src/sys/arch/amd64/include: pmc.h
        src/sys/arch/i386/conf: files.i386
        src/sys/arch/x86/conf: files.x86
        src/sys/arch/xen/conf: files.xen
Added Files:
        src/sys/arch/x86/x86: pmc.c
Removed Files:
        src/sys/arch/i386/i386: pmc.c

Log Message:
Move pmc.c into x86/, it can be shared with amd64.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/amd64/include/pmc.h
cvs rdiff -u -r1.377 -r1.378 src/sys/arch/i386/conf/files.i386
cvs rdiff -u -r1.25 -r0 src/sys/arch/i386/i386/pmc.c
cvs rdiff -u -r1.87 -r1.88 src/sys/arch/x86/conf/files.x86
cvs rdiff -u -r0 -r1.1 src/sys/arch/x86/x86/pmc.c
cvs rdiff -u -r1.144 -r1.145 src/sys/arch/xen/conf/files.xen

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/amd64/include/pmc.h
diff -u src/sys/arch/amd64/include/pmc.h:1.3 src/sys/arch/amd64/include/pmc.h:1.4
--- src/sys/arch/amd64/include/pmc.h:1.3	Sat Feb 18 14:43:35 2017
+++ src/sys/arch/amd64/include/pmc.h	Fri Mar 10 14:40:56 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmc.h,v 1.3 2017/02/18 14:43:35 maxv Exp $	*/
+/*	$NetBSD: pmc.h,v 1.4 2017/03/10 14:40:56 maxv Exp $	*/
 
 /*-
  * Copyright (c) 2000 Zembu Labs, Inc.
@@ -34,17 +34,14 @@
  */
 
 #ifdef _KERNEL
-/*
- * LEGACY PMC support
- */
-struct x86_64_pmc_info_args;
-int	pmc_info(struct proc *, struct x86_64_pmc_info_args *,
+struct x86_pmc_info_args;
+struct x86_pmc_startstop_args;
+struct x86_pmc_read_args;
+void pmc_init(void);
+int sys_pmc_info(struct lwp *, struct x86_pmc_info_args *,
     register_t *);
-struct x86_64_pmc_startstop_args;
-int	pmc_startstop(struct proc *, struct x86_64_pmc_startstop_args *,
+int sys_pmc_startstop(struct lwp *, struct x86_pmc_startstop_args *,
     register_t *);
-struct x86_64_pmc_read_args;
-int	pmc_read(struct proc *, struct x86_64_pmc_read_args *,
+int sys_pmc_read(struct lwp *, struct x86_pmc_read_args *,
     register_t *);
-/* END LEGACY PMC SUPPORT */
 #endif

Index: src/sys/arch/i386/conf/files.i386
diff -u src/sys/arch/i386/conf/files.i386:1.377 src/sys/arch/i386/conf/files.i386:1.378
--- src/sys/arch/i386/conf/files.i386:1.377	Fri Feb 17 12:10:40 2017
+++ src/sys/arch/i386/conf/files.i386	Fri Mar 10 14:40:56 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: files.i386,v 1.377 2017/02/17 12:10:40 maxv Exp $
+#	$NetBSD: files.i386,v 1.378 2017/03/10 14:40:56 maxv Exp $
 #
 # new style config file for i386 architecture
 #
@@ -74,7 +74,6 @@ file	arch/i386/i386/kobj_machdep.c	modul
 file	arch/i386/i386/machdep.c
 file 	arch/i386/i386/longrun.c
 file	arch/i386/i386/mtrr_k6.c	mtrr
-file	arch/i386/i386/pmc.c
 file	arch/i386/i386/process_machdep.c
 file	arch/x86/x86/convert_xmm_s87.c
 file	arch/i386/i386/trap.c

Index: src/sys/arch/x86/conf/files.x86
diff -u src/sys/arch/x86/conf/files.x86:1.87 src/sys/arch/x86/conf/files.x86:1.88
--- src/sys/arch/x86/conf/files.x86:1.87	Sat Feb 27 00:09:45 2016
+++ src/sys/arch/x86/conf/files.x86	Fri Mar 10 14:40:56 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: files.x86,v 1.87 2016/02/27 00:09:45 tls Exp $
+#	$NetBSD: files.x86,v 1.88 2017/03/10 14:40:56 maxv Exp $
 
 # options for MP configuration through the MP spec
 defflag opt_mpbios.h MPBIOS MPVERBOSE MPDEBUG MPBIOS_SCANPCI
@@ -88,6 +88,7 @@ file 	arch/x86/x86/patch.c		machdep
 file	arch/x86/x86/platform.c		machdep
 file 	arch/x86/x86/pmap.c		machdep
 file 	arch/x86/x86/pmap_tlb.c		machdep
+file 	arch/x86/x86/pmc.c		machdep
 file	arch/x86/x86/procfs_machdep.c	procfs
 file	arch/x86/x86/sys_machdep.c	machdep
 file	arch/x86/x86/syscall.c		machdep

Index: src/sys/arch/xen/conf/files.xen
diff -u src/sys/arch/xen/conf/files.xen:1.144 src/sys/arch/xen/conf/files.xen:1.145
--- src/sys/arch/xen/conf/files.xen:1.144	Fri Feb 17 21:51:47 2017
+++ src/sys/arch/xen/conf/files.xen	Fri Mar 10 14:40:56 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: files.xen,v 1.144 2017/02/17 21:51:47 kre Exp $
+#	$NetBSD: files.xen,v 1.145 2017/03/10 14:40:56 maxv Exp $
 #	NetBSD: files.x86,v 1.10 2003/10/08 17:30:00 bouyer Exp 
 #	NetBSD: files.i386,v 1.254 2004/03/25 23:32:10 jmc Exp 
 
@@ -50,7 +50,6 @@ file	arch/i386/i386/kobj_machdep.c	modul
 file	arch/i386/i386/machdep.c
 file	arch/i386/i386/longrun.c
 file	arch/i386/i386/mtrr_k6.c	mtrr
-file	arch/i386/i386/pmc.c
 file	arch/i386/i386/process_machdep.c
 file	arch/i386/i386/trap.c
 file	arch/i386/i386/lock_stubs.S
@@ -141,6 +140,7 @@ file	arch/xen/x86/intr.c		machdep
 file	arch/xen/x86/xen_ipi.c		multiprocessor
 file	arch/x86/x86/pmap.c		machdep
 file	arch/x86/x86/pmap_tlb.c		machdep
+file	arch/x86/x86/pmc.c		machdep
 file	arch/x86/x86/procfs_machdep.c	procfs
 file	arch/x86/x86/sys_machdep.c	machdep
 file	arch/x86/x86/tsc.c		machdep

Added files:

Index: src/sys/arch/x86/x86/pmc.c
diff -u /dev/null src/sys/arch/x86/x86/pmc.c:1.1
--- /dev/null	Fri Mar 10 14:40:56 2017
+++ src/sys/arch/x86/x86/pmc.c	Fri Mar 10 14:40:56 2017
@@ -0,0 +1,363 @@
+/*	$NetBSD: pmc.c,v 1.1 2017/03/10 14:40:56 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.
+ *
+ * Author: Jason R. Thorpe <[email protected]>
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Zembu Labs, Inc.
+ * 4. Neither the name of Zembu Labs nor the names of its employees may
+ *    be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ZEMBU LABS, INC. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAR-
+ * RANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DIS-
+ * CLAIMED.  IN NO EVENT SHALL ZEMBU LABS 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.
+ */
+
+/*
+ * Interface to x86 CPU Performance Counters.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: pmc.c,v 1.1 2017/03/10 14:40:56 maxv Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/cpu.h>
+#include <sys/xcall.h>
+
+#include <machine/cpufunc.h>
+#include <machine/cpuvar.h>
+#include <machine/specialreg.h>
+#include <machine/sysarch.h>
+#include <machine/pmc.h>
+#include <machine/cpu_counter.h>
+#include <machine/cputypes.h>
+
+typedef struct {
+	bool running;
+	uint32_t evtmsr;	/* event selector MSR */
+	uint64_t evtval;	/* event selector value */
+	uint32_t ctrmsr;	/* counter MSR */
+	uint64_t ctrval;	/* initial counter value */
+} pmc_state_t;
+
+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 void
+pmc_read_cpu(void *arg1, void *arg2)
+{
+	pmc_state_t *pmc = (pmc_state_t *)arg1;
+	struct cpu_info *ci = curcpu();
+
+	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;
+
+	xc = xc_broadcast(0, pmc_read_cpu, pmc, NULL);
+	xc_wait(xc);
+}
+
+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) {
+	case PMC_TYPE_I586:
+		wrmsr(MSR_CESR, pmc_state[0].evtval |
+		    (pmc_state[1].evtval << 16));
+		break;
+
+	case PMC_TYPE_I686:
+	case PMC_TYPE_K7:
+		wrmsr(pmc->evtmsr, pmc->evtval);
+		break;
+	}
+
+	pmc_val_cpus[cpu_index(ci)].ctrval = 0;
+	pmc_val_cpus[cpu_index(ci)].overfl = 0;
+}
+
+static void
+pmc_apply(pmc_state_t *pmc)
+{
+	uint64_t xc;
+
+	xc = xc_broadcast(0, pmc_apply_cpu, pmc, NULL);
+	xc_wait(xc);
+}
+
+static void
+pmc_start(pmc_state_t *pmc, struct x86_pmc_startstop_args *args)
+{
+	uint64_t event, unit;
+
+	pmc->running = true;
+
+	/*
+	 * Initialize the counter MSR.
+	 */
+	pmc->ctrval = args->val;
+
+	/*
+	 * Initialize the event MSR.
+	 */
+	switch (pmc_type) {
+	case PMC_TYPE_I586:
+		pmc->evtval = args->event |
+		    ((args->flags & PMC_SETUP_KERNEL) ? PMC5_CESR_OS : 0) |
+		    ((args->flags & PMC_SETUP_USER) ? PMC5_CESR_USR : 0) |
+		    ((args->flags & PMC_SETUP_EDGE) ? PMC5_CESR_E : 0);
+		break;
+
+	case PMC_TYPE_I686:
+		pmc->evtval = args->event | PMC6_EVTSEL_EN |
+		    (args->unit << PMC6_EVTSEL_UNIT_SHIFT) |
+		    ((args->flags & PMC_SETUP_KERNEL) ? PMC6_EVTSEL_OS : 0) |
+		    ((args->flags & PMC_SETUP_USER) ? PMC6_EVTSEL_USR : 0) |
+		    ((args->flags & PMC_SETUP_EDGE) ? PMC6_EVTSEL_E : 0) |
+		    ((args->flags & PMC_SETUP_INV) ? PMC6_EVTSEL_INV : 0) |
+		    (args->compare << PMC6_EVTSEL_COUNTER_MASK_SHIFT);
+		break;
+
+	case PMC_TYPE_K7:
+		event = (args->event & K7_EVTSEL_EVENT);
+		unit = (args->unit << K7_EVTSEL_UNIT_SHIFT) &
+		    K7_EVTSEL_UNIT;
+		pmc->evtval = event | unit | K7_EVTSEL_EN |
+		    ((args->flags & PMC_SETUP_KERNEL) ? K7_EVTSEL_OS : 0) |
+		    ((args->flags & PMC_SETUP_USER) ? K7_EVTSEL_USR : 0) |
+		    ((args->flags & PMC_SETUP_EDGE) ? K7_EVTSEL_E : 0) |
+		    ((args->flags & PMC_SETUP_INV) ? K7_EVTSEL_INV : 0) |
+		    (args->compare << K7_EVTSEL_COUNTER_MASK_SHIFT);
+		break;
+	}
+
+	/*
+	 * Apply the changes.
+	 */
+	pmc_apply(pmc);
+}
+
+static void
+pmc_stop(pmc_state_t *pmc, struct x86_pmc_startstop_args *args)
+{
+	pmc->running = false;
+	pmc->evtval = 0;
+	pmc->ctrval = 0;
+	pmc_apply(pmc);
+}
+
+void
+pmc_init(void)
+{
+	const char *cpu_vendorstr;
+	struct cpu_info *ci;
+
+	pmc_type = PMC_TYPE_NONE;
+
+	ci = curcpu();
+	cpu_vendorstr = (char *)ci->ci_vendor;
+
+	switch (cpu_class) {
+	case CPUCLASS_586:
+		if (strncmp(cpu_vendorstr, "GenuineIntel", 12) == 0) {
+			pmc_type = PMC_TYPE_I586;
+			pmc_ncounters = 2;
+			pmc_state[0].ctrmsr = MSR_CTR0;
+			pmc_state[1].ctrmsr = MSR_CTR1;
+			break;
+		}
+
+	case CPUCLASS_686:
+		if (strncmp(cpu_vendorstr, "GenuineIntel", 12) == 0) {
+			/* Right now we're missing Pentium 4 support. */
+			if (cpuid_level == -1 ||
+			    CPUID_TO_FAMILY(ci->ci_signature) == CPU_FAMILY_P4)
+				break;
+			pmc_type = PMC_TYPE_I686;
+			pmc_ncounters = 2;
+			pmc_state[0].evtmsr = MSR_EVNTSEL0;
+			pmc_state[0].ctrmsr = MSR_PERFCTR0;
+			pmc_state[1].evtmsr = MSR_EVNTSEL1;
+			pmc_state[1].ctrmsr = MSR_PERFCTR1;
+		} else if (strncmp(cpu_vendorstr, "AuthenticAMD", 12) == 0) {
+			/* XXX: make sure it is at least K7 */
+			pmc_type = PMC_TYPE_K7;
+			pmc_ncounters = 4;
+			pmc_state[0].evtmsr = MSR_K7_EVNTSEL0;
+			pmc_state[0].ctrmsr = MSR_K7_PERFCTR0;
+			pmc_state[1].evtmsr = MSR_K7_EVNTSEL1;
+			pmc_state[1].ctrmsr = MSR_K7_PERFCTR1;
+			pmc_state[2].evtmsr = MSR_K7_EVNTSEL2;
+			pmc_state[2].ctrmsr = MSR_K7_PERFCTR2;
+			pmc_state[3].evtmsr = MSR_K7_EVNTSEL3;
+			pmc_state[3].ctrmsr = MSR_K7_PERFCTR3;
+		}
+		break;
+	}
+
+	mutex_init(&pmc_lock, MUTEX_DEFAULT, IPL_NONE);
+}
+
+int
+sys_pmc_info(struct lwp *l, struct x86_pmc_info_args *uargs, register_t *retval)
+{
+	struct x86_pmc_info_args rv;
+
+	memset(&rv, 0, sizeof(rv));
+
+	rv.vers = PMC_VERSION;
+	rv.type = pmc_type;
+	rv.nctrs = pmc_ncounters;
+
+	return copyout(&rv, uargs, sizeof(rv));
+}
+
+int
+sys_pmc_startstop(struct lwp *l, struct x86_pmc_startstop_args *uargs,
+    register_t *retval)
+{
+	struct x86_pmc_startstop_args args;
+	pmc_state_t *pmc;
+	bool start;
+	int error;
+
+	if (pmc_type == PMC_TYPE_NONE)
+		return ENODEV;
+
+	error = copyin(uargs, &args, sizeof(args));
+	if (error)
+		return error;
+
+	if (args.counter >= pmc_ncounters)
+		return EINVAL;
+
+	start = (args.flags & (PMC_SETUP_KERNEL|PMC_SETUP_USER)) != 0;
+	pmc = &pmc_state[args.counter];
+
+	mutex_enter(&pmc_lock);
+
+	if (start && pmc->running) {
+		mutex_exit(&pmc_lock);
+		return EBUSY;
+	} else if (!start && !pmc->running) {
+		mutex_exit(&pmc_lock);
+		return 0;
+	}
+
+	if (start) {
+		pmc_start(pmc, &args);
+	} else {
+		pmc_stop(pmc, &args);
+	}
+
+	mutex_exit(&pmc_lock);
+
+	return 0;
+}
+
+int
+sys_pmc_read(struct lwp *l, struct x86_pmc_read_args *uargs, register_t *retval)
+{
+	struct x86_pmc_read_args args;
+	pmc_state_t *pmc;
+	size_t nval;
+	int error;
+
+	if (pmc_type == PMC_TYPE_NONE)
+		return ENODEV;
+
+	error = copyin(uargs, &args, sizeof(args));
+	if (error)
+		return error;
+
+	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);
+		error = copyout(&pmc_val_cpus, args.values,
+		    nval * sizeof(x86_pmc_cpuval_t));
+		args.nval = nval;
+	} else {
+		error = ENOENT;
+	}
+
+	mutex_exit(&pmc_lock);
+
+	if (error)
+		return error;
+
+	return copyout(&args, uargs, sizeof(args));
+}

Reply via email to