diff options
author | kib <kib@FreeBSD.org> | 2016-02-12 07:27:24 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2016-02-12 07:27:24 +0000 |
commit | 7af72453b7efe688c01e9d79607f455c01914ba7 (patch) | |
tree | 03b7658a0a050f361c040e69c7caca92eb3b1e78 /sys/dev | |
parent | 36e6e79737e0bc8fcf93bdf292812567a3cca809 (diff) | |
download | FreeBSD-src-7af72453b7efe688c01e9d79607f455c01914ba7.zip FreeBSD-src-7af72453b7efe688c01e9d79607f455c01914ba7.tar.gz |
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@yahoo.com
MFC after: 2 weeks
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/hwpmc/hwpmc_core.c | 36 | ||||
-rw-r--r-- | sys/dev/hwpmc/hwpmc_core.h | 9 |
2 files changed, 34 insertions, 11 deletions
diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c index d26c965..f092a21 100644 --- a/sys/dev/hwpmc/hwpmc_core.c +++ b/sys/dev/hwpmc/hwpmc_core.c @@ -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_t *v) *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_t v) ("[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, int maxcpu, int version_override) 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; /* diff --git a/sys/dev/hwpmc/hwpmc_core.h b/sys/dev/hwpmc/hwpmc_core.h index 63b6d02..7196d9d 100644 --- a/sys/dev/hwpmc/hwpmc_core.h +++ b/sys/dev/hwpmc/hwpmc_core.h @@ -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. |