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"

Reply via email to