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>
