Module Name:    src
Committed By:   maxv
Date:           Fri Feb 17 12:10:40 UTC 2017

Modified Files:
        src/sys/arch/i386/conf: GENERIC files.i386
        src/sys/arch/i386/i386: machdep.c pmc.c
        src/sys/arch/i386/include: pmc.h
        src/sys/arch/x86/x86: sys_machdep.c

Log Message:
Support PMCs on multi-processor systems. Still several things to fix, but
at least it works a little. Will be improved and moved into x86/ soon.


To generate a diff of this commit:
cvs rdiff -u -r1.1146 -r1.1147 src/sys/arch/i386/conf/GENERIC
cvs rdiff -u -r1.376 -r1.377 src/sys/arch/i386/conf/files.i386
cvs rdiff -u -r1.778 -r1.779 src/sys/arch/i386/i386/machdep.c
cvs rdiff -u -r1.21 -r1.22 src/sys/arch/i386/i386/pmc.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/i386/include/pmc.h
cvs rdiff -u -r1.32 -r1.33 src/sys/arch/x86/x86/sys_machdep.c

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/i386/conf/GENERIC
diff -u src/sys/arch/i386/conf/GENERIC:1.1146 src/sys/arch/i386/conf/GENERIC:1.1147
--- src/sys/arch/i386/conf/GENERIC:1.1146	Thu Jan 12 05:24:36 2017
+++ src/sys/arch/i386/conf/GENERIC	Fri Feb 17 12:10:40 2017
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.1146 2017/01/12 05:24:36 ryo Exp $
+# $NetBSD: GENERIC,v 1.1147 2017/02/17 12:10:40 maxv Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@ include 	"arch/i386/conf/std.i386"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"GENERIC-$Revision: 1.1146 $"
+#ident		"GENERIC-$Revision: 1.1147 $"
 
 maxusers	64		# estimated number of users
 
@@ -42,7 +42,6 @@ viac7temp*	at cpu?		# VIA C7 temperature
 vmt0		at cpu0		# VMware Tools
 
 options 	MTRR		# memory-type range register syscall support
-# doesn't work with MP just yet..
 #options 	PERFCTRS	# performance-monitoring counters support
 
 options 	MULTIBOOT	# Multiboot support (see multiboot(8))

Index: src/sys/arch/i386/conf/files.i386
diff -u src/sys/arch/i386/conf/files.i386:1.376 src/sys/arch/i386/conf/files.i386:1.377
--- src/sys/arch/i386/conf/files.i386:1.376	Thu Dec 15 12:04:18 2016
+++ src/sys/arch/i386/conf/files.i386	Fri Feb 17 12:10:40 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: files.i386,v 1.376 2016/12/15 12:04:18 kamil Exp $
+#	$NetBSD: files.i386,v 1.377 2017/02/17 12:10:40 maxv Exp $
 #
 # new style config file for i386 architecture
 #
@@ -74,6 +74,7 @@ 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
@@ -83,8 +84,6 @@ file	arch/x86/x86/dbregs.c
 
 file	arch/i386/i386/mptramp.S	multiprocessor
 
-file	arch/i386/i386/pmc.c		perfctrs
-
 file	crypto/des/arch/i386/des_enc.S		des
 file	crypto/des/arch/i386/des_cbc.S		des
 

Index: src/sys/arch/i386/i386/machdep.c
diff -u src/sys/arch/i386/i386/machdep.c:1.778 src/sys/arch/i386/i386/machdep.c:1.779
--- src/sys/arch/i386/i386/machdep.c:1.778	Sun Feb  5 10:42:21 2017
+++ src/sys/arch/i386/i386/machdep.c	Fri Feb 17 12:10:40 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.778 2017/02/05 10:42:21 maxv Exp $	*/
+/*	$NetBSD: machdep.c,v 1.779 2017/02/17 12:10:40 maxv Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.778 2017/02/05 10:42:21 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.779 2017/02/17 12:10:40 maxv Exp $");
 
 #include "opt_beep.h"
 #include "opt_compat_ibcs2.h"
@@ -135,6 +135,7 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 
 #include <machine/intr.h>
 #include <machine/kcore.h>
 #include <machine/pio.h>
+#include <machine/pmc.h>
 #include <machine/psl.h>
 #include <machine/reg.h>
 #include <machine/specialreg.h>
@@ -1402,6 +1403,8 @@ init386(paddr_t first_avail)
 	}
 
 	rw_init(&svr4_fasttrap_lock);
+
+	pmc_init();
 }
 
 #include <dev/ic/mc146818reg.h>		/* for NVRAM POST */

