Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Jul 2010 13:16:13 -0400
From:      George Neville-Neil <gnn@neville-neil.com>
To:        current@freebsd.org
Subject:   hwpmc on Intel Core architectures fixed counters patch
Message-ID:  <59EEB71E-1FE5-430C-85DF-52727AE7805D@neville-neil.com>

index | next in thread | raw e-mail

[-- Attachment #1 --]
Howdy,

If anyone is using hwpmc on core architectures, i.e. Core, Core2, Nehalem, Westmere, can you
please test the following patch which fixes occasional panics of this code on those 
processors?  The specific bug address comes when sampling the IAF (Fixed Function) counters
which are: 

IAF
        INSTR_RETIRED_ANY
        CPU_CLK_UNHALTED_CORE
        CPU_CLK_UNHALTED_REF

I plan to commit this to HEAD this week.  I have tested it on HEAD and 7.X.



Thanks,
George



[-- Attachment #2 --]
Index: sys/dev/hwpmc/hwpmc_core.c
===================================================================
--- sys/dev/hwpmc/hwpmc_core.c	(revision 209857)
+++ sys/dev/hwpmc/hwpmc_core.c	(working copy)
@@ -147,6 +147,7 @@
 	int core_ri, n, npmc;
 	struct pmc_cpu *pc;
 	struct core_cpu *cc;
+	uint64_t msr = 0;
 
 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 	    ("[core,%d] insane cpu number (%d)", __LINE__, cpu));
@@ -166,11 +167,14 @@
 	npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_num;
 	core_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_ri;
 
-	for (n = 0; n < npmc; n++)
-		wrmsr(IAP_EVSEL0 + n, 0);
+	for (n = 0; n < npmc; n++) {
+		msr = rdmsr(IAP_EVSEL0 + n);
+		wrmsr(IAP_EVSEL0 + n, msr & ~IAP_EVSEL_MASK);
+	}
 
 	if (core_cputype != PMC_CPU_INTEL_CORE) {
-		wrmsr(IAF_CTRL, 0);
+		msr = rdmsr(IAF_CTRL);
+		wrmsr(IAF_CTRL, msr & ~IAF_CTRL_MASK);
 		npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF].pcd_num;
 	}
 
@@ -374,6 +378,7 @@
 {
 	struct pmc *pm;
 	struct core_cpu *iafc;
+	uint64_t msr = 0;
 
 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 	    ("[core,%d] illegal CPU value %d", __LINE__, cpu));
@@ -387,12 +392,15 @@
 
 	iafc->pc_iafctrl |= pm->pm_md.pm_iaf.pm_iaf_ctrl;
 
