Hah great catch! I always wondered about this!
-a On 11 February 2016 at 23:27, Konstantin Belousov <k...@freebsd.org> wrote: > 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.up...@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. > _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"