Index: src/sys/arch/i386/i386/pmc.c
diff -u src/sys/arch/i386/i386/pmc.c:1.21 src/sys/arch/i386/i386/pmc.c:1.22
--- src/sys/arch/i386/i386/pmc.c:1.21	Thu Nov 21 22:04:40 2013
+++ src/sys/arch/i386/i386/pmc.c	Fri Feb 17 12:10:40 2017
@@ -1,6 +1,35 @@
-/*	$NetBSD: pmc.c,v 1.21 2013/11/21 22:04:40 riz Exp $	*/
+/*	$NetBSD: pmc.c,v 1.22 2017/02/17 12:10:40 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.
  *
@@ -38,11 +67,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmc.c,v 1.21 2013/11/21 22:04:40 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmc.c,v 1.22 2017/02/17 12:10:40 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>
@@ -52,37 +83,142 @@ __KERNEL_RCSID(0, "$NetBSD: pmc.c,v 1.21
 #include <machine/cpu_counter.h>
 #include <machine/cputypes.h>
 
-static int pmc_initialized;
-static int pmc_ncounters;
-static int pmc_type;
-static int pmc_flags;
-
-static struct pmc_state {
-	uint64_t pmcs_val;
-	uint64_t pmcs_tsc;
-	uint64_t pmcs_control;
-	uint32_t pmcs_ctrmsr;
-} pmc_state[PMC_NCOUNTERS];
+typedef struct {
+	bool running;
+	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;
+} pmc_state_t;
+
+static uint64_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)
+{
+	pmc_state_t *pmc = (pmc_state_t *)arg1;
+	struct cpu_info *ci = curcpu();
+
+	pmc_val_cpus[cpu_index(ci)] = rdmsr(pmc->ctrmsr) & 0xffffffffffULL;
+}
+
+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;
+
+	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;
+	}
+}
+
+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)
+{
+	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;
 
-static int pmc_running;
+	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:
+		args->event &= K7_EVTSEL_EVENT;
+		args->unit = (args->unit << K7_EVTSEL_UNIT_SHIFT) &
+		    K7_EVTSEL_UNIT;
+		pmc->evtval = args->event | args->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_apply(pmc);
+}
+
+void
 pmc_init(void)
 {
 	const char *cpu_vendorstr;
 	struct cpu_info *ci;
 
-	if (pmc_initialized)
-		return;
-
 	pmc_type = PMC_TYPE_NONE;
 
-#ifdef MULTIPROCESSOR
-	/* XXX */
-	if (ncpu > 1)
-		goto done;
-#endif
-
 	ci = curcpu();
 	cpu_vendorstr = (char *)ci->ci_vendor;
 