-	wrmsr(IAF_CTRL, iafc->pc_iafctrl);
+ 	msr = rdmsr(IAF_CTRL);
+ 	wrmsr(IAF_CTRL, msr | (iafc->pc_iafctrl & IAF_CTRL_MASK));
 
 	do {
 		iafc->pc_resync = 0;
 		iafc->pc_globalctrl |= (1ULL << (ri + IAF_OFFSET));
-		wrmsr(IA_GLOBAL_CTRL, iafc->pc_globalctrl);
+ 		msr = rdmsr(IA_GLOBAL_CTRL);
+ 		wrmsr(IA_GLOBAL_CTRL, msr | (iafc->pc_globalctrl & 
+ 					     IAF_GLOBAL_CTRL_MASK));
 	} while (iafc->pc_resync != 0);
 
 	PMCDBG(MDP,STA,1,"iafctrl=%x(%x) globalctrl=%jx(%jx)",
@@ -407,6 +415,7 @@
 {
 	uint32_t fc;
 	struct core_cpu *iafc;
+	uint64_t msr = 0;
 
 	PMCDBG(MDP,STO,1,"iaf-stop cpu=%d ri=%d", cpu, ri);
 
@@ -425,12 +434,15 @@
 	iafc->pc_iafctrl &= ~fc;
 
 	PMCDBG(MDP,STO,1,"iaf-stop iafctrl=%x", iafc->pc_iafctrl);
-	wrmsr(IAF_CTRL, iafc->pc_iafctrl);
+ 	msr = rdmsr(IAF_CTRL);
+ 	wrmsr(IAF_CTRL, msr | (iafc->pc_iafctrl & IAF_CTRL_MASK));
 
 	do {
 		iafc->pc_resync = 0;
 		iafc->pc_globalctrl &= ~(1ULL << (ri + IAF_OFFSET));
-		wrmsr(IA_GLOBAL_CTRL, iafc->pc_globalctrl);
+ 		msr = rdmsr(IA_GLOBAL_CTRL);
+ 		wrmsr(IA_GLOBAL_CTRL, msr | (iafc->pc_globalctrl &
+ 					     IAF_GLOBAL_CTRL_MASK));
 	} while (iafc->pc_resync != 0);
 
 	PMCDBG(MDP,STO,1,"iafctrl=%x(%x) globalctrl=%jx(%jx)",
@@ -445,6 +457,7 @@
 {
 	struct core_cpu *cc;
 	struct pmc *pm;
+	uint64_t msr;
 
 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 	    ("[core,%d] illegal cpu value %d", __LINE__, cpu));
@@ -460,9 +473,11 @@
 	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 		v = iaf_reload_count_to_perfctr_value(v);
 
-	wrmsr(IAF_CTRL, 0);	/* Turn off fixed counters */
-	wrmsr(IAF_CTR0 + ri, v);
-	wrmsr(IAF_CTRL, cc->pc_iafctrl);
+	msr = rdmsr(IAF_CTRL);
+	wrmsr(IAF_CTRL, msr & ~IAF_CTRL_MASK);
+	wrmsr(IAF_CTR0 + ri, v & ((1ULL << core_iaf_width) - 1));
+	msr = rdmsr(IAF_CTRL);
+	wrmsr(IAF_CTRL, msr | (cc->pc_iafctrl & IAF_CTRL_MASK));
 
 	PMCDBG(MDP,WRI,1, "iaf-write cpu=%d ri=%d msr=0x%x v=%jx iafctrl=%jx "
 	    "pmc=%jx", cpu, ri, IAF_RI_TO_MSR(ri), v,
@@ -1879,6 +1894,7 @@
 {
 	struct pmc *pm;
 	struct core_cpu *cc;
+	uint64_t msr;
 
 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 	    ("[core,%d] illegal cpu value %d", __LINE__, cpu));
@@ -1894,7 +1910,8 @@
 
 	PMCDBG(MDP,STO,1, "iap-stop cpu=%d ri=%d", cpu, ri);
 
-	wrmsr(IAP_EVSEL0 + ri, 0);	/* stop hw */
+	msr = rdmsr(IAP_EVSEL0 + ri);
+	wrmsr(IAP_EVSEL0 + ri, msr & IAP_EVSEL_MASK);	/* stop hw */
 
 	if (core_cputype == PMC_CPU_INTEL_CORE)
 		return (0);
@@ -1937,7 +1954,7 @@
 	 * a stopped state when the pcd_write() entry point is called.
 	 */
 
-	wrmsr(IAP_PMC0 + ri, v);
+	wrmsr(IAP_PMC0 + ri, v & ((1ULL << core_iap_width) - 1));
 
 	return (0);
 }
@@ -1987,6 +2004,7 @@
 	struct pmc *pm;
 	struct core_cpu *cc;
 	int error, found_interrupt, ri;
+	uint64_t msr = 0;
 
 	PMCDBG(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf,
 	    TRAPF_USERMODE(tf));
@@ -2018,7 +2036,8 @@
 		 * Stop the counter, reload it but only restart it if
 		 * the PMC is not stalled.
 		 */
-		wrmsr(IAP_EVSEL0 + ri, 0);
+		msr = rdmsr(IAP_EVSEL0 + ri);
+		wrmsr(IAP_EVSEL0 + ri, msr & ~IAP_EVSEL_MASK);
 		wrmsr(IAP_PMC0 + ri, v);
 
 		if (error)
Index: sys/dev/hwpmc/hwpmc_core.h
===================================================================
--- sys/dev/hwpmc/hwpmc_core.h	(revision 209857)
+++ sys/dev/hwpmc/hwpmc_core.h	(working copy)
@@ -67,20 +67,59 @@
 /*
  * Fixed-function counters.
  */
+
 #define	IAF_MASK				0xF
 
+#define IAF_COUNTER_MASK			0x0000ffffffffffff
 #define	IAF_CTR0				0x309
 #define	IAF_CTR1				0x30A
 #define	IAF_CTR2				0x30B
 
+/*
+ * The IAF_CTRL MSR is laid out in the following way.
+ *
+ * Bit Position    Use
+ * 63 - 12         Reserved (do not touch)
+ * 11              Ctr 2 PMI
+ * 10              Reserved (do not touch)
+ * 9-8             Ctr 2 Enable
+ * 7               Ctr 1 PMI
+ * 6               Reserved (do not touch)
+ * 5-4             Ctr 1 Enable
+ * 3               Ctr 0 PMI
+ * 2               Reserved (do not touch)
+ * 1-0             Ctr 0 Enable (3: All Levels, 2: User, 1: OS, 0: Disable)
+ */
+
 #define	IAF_OFFSET				32
 #define	IAF_CTRL				0x38D
+#define IAF_CTRL_MASK				0x0000000000000bbb
 
 /*
  * Programmable counters.
  */
 
 #define	IAP_PMC0				0x0C1
+
+/*
+ * IAP_EVSEL(n) is laid out in the following way.
+ *
+ * Bit Position    Use
+ * 63-31           Reserved (do not touch)
+ * 31-24           Counter Mask
+ * 23              Invert
+ * 22              Enable
+ * 21              Reserved (do not touch)
+ * 20              APIC Interrupt Enable
+ * 19              Pin Control
+ * 18              Edge Detect
+ * 17              OS
+ * 16              User
+ * 15-8            Unit Mask
+ * 7-0             Event Select
+ */
+
+#define IAP_EVSEL_MASK				0x00000000ffdfffff
 #define	IAP_EVSEL0				0x186
 
 /*
@@ -90,6 +129,21 @@
 
 #define	IA_GLOBAL_STATUS			0x38E
 #define	IA_GLOBAL_CTRL				0x38F
+
+/*
+ * IA_GLOBAL_CTRL is layed out in the following way.
+ * 
+ * Bit Position    Use
+ * 63-35           Reserved (do not touch)
+ * 34              IAF Counter 2 Enable
+ * 33              IAF Counter 1 Enable
+ * 32              IAF Counter 0 Enable
+ * 31-0            Depends on programmable counters
+ */
+
+/* The mask is only for the fixed porttion of the register. */
+#define IAF_GLOBAL_CTRL_MASK			0x0000000700000000
+
 #define	IA_GLOBAL_OVF_CTRL			0x390
 
 #define	IA_GLOBAL_STATUS_FLAG_CONDCHG		(1ULL << 63)
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?59EEB71E-1FE5-430C-85DF-52727AE7805D>