svn commit: r295560 - head/sys/dev/hwpmc

Konstantin Belousov kib at FreeBSD.org
Fri Feb 12 07:27:25 UTC 2016


Author: kib
Date: Fri Feb 12 07:27:24 2016
New Revision: 295560
URL: https://svnweb.freebsd.org/changeset/base/295560

Log:
  If full width writes to the performance monitoring counters are
  supported, use full-width aliases MSRs for writes.  This fixes the
  "[pmc,X] negative increment" assertion on the context switch when
  clipped counter value is sign-extended.
  
  Add definitions for the MSR IA32_PERF_CAPABILITIES needed to detect
  the feature.
  
  PR:	207068
  Submitted by:	joss.upton at yahoo.com
  MFC after:	2 weeks

Modified:
  head/sys/dev/hwpmc/hwpmc_core.c
  head/sys/dev/hwpmc/hwpmc_core.h

Modified: head/sys/dev/hwpmc/hwpmc_core.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_core.c	Fri Feb 12 07:20:27 2016	(r295559)
+++ head/sys/dev/hwpmc/hwpmc_core.c	Fri Feb 12 07:27:24 2016	(r295560)
@@ -103,6 +103,7 @@ static int core_iaf_npmc;
 
 static int core_iap_width;
 static int core_iap_npmc;
+static int core_iap_wroffset;
 
 static int
 core_pcpu_noop(struct pmc_mdep *md, int cpu)
@@ -2473,7 +2474,7 @@ iap_read_pmc(int cpu, int ri, pmc_value_
 		*v = tmp & ((1ULL << core_iap_width) - 1);
 
 	PMCDBG4(MDP,REA,1, "iap-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
-	    ri, *v);
+	    IAP_PMC0 + ri, *v);
 
 	return (0);
 }
@@ -2605,19 +2606,20 @@ iap_write_pmc(int cpu, int ri, pmc_value
 	    ("[core,%d] cpu%d ri%d no configured PMC to stop", __LINE__,
 		cpu, ri));
 
-	PMCDBG4(MDP,WRI,1, "iap-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri,
-	    IAP_PMC0 + ri, v);
-
 	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 		v = iap_reload_count_to_perfctr_value(v);
 
-	/*
-	 * Write the new value to the counter.  The counter will be in
-	 * a stopped state when the pcd_write() entry point is called.
-	 */
+	v &= (1ULL << core_iap_width) - 1;
 
-	wrmsr(IAP_PMC0 + ri, v & ((1ULL << core_iap_width) - 1));
+	PMCDBG4(MDP,WRI,1, "iap-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri,
+	    IAP_PMC0 + ri, v);
 
+	/*
+	 * Write the new value to the counter (or it's alias).  The
+	 * counter will be in a stopped state when the pcd_write()
+	 * entry point is called.
+	 */
+	wrmsr(core_iap_wroffset + IAP_PMC0 + ri, v);
 	return (0);
 }
 
@@ -2700,7 +2702,7 @@ core_intr(int cpu, struct trapframe *tf)
 		 */
 		msr = rdmsr(IAP_EVSEL0 + ri) & ~IAP_EVSEL_MASK;
 		wrmsr(IAP_EVSEL0 + ri, msr);
-		wrmsr(IAP_PMC0 + ri, v);
+		wrmsr(core_iap_wroffset + IAP_PMC0 + ri, v);
 
 		if (error)
 			continue;
@@ -2814,7 +2816,7 @@ core2_intr(int cpu, struct trapframe *tf
 		    (uintmax_t) v);
 
 		/* Reload sampling count. */
-		wrmsr(IAP_PMC0 + n, v);
+		wrmsr(core_iap_wroffset + IAP_PMC0 + n, v);
 	}
 
 	/*
@@ -2865,6 +2867,18 @@ pmc_core_initialize(struct pmc_mdep *md,
 		return (EPROGMISMATCH);
 	}
 
+	core_iap_wroffset = 0;
+	if (cpu_feature2 & CPUID2_PDCM) {
+		if (rdmsr(IA32_PERF_CAPABILITIES) & PERFCAP_FW_WRITE) {
+			PMCDBG0(MDP, INI, 1,
+			    "core-init full-width write supported");
+			core_iap_wroffset = IAP_A_PMC0 - IAP_PMC0;
+		} else
+			PMCDBG0(MDP, INI, 1,
+			    "core-init full-width write NOT supported");
+	} else
+		PMCDBG0(MDP, INI, 1, "core-init pdcm not supported");
+
 	core_pmcmask = 0;
 
 	/*

Modified: head/sys/dev/hwpmc/hwpmc_core.h
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_core.h	Fri Feb 12 07:20:27 2016	(r295559)
+++ head/sys/dev/hwpmc/hwpmc_core.h	Fri Feb 12 07:27:24 2016	(r295560)
@@ -29,6 +29,14 @@
 #ifndef _DEV_HWPMC_CORE_H_
 #define	_DEV_HWPMC_CORE_H_ 1
 
+#define	IA32_PERF_CAPABILITIES		0x345
+#define	PERFCAP_LBR_FORMAT		0x003f
+#define	PERFCAP_PEBS_TRAP		0x0040
+#define	PERFCAP_PEBS_SAVEARCH		0x0080
+#define	PERFCAP_PEBS_RECFORMAT		0x0f00
+#define	PERFCAP_SMM_FREEZE		0x1000
+#define	PERFCAP_FW_WRITE		0x2000	/* full width write aliases */
+
 /*
  * Fixed-function PMCs.
  */
@@ -101,6 +109,7 @@ struct pmc_md_iap_op_pmcallocate {
  */
 
 #define	IAP_PMC0				0x0C1
+#define	IAP_A_PMC0				0x4C1
 
 /*
  * IAP_EVSEL(n) is laid out in the following way.


More information about the svn-src-head mailing list