@@ -91,34 +227,35 @@ pmc_init(void)
 		if (strncmp(cpu_vendorstr, "GenuineIntel", 12) == 0) {
 			pmc_type = PMC_TYPE_I586;
 			pmc_ncounters = 2;
-			pmc_state[0].pmcs_ctrmsr = MSR_CTR0;
-			pmc_state[1].pmcs_ctrmsr = MSR_CTR1;
+			pmc_state[0].ctrmsr = MSR_CTR0;
+			pmc_state[1].ctrmsr = MSR_CTR1;
 			break;
 		}
 
 	case CPUCLASS_686:
 		if (strncmp(cpu_vendorstr, "GenuineIntel", 12) == 0) {
-
-			/*
-			 * Figure out what we support; right now
-			 * we're missing Pentium 4 support.
-			 */
+			/* 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].pmcs_ctrmsr = MSR_PERFCTR0;
-			pmc_state[1].pmcs_ctrmsr = MSR_PERFCTR1;
-		} else if (strncmp(cpu_vendorstr, "AuthenticAMD",
-			   12) == 0) {
+			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].pmcs_ctrmsr = MSR_K7_PERFCTR0;
-			pmc_state[1].pmcs_ctrmsr = MSR_K7_PERFCTR1;
-			pmc_state[2].pmcs_ctrmsr = MSR_K7_PERFCTR2;
-			pmc_state[3].pmcs_ctrmsr = MSR_K7_PERFCTR3;
+			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;
 	}
@@ -126,160 +263,95 @@ pmc_init(void)
 	if (pmc_type != PMC_TYPE_NONE && cpu_hascounter())
 		pmc_flags |= PMC_INFO_HASTSC;
 
-#ifdef MULTIPROCESSOR
-done:
-#endif
-	pmc_initialized = 1;
+	mutex_init(&pmc_lock, MUTEX_DEFAULT, IPL_NONE);
 }
 
 int
-pmc_info(struct lwp *l, struct x86_pmc_info_args *uargs,
-    register_t *retval)
+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));
 
-	if (pmc_initialized == 0)
-		pmc_init();
-
 	rv.type = pmc_type;
 	rv.flags = pmc_flags;
 
-	return (copyout(&rv, uargs, sizeof(rv)));
+	return copyout(&rv, uargs, sizeof(rv));
 }
 
 int
-pmc_startstop(struct lwp *l, struct x86_pmc_startstop_args *uargs,
+sys_pmc_startstop(struct lwp *l, struct x86_pmc_startstop_args *uargs,
     register_t *retval)
 {
 	struct x86_pmc_startstop_args args;
-	int error, mask, start;
+	pmc_state_t *pmc;
+	bool start;
+	int error;
 
-	if (pmc_initialized == 0)
-		pmc_init();
 	if (pmc_type == PMC_TYPE_NONE)
-		return (ENODEV);
+		return ENODEV;
 
 	error = copyin(uargs, &args, sizeof(args));
 	if (error)
-		return (error);
+		return error;
 
 	if (args.counter < 0 || args.counter >= pmc_ncounters)
-		return (EINVAL);
+		return EINVAL;
 
-	mask = 1 << args.counter;
 	start = (args.flags & (PMC_SETUP_KERNEL|PMC_SETUP_USER)) != 0;
+	pmc = &pmc_state[args.counter];
 
-	if ((pmc_running & mask) != 0 && start != 0)
-		return (EBUSY);
-	else if ((pmc_running & mask) == 0 && start == 0)
-		return (0);
-
-	x86_disable_intr();
-	if (start) {
-		pmc_running |= mask;
-		pmc_state[args.counter].pmcs_val = args.val;
-		switch (pmc_type) {
-		case PMC_TYPE_I586:
-			pmc_state[args.counter].pmcs_control = 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;
+	mutex_enter(&pmc_lock);
 
-		case PMC_TYPE_I686:
-			pmc_state[args.counter].pmcs_control = args.event |
-			    (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;
+	if (start && pmc->running) {
+		mutex_exit(&pmc_lock);
+		return EBUSY;
+	} else if (!start && !pmc->running) {
+		mutex_exit(&pmc_lock);
+		return 0;
+	}
 
-		case PMC_TYPE_K7:
-			pmc_state[args.counter].pmcs_control = args.event |
-			    (args.unit << K7_EVTSEL_UNIT_SHIFT) |
-			    ((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 << PMC6_EVTSEL_COUNTER_MASK_SHIFT);
-			break;
-		}
-		wrmsr(pmc_state[args.counter].pmcs_ctrmsr,
-		    pmc_state[args.counter].pmcs_val);
+	if (start) {
+		pmc_start(pmc, &args);
 	} else {
-		pmc_running &= ~mask;
-		pmc_state[args.counter].pmcs_control = 0;
+		pmc_stop(pmc, &args);
 	}
 
-	switch (pmc_type) {
-	case PMC_TYPE_I586:
-		wrmsr(MSR_CESR, pmc_state[0].pmcs_control |
-		    (pmc_state[1].pmcs_control << 16));
-		break;
-
-	case PMC_TYPE_I686:
-		if (args.counter == 1)
-			wrmsr(MSR_EVNTSEL1, pmc_state[1].pmcs_control);
-		wrmsr(MSR_EVNTSEL0, pmc_state[0].pmcs_control |
-		    (pmc_running ? PMC6_EVTSEL_EN : 0));
-		break;
+	mutex_exit(&pmc_lock);
 
-	case PMC_TYPE_K7:
-		if (args.counter == 1)
-			wrmsr(MSR_K7_EVNTSEL1, pmc_state[1].pmcs_control);
-		wrmsr(MSR_K7_EVNTSEL0, pmc_state[0].pmcs_control |
-		    (pmc_running ? K7_EVTSEL_EN : 0));
-		break;
-	}
-	x86_enable_intr();
-
-	return (0);
+	return 0;
 }
 
 int
-pmc_read(struct lwp *l, struct x86_pmc_read_args *uargs,
-    register_t *retval)
+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;
 	int error;
 
-	if (pmc_initialized == 0)
-		pmc_init();
 	if (pmc_type == PMC_TYPE_NONE)
-		return (ENODEV);
+		return ENODEV;
 
 	error = copyin(uargs, &args, sizeof(args));
 	if (error)
-		return (error);
+		return error;
 
 	if (args.counter < 0 || args.counter >= pmc_ncounters)
-		return (EINVAL);
+		return EINVAL;
+	pmc = &pmc_state[args.counter];
 
-	if (pmc_running & (1 << args.counter)) {
-		pmc_state[args.counter].pmcs_val =
-		    rdmsr(pmc_state[args.counter].pmcs_ctrmsr) &
-		    0xffffffffffULL;
+	mutex_enter(&pmc_lock);
+
+	if (pmc->running) {
+		pmc_read(pmc);
 		if (pmc_flags & PMC_INFO_HASTSC)
-			pmc_state[args.counter].pmcs_tsc = cpu_counter();
+			pmc->tsc = cpu_counter();
 	}
 
-	args.val = pmc_state[args.counter].pmcs_val;
-	args.time = pmc_state[args.counter].pmcs_tsc;
+	args.val = pmc->ctrval;
+	args.time = pmc->tsc;
+
+	mutex_exit(&pmc_lock);
 
-	return (copyout(&args, uargs, sizeof(args)));
+	return copyout(&args, uargs, sizeof(args));
 }

Index: src/sys/arch/i386/include/pmc.h
diff -u src/sys/arch/i386/include/pmc.h:1.8 src/sys/arch/i386/include/pmc.h:1.9
--- src/sys/arch/i386/include/pmc.h:1.8	Mon Apr 16 19:12:18 2007
+++ src/sys/arch/i386/include/pmc.h	Fri Feb 17 12:10:40 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmc.h,v 1.8 2007/04/16 19:12:18 ad Exp $	*/
+/*	$NetBSD: pmc.h,v 1.9 2017/02/17 12:10:40 maxv Exp $	*/
 
 /*-
  * Copyright (c) 2000 Zembu Labs, Inc.
@@ -66,12 +66,13 @@
 struct x86_pmc_info_args;
 struct x86_pmc_startstop_args;
 struct x86_pmc_read_args;
-int	pmc_info(struct lwp *, struct x86_pmc_info_args *,
-	    register_t *);
-int	pmc_startstop(struct lwp *, struct x86_pmc_startstop_args *,
-	    register_t *);
-int	pmc_read(struct lwp *, struct x86_pmc_read_args *,
-	    register_t *);
+void pmc_init(void);
+int sys_pmc_info(struct lwp *, struct x86_pmc_info_args *,
+    register_t *);
+int sys_pmc_startstop(struct lwp *, struct x86_pmc_startstop_args *,
+    register_t *);
+int sys_pmc_read(struct lwp *, struct x86_pmc_read_args *,
+    register_t *);
 /* END LEGACY PMC SUPPORT */
 
 #define pmc_md_fork(p1,p2)

Index: src/sys/arch/x86/x86/sys_machdep.c
diff -u src/sys/arch/x86/x86/sys_machdep.c:1.32 src/sys/arch/x86/x86/sys_machdep.c:1.33
--- src/sys/arch/x86/x86/sys_machdep.c:1.32	Tue Feb 14 09:11:05 2017
+++ src/sys/arch/x86/x86/sys_machdep.c	Fri Feb 17 12:10:40 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_machdep.c,v 1.32 2017/02/14 09:11:05 maxv Exp $	*/
+/*	$NetBSD: sys_machdep.c,v 1.33 2017/02/17 12:10:40 maxv Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2009 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.32 2017/02/14 09:11:05 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.33 2017/02/17 12:10:40 maxv Exp $");
 
 #include "opt_mtrr.h"
 #include "opt_perfctrs.h"
@@ -849,21 +849,15 @@ sys_sysarch(struct lwp *l, const struct 
 
 #ifdef PERFCTRS
 	case X86_PMC_INFO:
-		KERNEL_LOCK(1, NULL);
-		error = pmc_info(l, SCARG(uap, parms), retval);
-		KERNEL_UNLOCK_ONE(NULL);
+		error = sys_pmc_info(l, SCARG(uap, parms), retval);
 		break;
 
 	case X86_PMC_STARTSTOP:
-		KERNEL_LOCK(1, NULL);
-		error = pmc_startstop(l, SCARG(uap, parms), retval);
-		KERNEL_UNLOCK_ONE(NULL);
+		error = sys_pmc_startstop(l, SCARG(uap, parms), retval);
 		break;
 
 	case X86_PMC_READ:
-		KERNEL_LOCK(1, NULL);
-		error = pmc_read(l, SCARG(uap, parms), retval);
-		KERNEL_UNLOCK_ONE(NULL);
+		error = sys_pmc_read(l, SCARG(uap, parms), retval);
 		break;
 #endif
 

Reply via email to