The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/hwpmc/hwpmc_core.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2008 Joseph Koshy
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 /*
   30  * Intel Core PMCs.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include <sys/param.h>
   37 #include <sys/bus.h>
   38 #include <sys/pmc.h>
   39 #include <sys/pmckern.h>
   40 #include <sys/smp.h>
   41 #include <sys/systm.h>
   42 
   43 #include <machine/intr_machdep.h>
   44 #include <x86/apicvar.h>
   45 #include <machine/cpu.h>
   46 #include <machine/cpufunc.h>
   47 #include <machine/md_var.h>
   48 #include <machine/specialreg.h>
   49 
   50 #define CORE_CPUID_REQUEST              0xA
   51 #define CORE_CPUID_REQUEST_SIZE         0x4
   52 #define CORE_CPUID_EAX                  0x0
   53 #define CORE_CPUID_EBX                  0x1
   54 #define CORE_CPUID_ECX                  0x2
   55 #define CORE_CPUID_EDX                  0x3
   56 
   57 #define IAF_PMC_CAPS                    \
   58         (PMC_CAP_READ | PMC_CAP_WRITE | PMC_CAP_INTERRUPT | \
   59          PMC_CAP_USER | PMC_CAP_SYSTEM)
   60 #define IAF_RI_TO_MSR(RI)               ((RI) + (1 << 30))
   61 
   62 #define IAP_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | PMC_CAP_SYSTEM | \
   63     PMC_CAP_EDGE | PMC_CAP_THRESHOLD | PMC_CAP_READ | PMC_CAP_WRITE |    \
   64     PMC_CAP_INVERT | PMC_CAP_QUALIFIER | PMC_CAP_PRECISE)
   65 
   66 #define EV_IS_NOTARCH           0
   67 #define EV_IS_ARCH_SUPP         1
   68 #define EV_IS_ARCH_NOTSUPP      -1
   69 
   70 /*
   71  * "Architectural" events defined by Intel.  The values of these
   72  * symbols correspond to positions in the bitmask returned by
   73  * the CPUID.0AH instruction.
   74  */
   75 enum core_arch_events {
   76         CORE_AE_BRANCH_INSTRUCTION_RETIRED      = 5,
   77         CORE_AE_BRANCH_MISSES_RETIRED           = 6,
   78         CORE_AE_INSTRUCTION_RETIRED             = 1,
   79         CORE_AE_LLC_MISSES                      = 4,
   80         CORE_AE_LLC_REFERENCE                   = 3,
   81         CORE_AE_UNHALTED_REFERENCE_CYCLES       = 2,
   82         CORE_AE_UNHALTED_CORE_CYCLES            = 0
   83 };
   84 
   85 static enum pmc_cputype core_cputype;
   86 static int core_version;
   87 
   88 struct core_cpu {
   89         volatile uint32_t       pc_iafctrl;     /* Fixed function control. */
   90         volatile uint64_t       pc_globalctrl;  /* Global control register. */
   91         struct pmc_hw           pc_corepmcs[];
   92 };
   93 
   94 static struct core_cpu **core_pcpu;
   95 
   96 static uint32_t core_architectural_events;
   97 static uint64_t core_pmcmask;
   98 
   99 static int core_iaf_ri;         /* relative index of fixed counters */
  100 static int core_iaf_width;
  101 static int core_iaf_npmc;
  102 
  103 static int core_iap_width;
  104 static int core_iap_npmc;
  105 static int core_iap_wroffset;
  106 
  107 static u_int pmc_alloc_refs;
  108 static bool pmc_tsx_force_abort_set;
  109 
  110 static int
  111 core_pcpu_noop(struct pmc_mdep *md, int cpu)
  112 {
  113         (void) md;
  114         (void) cpu;
  115         return (0);
  116 }
  117 
  118 static int
  119 core_pcpu_init(struct pmc_mdep *md, int cpu)
  120 {
  121         struct pmc_cpu *pc;
  122         struct core_cpu *cc;
  123         struct pmc_hw *phw;
  124         int core_ri, n, npmc;
  125 
  126         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  127             ("[iaf,%d] insane cpu number %d", __LINE__, cpu));
  128 
  129         PMCDBG1(MDP,INI,1,"core-init cpu=%d", cpu);
  130 
  131         core_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_ri;
  132         npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_num;
  133 
  134         if (core_version >= 2)
  135                 npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF].pcd_num;
  136 
  137         cc = malloc(sizeof(struct core_cpu) + npmc * sizeof(struct pmc_hw),
  138             M_PMC, M_WAITOK | M_ZERO);
  139 
  140         core_pcpu[cpu] = cc;
  141         pc = pmc_pcpu[cpu];
  142 
  143         KASSERT(pc != NULL && cc != NULL,
  144             ("[core,%d] NULL per-cpu structures cpu=%d", __LINE__, cpu));
  145 
  146         for (n = 0, phw = cc->pc_corepmcs; n < npmc; n++, phw++) {
  147                 phw->phw_state    = PMC_PHW_FLAG_IS_ENABLED |
  148                     PMC_PHW_CPU_TO_STATE(cpu) |
  149                     PMC_PHW_INDEX_TO_STATE(n + core_ri);
  150                 phw->phw_pmc      = NULL;
  151                 pc->pc_hwpmcs[n + core_ri]  = phw;
  152         }
  153 
  154         if (core_version >= 2 && vm_guest == VM_GUEST_NO) {
  155                 /* Enable Freezing PMCs on PMI. */
  156                 wrmsr(MSR_DEBUGCTLMSR, rdmsr(MSR_DEBUGCTLMSR) | 0x1000);
  157         }
  158 
  159         return (0);
  160 }
  161 
  162 static int
  163 core_pcpu_fini(struct pmc_mdep *md, int cpu)
  164 {
  165         int core_ri, n, npmc;
  166         struct pmc_cpu *pc;
  167         struct core_cpu *cc;
  168 
  169         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  170             ("[core,%d] insane cpu number (%d)", __LINE__, cpu));
  171 
  172         PMCDBG1(MDP,INI,1,"core-pcpu-fini cpu=%d", cpu);
  173 
  174         if ((cc = core_pcpu[cpu]) == NULL)
  175                 return (0);
  176 
  177         core_pcpu[cpu] = NULL;
  178 
  179         pc = pmc_pcpu[cpu];
  180 
  181         KASSERT(pc != NULL, ("[core,%d] NULL per-cpu %d state", __LINE__,
  182                 cpu));
  183 
  184         npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_num;
  185         core_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_ri;
  186 
  187         for (n = 0; n < npmc; n++)
  188                 wrmsr(IAP_EVSEL0 + n, 0);
  189 
  190         if (core_version >= 2) {
  191                 wrmsr(IAF_CTRL, 0);
  192                 npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF].pcd_num;
  193         }
  194 
  195         for (n = 0; n < npmc; n++)
  196                 pc->pc_hwpmcs[n + core_ri] = NULL;
  197 
  198         free(cc, M_PMC);
  199 
  200         return (0);
  201 }
  202 
  203 /*
  204  * Fixed function counters.
  205  */
  206 
  207 static pmc_value_t
  208 iaf_perfctr_value_to_reload_count(pmc_value_t v)
  209 {
  210 
  211         /* If the PMC has overflowed, return a reload count of zero. */
  212         if ((v & (1ULL << (core_iaf_width - 1))) == 0)
  213                 return (0);
  214         v &= (1ULL << core_iaf_width) - 1;
  215         return (1ULL << core_iaf_width) - v;
  216 }
  217 
  218 static pmc_value_t
  219 iaf_reload_count_to_perfctr_value(pmc_value_t rlc)
  220 {
  221         return (1ULL << core_iaf_width) - rlc;
  222 }
  223 
  224 static int
  225 iaf_allocate_pmc(int cpu, int ri, struct pmc *pm,
  226     const struct pmc_op_pmcallocate *a)
  227 {
  228         uint8_t ev, umask;
  229         uint32_t caps;
  230         uint64_t config, flags;
  231         const struct pmc_md_iap_op_pmcallocate *iap;
  232 
  233         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  234             ("[core,%d] illegal CPU %d", __LINE__, cpu));
  235 
  236         PMCDBG2(MDP,ALL,1, "iaf-allocate ri=%d reqcaps=0x%x", ri, pm->pm_caps);
  237 
  238         if (ri < 0 || ri > core_iaf_npmc)
  239                 return (EINVAL);
  240 
  241         if (a->pm_class != PMC_CLASS_IAF)
  242                 return (EINVAL);
  243 
  244         iap = &a->pm_md.pm_iap;
  245         config = iap->pm_iap_config;
  246         ev = IAP_EVSEL_GET(config);
  247         umask = IAP_UMASK_GET(config);
  248 
  249         if (ev == 0x0) {
  250                 if (umask != ri + 1)
  251                         return (EINVAL);
  252         } else {
  253                 switch (ri) {
  254                 case 0: /* INST_RETIRED.ANY */
  255                         if (ev != 0xC0 || umask != 0x00)
  256                                 return (EINVAL);
  257                         break;
  258                 case 1: /* CPU_CLK_UNHALTED.THREAD */
  259                         if (ev != 0x3C || umask != 0x00)
  260                                 return (EINVAL);
  261                         break;
  262                 case 2: /* CPU_CLK_UNHALTED.REF */
  263                         if (ev != 0x3C || umask != 0x01)
  264                                 return (EINVAL);
  265                         break;
  266                 case 3: /* TOPDOWN.SLOTS */
  267                         if (ev != 0xA4 || umask != 0x01)
  268                                 return (EINVAL);
  269                         break;
  270                 default:
  271                         return (EINVAL);
  272                 }
  273         }
  274 
  275         pmc_alloc_refs++;
  276         if ((cpu_stdext_feature3 & CPUID_STDEXT3_TSXFA) != 0 &&
  277             !pmc_tsx_force_abort_set) {
  278                 pmc_tsx_force_abort_set = true;
  279                 x86_msr_op(MSR_TSX_FORCE_ABORT, MSR_OP_RENDEZVOUS_ALL |
  280                     MSR_OP_WRITE, 1, NULL);
  281         }
  282 
  283         flags = 0;
  284         if (config & IAP_OS)
  285                 flags |= IAF_OS;
  286         if (config & IAP_USR)
  287                 flags |= IAF_USR;
  288         if (config & IAP_ANY)
  289                 flags |= IAF_ANY;
  290         if (config & IAP_INT)
  291                 flags |= IAF_PMI;
  292 
  293         caps = a->pm_caps;
  294         if (caps & PMC_CAP_INTERRUPT)
  295                 flags |= IAF_PMI;
  296         if (caps & PMC_CAP_SYSTEM)
  297                 flags |= IAF_OS;
  298         if (caps & PMC_CAP_USER)
  299                 flags |= IAF_USR;
  300         if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
  301                 flags |= (IAF_OS | IAF_USR);
  302 
  303         pm->pm_md.pm_iaf.pm_iaf_ctrl = (flags << (ri * 4));
  304 
  305         PMCDBG1(MDP,ALL,2, "iaf-allocate config=0x%jx",
  306             (uintmax_t) pm->pm_md.pm_iaf.pm_iaf_ctrl);
  307 
  308         return (0);
  309 }
  310 
  311 static int
  312 iaf_config_pmc(int cpu, int ri, struct pmc *pm)
  313 {
  314         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  315             ("[core,%d] illegal CPU %d", __LINE__, cpu));
  316 
  317         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  318             ("[core,%d] illegal row-index %d", __LINE__, ri));
  319 
  320         PMCDBG3(MDP,CFG,1, "iaf-config cpu=%d ri=%d pm=%p", cpu, ri, pm);
  321 
  322         KASSERT(core_pcpu[cpu] != NULL, ("[core,%d] null per-cpu %d", __LINE__,
  323             cpu));
  324 
  325         core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc = pm;
  326 
  327         return (0);
  328 }
  329 
  330 static int
  331 iaf_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
  332 {
  333         int error;
  334         struct pmc_hw *phw;
  335         char iaf_name[PMC_NAME_MAX];
  336 
  337         phw = &core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri];
  338 
  339         (void) snprintf(iaf_name, sizeof(iaf_name), "IAF-%d", ri);
  340         if ((error = copystr(iaf_name, pi->pm_name, PMC_NAME_MAX,
  341             NULL)) != 0)
  342                 return (error);
  343 
  344         pi->pm_class = PMC_CLASS_IAF;
  345 
  346         if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
  347                 pi->pm_enabled = TRUE;
  348                 *ppmc          = phw->phw_pmc;
  349         } else {
  350                 pi->pm_enabled = FALSE;
  351                 *ppmc          = NULL;
  352         }
  353 
  354         return (0);
  355 }
  356 
  357 static int
  358 iaf_get_config(int cpu, int ri, struct pmc **ppm)
  359 {
  360         *ppm = core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
  361 
  362         return (0);
  363 }
  364 
  365 static int
  366 iaf_get_msr(int ri, uint32_t *msr)
  367 {
  368         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  369             ("[iaf,%d] ri %d out of range", __LINE__, ri));
  370 
  371         *msr = IAF_RI_TO_MSR(ri);
  372 
  373         return (0);
  374 }
  375 
  376 static int
  377 iaf_read_pmc(int cpu, int ri, pmc_value_t *v)
  378 {
  379         struct pmc *pm;
  380         pmc_value_t tmp;
  381 
  382         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  383             ("[core,%d] illegal cpu value %d", __LINE__, cpu));
  384         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  385             ("[core,%d] illegal row-index %d", __LINE__, ri));
  386 
  387         pm = core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
  388 
  389         KASSERT(pm,
  390             ("[core,%d] cpu %d ri %d(%d) pmc not configured", __LINE__, cpu,
  391                 ri, ri + core_iaf_ri));
  392 
  393         tmp = rdpmc(IAF_RI_TO_MSR(ri));
  394 
  395         if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
  396                 *v = iaf_perfctr_value_to_reload_count(tmp);
  397         else
  398                 *v = tmp & ((1ULL << core_iaf_width) - 1);
  399 
  400         PMCDBG4(MDP,REA,1, "iaf-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
  401             IAF_RI_TO_MSR(ri), *v);
  402 
  403         return (0);
  404 }
  405 
  406 static int
  407 iaf_release_pmc(int cpu, int ri, struct pmc *pmc)
  408 {
  409         PMCDBG3(MDP,REL,1, "iaf-release cpu=%d ri=%d pm=%p", cpu, ri, pmc);
  410 
  411         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  412             ("[core,%d] illegal CPU value %d", __LINE__, cpu));
  413         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  414             ("[core,%d] illegal row-index %d", __LINE__, ri));
  415 
  416         KASSERT(core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc == NULL,
  417             ("[core,%d] PHW pmc non-NULL", __LINE__));
  418 
  419         MPASS(pmc_alloc_refs > 0);
  420         if (pmc_alloc_refs-- == 1 && pmc_tsx_force_abort_set) {
  421                 pmc_tsx_force_abort_set = false;
  422                 x86_msr_op(MSR_TSX_FORCE_ABORT, MSR_OP_RENDEZVOUS_ALL |
  423                     MSR_OP_WRITE, 0, NULL);
  424         }
  425 
  426         return (0);
  427 }
  428 
  429 static int
  430 iaf_start_pmc(int cpu, int ri)
  431 {
  432         struct pmc *pm;
  433         struct core_cpu *cc;
  434 
  435         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  436             ("[core,%d] illegal CPU value %d", __LINE__, cpu));
  437         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  438             ("[core,%d] illegal row-index %d", __LINE__, ri));
  439 
  440         PMCDBG2(MDP,STA,1,"iaf-start cpu=%d ri=%d", cpu, ri);
  441 
  442         cc = core_pcpu[cpu];
  443         pm = cc->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
  444 
  445         cc->pc_iafctrl |= pm->pm_md.pm_iaf.pm_iaf_ctrl;
  446         wrmsr(IAF_CTRL, cc->pc_iafctrl);
  447 
  448         cc->pc_globalctrl |= (1ULL << (ri + IAF_OFFSET));
  449         wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
  450 
  451         PMCDBG4(MDP,STA,1,"iafctrl=%x(%x) globalctrl=%jx(%jx)",
  452             cc->pc_iafctrl, (uint32_t) rdmsr(IAF_CTRL),
  453             cc->pc_globalctrl, rdmsr(IA_GLOBAL_CTRL));
  454 
  455         return (0);
  456 }
  457 
  458 static int
  459 iaf_stop_pmc(int cpu, int ri)
  460 {
  461         struct core_cpu *cc;
  462 
  463         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  464             ("[core,%d] illegal CPU value %d", __LINE__, cpu));
  465         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  466             ("[core,%d] illegal row-index %d", __LINE__, ri));
  467 
  468         PMCDBG2(MDP,STA,1,"iaf-stop cpu=%d ri=%d", cpu, ri);
  469 
  470         cc = core_pcpu[cpu];
  471 
  472         cc->pc_iafctrl &= ~(IAF_MASK << (ri * 4));
  473         wrmsr(IAF_CTRL, cc->pc_iafctrl);
  474 
  475         /* Don't need to write IA_GLOBAL_CTRL, one disable is enough. */
  476 
  477         PMCDBG4(MDP,STO,1,"iafctrl=%x(%x) globalctrl=%jx(%jx)",
  478             cc->pc_iafctrl, (uint32_t) rdmsr(IAF_CTRL),
  479             cc->pc_globalctrl, rdmsr(IA_GLOBAL_CTRL));
  480 
  481         return (0);
  482 }
  483 
  484 static int
  485 iaf_write_pmc(int cpu, int ri, pmc_value_t v)
  486 {
  487         struct core_cpu *cc;
  488         struct pmc *pm;
  489 
  490         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  491             ("[core,%d] illegal cpu value %d", __LINE__, cpu));
  492         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  493             ("[core,%d] illegal row-index %d", __LINE__, ri));
  494 
  495         cc = core_pcpu[cpu];
  496         pm = cc->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
  497 
  498         KASSERT(pm,
  499             ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, ri));
  500 
  501         if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
  502                 v = iaf_reload_count_to_perfctr_value(v);
  503 
  504         /* Turn off the fixed counter */
  505         wrmsr(IAF_CTRL, cc->pc_iafctrl & ~(IAF_MASK << (ri * 4)));
  506 
  507         wrmsr(IAF_CTR0 + ri, v & ((1ULL << core_iaf_width) - 1));
  508 
  509         /* Turn on fixed counters */
  510         wrmsr(IAF_CTRL, cc->pc_iafctrl);
  511 
  512         PMCDBG6(MDP,WRI,1, "iaf-write cpu=%d ri=%d msr=0x%x v=%jx iafctrl=%jx "
  513             "pmc=%jx", cpu, ri, IAF_RI_TO_MSR(ri), v,
  514             (uintmax_t) rdmsr(IAF_CTRL),
  515             (uintmax_t) rdpmc(IAF_RI_TO_MSR(ri)));
  516 
  517         return (0);
  518 }
  519 
  520 
  521 static void
  522 iaf_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth)
  523 {
  524         struct pmc_classdep *pcd;
  525 
  526         KASSERT(md != NULL, ("[iaf,%d] md is NULL", __LINE__));
  527 
  528         PMCDBG0(MDP,INI,1, "iaf-initialize");
  529 
  530         pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF];
  531 
  532         pcd->pcd_caps   = IAF_PMC_CAPS;
  533         pcd->pcd_class  = PMC_CLASS_IAF;
  534         pcd->pcd_num    = npmc;
  535         pcd->pcd_ri     = md->pmd_npmc;
  536         pcd->pcd_width  = pmcwidth;
  537 
  538         pcd->pcd_allocate_pmc   = iaf_allocate_pmc;
  539         pcd->pcd_config_pmc     = iaf_config_pmc;
  540         pcd->pcd_describe       = iaf_describe;
  541         pcd->pcd_get_config     = iaf_get_config;
  542         pcd->pcd_get_msr        = iaf_get_msr;
  543         pcd->pcd_pcpu_fini      = core_pcpu_noop;
  544         pcd->pcd_pcpu_init      = core_pcpu_noop;
  545         pcd->pcd_read_pmc       = iaf_read_pmc;
  546         pcd->pcd_release_pmc    = iaf_release_pmc;
  547         pcd->pcd_start_pmc      = iaf_start_pmc;
  548         pcd->pcd_stop_pmc       = iaf_stop_pmc;
  549         pcd->pcd_write_pmc      = iaf_write_pmc;
  550 
  551         md->pmd_npmc           += npmc;
  552 }
  553 
  554 /*
  555  * Intel programmable PMCs.
  556  */
  557 
  558 /* Sub fields of UMASK that this event supports. */
  559 #define IAP_M_CORE              (1 << 0) /* Core specificity */
  560 #define IAP_M_AGENT             (1 << 1) /* Agent specificity */
  561 #define IAP_M_PREFETCH          (1 << 2) /* Prefetch */
  562 #define IAP_M_MESI              (1 << 3) /* MESI */
  563 #define IAP_M_SNOOPRESPONSE     (1 << 4) /* Snoop response */
  564 #define IAP_M_SNOOPTYPE         (1 << 5) /* Snoop type */
  565 #define IAP_M_TRANSITION        (1 << 6) /* Transition */
  566 
  567 #define IAP_F_CORE              (0x3 << 14) /* Core specificity */
  568 #define IAP_F_AGENT             (0x1 << 13) /* Agent specificity */
  569 #define IAP_F_PREFETCH          (0x3 << 12) /* Prefetch */
  570 #define IAP_F_MESI              (0xF <<  8) /* MESI */
  571 #define IAP_F_SNOOPRESPONSE     (0xB <<  8) /* Snoop response */
  572 #define IAP_F_SNOOPTYPE         (0x3 <<  8) /* Snoop type */
  573 #define IAP_F_TRANSITION        (0x1 << 12) /* Transition */
  574 
  575 #define IAP_PREFETCH_RESERVED   (0x2 << 12)
  576 #define IAP_CORE_THIS           (0x1 << 14)
  577 #define IAP_CORE_ALL            (0x3 << 14)
  578 #define IAP_F_CMASK             0xFF000000
  579 
  580 static pmc_value_t
  581 iap_perfctr_value_to_reload_count(pmc_value_t v)
  582 {
  583 
  584         /* If the PMC has overflowed, return a reload count of zero. */
  585         if ((v & (1ULL << (core_iap_width - 1))) == 0)
  586                 return (0);
  587         v &= (1ULL << core_iap_width) - 1;
  588         return (1ULL << core_iap_width) - v;
  589 }
  590 
  591 static pmc_value_t
  592 iap_reload_count_to_perfctr_value(pmc_value_t rlc)
  593 {
  594         return (1ULL << core_iap_width) - rlc;
  595 }
  596 
  597 static int
  598 iap_pmc_has_overflowed(int ri)
  599 {
  600         uint64_t v;
  601 
  602         /*
  603          * We treat a Core (i.e., Intel architecture v1) PMC as has
  604          * having overflowed if its MSB is zero.
  605          */
  606         v = rdpmc(ri);
  607         return ((v & (1ULL << (core_iap_width - 1))) == 0);
  608 }
  609 
  610 static int
  611 iap_event_corei7_ok_on_counter(uint8_t evsel, int ri)
  612 {
  613         uint32_t mask;
  614 
  615         switch (evsel) {
  616         /* Events valid only on counter 0, 1. */
  617         case 0x40:
  618         case 0x41:
  619         case 0x42:
  620         case 0x43:
  621         case 0x4C:
  622         case 0x4E:
  623         case 0x51:
  624         case 0x52:
  625         case 0x53:
  626         case 0x63:
  627                 mask = 0x3;
  628                 break;
  629         /* Any row index is ok. */
  630         default:
  631                 mask = ~0;
  632         }
  633 
  634         return (mask & (1 << ri));
  635 }
  636 
  637 static int
  638 iap_event_westmere_ok_on_counter(uint8_t evsel, int ri)
  639 {
  640         uint32_t mask;
  641 
  642         switch (evsel) {
  643         /* Events valid only on counter 0. */
  644         case 0x60:
  645         case 0xB3:
  646                 mask = 0x1;
  647                 break;
  648 
  649         /* Events valid only on counter 0, 1. */
  650         case 0x4C:
  651         case 0x4E:
  652         case 0x51:
  653         case 0x52:
  654         case 0x63:
  655                 mask = 0x3;
  656                 break;
  657         /* Any row index is ok. */
  658         default:
  659                 mask = ~0;
  660         }
  661 
  662         return (mask & (1 << ri));
  663 }
  664 
  665 static int
  666 iap_event_sb_sbx_ib_ibx_ok_on_counter(uint8_t evsel, int ri)
  667 {
  668         uint32_t mask;
  669 
  670         switch (evsel) {
  671         /* Events valid only on counter 0. */
  672         case 0xB7:
  673                 mask = 0x1;
  674                 break;
  675         /* Events valid only on counter 1. */
  676         case 0xC0:
  677                 mask = 0x2;
  678                 break;
  679         /* Events valid only on counter 2. */
  680         case 0x48:
  681         case 0xA2:
  682         case 0xA3:
  683                 mask = 0x4;
  684                 break;
  685         /* Events valid only on counter 3. */
  686         case 0xBB:
  687         case 0xCD:
  688                 mask = 0x8;
  689                 break;
  690         /* Any row index is ok. */
  691         default:
  692                 mask = ~0;
  693         }
  694 
  695         return (mask & (1 << ri));
  696 }
  697 
  698 static int
  699 iap_event_core_ok_on_counter(uint8_t evsel, int ri)
  700 {
  701         uint32_t mask;
  702 
  703         switch (evsel) {
  704                 /*
  705                  * Events valid only on counter 0.
  706                  */
  707         case 0x10:
  708         case 0x14:
  709         case 0x18:
  710         case 0xB3:
  711         case 0xC1:
  712         case 0xCB:
  713                 mask = (1 << 0);
  714                 break;
  715 
  716                 /*
  717                  * Events valid only on counter 1.
  718                  */
  719         case 0x11:
  720         case 0x12:
  721         case 0x13:
  722                 mask = (1 << 1);
  723                 break;
  724 
  725         default:
  726                 mask = ~0;      /* Any row index is ok. */
  727         }
  728 
  729         return (mask & (1 << ri));
  730 }
  731 
  732 static int
  733 iap_allocate_pmc(int cpu, int ri, struct pmc *pm,
  734     const struct pmc_op_pmcallocate *a)
  735 {
  736         uint8_t ev;
  737         const struct pmc_md_iap_op_pmcallocate *iap;
  738 
  739         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  740             ("[core,%d] illegal CPU %d", __LINE__, cpu));
  741         KASSERT(ri >= 0 && ri < core_iap_npmc,
  742             ("[core,%d] illegal row-index value %d", __LINE__, ri));
  743 
  744         if (a->pm_class != PMC_CLASS_IAP)
  745                 return (EINVAL);
  746 
  747         iap = &a->pm_md.pm_iap;
  748         ev = IAP_EVSEL_GET(iap->pm_iap_config);
  749 
  750         switch (core_cputype) {
  751         case PMC_CPU_INTEL_CORE:
  752         case PMC_CPU_INTEL_CORE2:
  753         case PMC_CPU_INTEL_CORE2EXTREME:
  754                 if (iap_event_core_ok_on_counter(ev, ri) == 0)
  755                         return (EINVAL);
  756         case PMC_CPU_INTEL_COREI7:
  757         case PMC_CPU_INTEL_NEHALEM_EX:
  758                 if (iap_event_corei7_ok_on_counter(ev, ri) == 0)
  759                         return (EINVAL);
  760                 break;
  761         case PMC_CPU_INTEL_WESTMERE:
  762         case PMC_CPU_INTEL_WESTMERE_EX:
  763                 if (iap_event_westmere_ok_on_counter(ev, ri) == 0)
  764                         return (EINVAL);
  765                 break;
  766         case PMC_CPU_INTEL_SANDYBRIDGE:
  767         case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
  768         case PMC_CPU_INTEL_IVYBRIDGE:
  769         case PMC_CPU_INTEL_IVYBRIDGE_XEON:
  770         case PMC_CPU_INTEL_HASWELL:
  771         case PMC_CPU_INTEL_HASWELL_XEON:
  772         case PMC_CPU_INTEL_BROADWELL:
  773         case PMC_CPU_INTEL_BROADWELL_XEON:
  774                 if (iap_event_sb_sbx_ib_ibx_ok_on_counter(ev, ri) == 0)
  775                         return (EINVAL);
  776                 break;
  777         case PMC_CPU_INTEL_ATOM:
  778         case PMC_CPU_INTEL_ATOM_SILVERMONT:
  779         case PMC_CPU_INTEL_ATOM_GOLDMONT:
  780         case PMC_CPU_INTEL_ATOM_GOLDMONT_P:
  781         case PMC_CPU_INTEL_ATOM_TREMONT:
  782         case PMC_CPU_INTEL_SKYLAKE:
  783         case PMC_CPU_INTEL_SKYLAKE_XEON:
  784         case PMC_CPU_INTEL_ICELAKE:
  785         case PMC_CPU_INTEL_ICELAKE_XEON:
  786         case PMC_CPU_INTEL_ALDERLAKE:
  787         default:
  788                 break;
  789         }
  790 
  791         pm->pm_md.pm_iap.pm_iap_evsel = iap->pm_iap_config;
  792         return (0);
  793 }
  794 
  795 static int
  796 iap_config_pmc(int cpu, int ri, struct pmc *pm)
  797 {
  798         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  799             ("[core,%d] illegal CPU %d", __LINE__, cpu));
  800 
  801         KASSERT(ri >= 0 && ri < core_iap_npmc,
  802             ("[core,%d] illegal row-index %d", __LINE__, ri));
  803 
  804         PMCDBG3(MDP,CFG,1, "iap-config cpu=%d ri=%d pm=%p", cpu, ri, pm);
  805 
  806         KASSERT(core_pcpu[cpu] != NULL, ("[core,%d] null per-cpu %d", __LINE__,
  807             cpu));
  808 
  809         core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc = pm;
  810 
  811         return (0);
  812 }
  813 
  814 static int
  815 iap_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
  816 {
  817         int error;
  818         struct pmc_hw *phw;
  819         char iap_name[PMC_NAME_MAX];
  820 
  821         phw = &core_pcpu[cpu]->pc_corepmcs[ri];
  822 
  823         (void) snprintf(iap_name, sizeof(iap_name), "IAP-%d", ri);
  824         if ((error = copystr(iap_name, pi->pm_name, PMC_NAME_MAX,
  825             NULL)) != 0)
  826                 return (error);
  827 
  828         pi->pm_class = PMC_CLASS_IAP;
  829 
  830         if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
  831                 pi->pm_enabled = TRUE;
  832                 *ppmc          = phw->phw_pmc;
  833         } else {
  834                 pi->pm_enabled = FALSE;
  835                 *ppmc          = NULL;
  836         }
  837 
  838         return (0);
  839 }
  840 
  841 static int
  842 iap_get_config(int cpu, int ri, struct pmc **ppm)
  843 {
  844         *ppm = core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc;
  845 
  846         return (0);
  847 }
  848 
  849 static int
  850 iap_get_msr(int ri, uint32_t *msr)
  851 {
  852         KASSERT(ri >= 0 && ri < core_iap_npmc,
  853             ("[iap,%d] ri %d out of range", __LINE__, ri));
  854 
  855         *msr = ri;
  856 
  857         return (0);
  858 }
  859 
  860 static int
  861 iap_read_pmc(int cpu, int ri, pmc_value_t *v)
  862 {
  863         struct pmc *pm;
  864         pmc_value_t tmp;
  865 
  866         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  867             ("[core,%d] illegal cpu value %d", __LINE__, cpu));
  868         KASSERT(ri >= 0 && ri < core_iap_npmc,
  869             ("[core,%d] illegal row-index %d", __LINE__, ri));
  870 
  871         pm = core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc;
  872 
  873         KASSERT(pm,
  874             ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu,
  875                 ri));
  876 
  877         tmp = rdpmc(ri);
  878         if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
  879                 *v = iap_perfctr_value_to_reload_count(tmp);
  880         else
  881                 *v = tmp & ((1ULL << core_iap_width) - 1);
  882 
  883         PMCDBG4(MDP,REA,1, "iap-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
  884             IAP_PMC0 + ri, *v);
  885 
  886         return (0);
  887 }
  888 
  889 static int
  890 iap_release_pmc(int cpu, int ri, struct pmc *pm)
  891 {
  892         (void) pm;
  893 
  894         PMCDBG3(MDP,REL,1, "iap-release cpu=%d ri=%d pm=%p", cpu, ri,
  895             pm);
  896 
  897         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  898             ("[core,%d] illegal CPU value %d", __LINE__, cpu));
  899         KASSERT(ri >= 0 && ri < core_iap_npmc,
  900             ("[core,%d] illegal row-index %d", __LINE__, ri));
  901 
  902         KASSERT(core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc
  903             == NULL, ("[core,%d] PHW pmc non-NULL", __LINE__));
  904 
  905         return (0);
  906 }
  907 
  908 static int
  909 iap_start_pmc(int cpu, int ri)
  910 {
  911         struct pmc *pm;
  912         uint64_t evsel;
  913         struct core_cpu *cc;
  914 
  915         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  916             ("[core,%d] illegal CPU value %d", __LINE__, cpu));
  917         KASSERT(ri >= 0 && ri < core_iap_npmc,
  918             ("[core,%d] illegal row-index %d", __LINE__, ri));
  919 
  920         cc = core_pcpu[cpu];
  921         pm = cc->pc_corepmcs[ri].phw_pmc;
  922 
  923         KASSERT(pm,
  924             ("[core,%d] starting cpu%d,ri%d with no pmc configured",
  925                 __LINE__, cpu, ri));
  926 
  927         PMCDBG2(MDP,STA,1, "iap-start cpu=%d ri=%d", cpu, ri);
  928 
  929         evsel = pm->pm_md.pm_iap.pm_iap_evsel;
  930 
  931         PMCDBG4(MDP,STA,2, "iap-start/2 cpu=%d ri=%d evselmsr=0x%x evsel=0x%x",
  932             cpu, ri, IAP_EVSEL0 + ri, evsel);
  933 
  934         /* Event specific configuration. */
  935 
  936         switch (IAP_EVSEL_GET(evsel)) {
  937         case 0xB7:
  938                 wrmsr(IA_OFFCORE_RSP0, pm->pm_md.pm_iap.pm_iap_rsp);
  939                 break;
  940         case 0xBB:
  941                 wrmsr(IA_OFFCORE_RSP1, pm->pm_md.pm_iap.pm_iap_rsp);
  942                 break;
  943         default:
  944                 break;
  945         }
  946 
  947         wrmsr(IAP_EVSEL0 + ri, evsel | IAP_EN);
  948 
  949         if (core_version >= 2) {
  950                 cc->pc_globalctrl |= (1ULL << ri);
  951                 wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
  952         }
  953 
  954         return (0);
  955 }
  956 
  957 static int
  958 iap_stop_pmc(int cpu, int ri)
  959 {
  960         struct pmc *pm __diagused;
  961         struct core_cpu *cc;
  962 
  963         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  964             ("[core,%d] illegal cpu value %d", __LINE__, cpu));
  965         KASSERT(ri >= 0 && ri < core_iap_npmc,
  966             ("[core,%d] illegal row index %d", __LINE__, ri));
  967 
  968         cc = core_pcpu[cpu];
  969         pm = cc->pc_corepmcs[ri].phw_pmc;
  970 
  971         KASSERT(pm,
  972             ("[core,%d] cpu%d ri%d no configured PMC to stop", __LINE__,
  973                 cpu, ri));
  974 
  975         PMCDBG2(MDP,STO,1, "iap-stop cpu=%d ri=%d", cpu, ri);
  976 
  977         wrmsr(IAP_EVSEL0 + ri, 0);
  978 
  979         /* Don't need to write IA_GLOBAL_CTRL, one disable is enough. */
  980 
  981         return (0);
  982 }
  983 
  984 static int
  985 iap_write_pmc(int cpu, int ri, pmc_value_t v)
  986 {
  987         struct pmc *pm;
  988         struct core_cpu *cc;
  989 
  990         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  991             ("[core,%d] illegal cpu value %d", __LINE__, cpu));
  992         KASSERT(ri >= 0 && ri < core_iap_npmc,
  993             ("[core,%d] illegal row index %d", __LINE__, ri));
  994 
  995         cc = core_pcpu[cpu];
  996         pm = cc->pc_corepmcs[ri].phw_pmc;
  997 
  998         KASSERT(pm,
  999             ("[core,%d] cpu%d ri%d no configured PMC to stop", __LINE__,
 1000                 cpu, ri));
 1001 
 1002         if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 1003                 v = iap_reload_count_to_perfctr_value(v);
 1004 
 1005         v &= (1ULL << core_iap_width) - 1;
 1006 
 1007         PMCDBG4(MDP,WRI,1, "iap-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri,
 1008             IAP_PMC0 + ri, v);
 1009 
 1010         /*
 1011          * Write the new value to the counter (or it's alias).  The
 1012          * counter will be in a stopped state when the pcd_write()
 1013          * entry point is called.
 1014          */
 1015         wrmsr(core_iap_wroffset + IAP_PMC0 + ri, v);
 1016         return (0);
 1017 }
 1018 
 1019 
 1020 static void
 1021 iap_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth,
 1022     int flags)
 1023 {
 1024         struct pmc_classdep *pcd;
 1025 
 1026         KASSERT(md != NULL, ("[iap,%d] md is NULL", __LINE__));
 1027 
 1028         PMCDBG0(MDP,INI,1, "iap-initialize");
 1029 
 1030         /* Remember the set of architectural events supported. */
 1031         core_architectural_events = ~flags;
 1032 
 1033         pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP];
 1034 
 1035         pcd->pcd_caps   = IAP_PMC_CAPS;
 1036         pcd->pcd_class  = PMC_CLASS_IAP;
 1037         pcd->pcd_num    = npmc;
 1038         pcd->pcd_ri     = md->pmd_npmc;
 1039         pcd->pcd_width  = pmcwidth;
 1040 
 1041         pcd->pcd_allocate_pmc   = iap_allocate_pmc;
 1042         pcd->pcd_config_pmc     = iap_config_pmc;
 1043         pcd->pcd_describe       = iap_describe;
 1044         pcd->pcd_get_config     = iap_get_config;
 1045         pcd->pcd_get_msr        = iap_get_msr;
 1046         pcd->pcd_pcpu_fini      = core_pcpu_fini;
 1047         pcd->pcd_pcpu_init      = core_pcpu_init;
 1048         pcd->pcd_read_pmc       = iap_read_pmc;
 1049         pcd->pcd_release_pmc    = iap_release_pmc;
 1050         pcd->pcd_start_pmc      = iap_start_pmc;
 1051         pcd->pcd_stop_pmc       = iap_stop_pmc;
 1052         pcd->pcd_write_pmc      = iap_write_pmc;
 1053 
 1054         md->pmd_npmc           += npmc;
 1055 }
 1056 
 1057 static int
 1058 core_intr(struct trapframe *tf)
 1059 {
 1060         pmc_value_t v;
 1061         struct pmc *pm;
 1062         struct core_cpu *cc;
 1063         int error, found_interrupt, ri;
 1064 
 1065         PMCDBG3(MDP,INT, 1, "cpu=%d tf=%p um=%d", curcpu, (void *) tf,
 1066             TRAPF_USERMODE(tf));
 1067 
 1068         found_interrupt = 0;
 1069         cc = core_pcpu[curcpu];
 1070 
 1071         for (ri = 0; ri < core_iap_npmc; ri++) {
 1072 
 1073                 if ((pm = cc->pc_corepmcs[ri].phw_pmc) == NULL ||
 1074                     !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 1075                         continue;
 1076 
 1077                 if (!iap_pmc_has_overflowed(ri))
 1078                         continue;
 1079 
 1080                 found_interrupt = 1;
 1081 
 1082                 if (pm->pm_state != PMC_STATE_RUNNING)
 1083                         continue;
 1084 
 1085                 error = pmc_process_interrupt(PMC_HR, pm, tf);
 1086 
 1087                 v = pm->pm_sc.pm_reloadcount;
 1088                 v = iap_reload_count_to_perfctr_value(v);
 1089 
 1090                 /*
 1091                  * Stop the counter, reload it but only restart it if
 1092                  * the PMC is not stalled.
 1093                  */
 1094                 wrmsr(IAP_EVSEL0 + ri, pm->pm_md.pm_iap.pm_iap_evsel);
 1095                 wrmsr(core_iap_wroffset + IAP_PMC0 + ri, v);
 1096 
 1097                 if (__predict_false(error))
 1098                         continue;
 1099 
 1100                 wrmsr(IAP_EVSEL0 + ri, pm->pm_md.pm_iap.pm_iap_evsel | IAP_EN);
 1101         }
 1102 
 1103         if (found_interrupt)
 1104                 counter_u64_add(pmc_stats.pm_intr_processed, 1);
 1105         else
 1106                 counter_u64_add(pmc_stats.pm_intr_ignored, 1);
 1107 
 1108         if (found_interrupt)
 1109                 lapic_reenable_pmc();
 1110 
 1111         return (found_interrupt);
 1112 }
 1113 
 1114 static int
 1115 core2_intr(struct trapframe *tf)
 1116 {
 1117         int error, found_interrupt = 0, n, cpu;
 1118         uint64_t flag, intrstatus, intrdisable = 0;
 1119         struct pmc *pm;
 1120         struct core_cpu *cc;
 1121         pmc_value_t v;
 1122 
 1123         cpu = curcpu;
 1124         PMCDBG3(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf,
 1125             TRAPF_USERMODE(tf));
 1126 
 1127         /*
 1128          * The IA_GLOBAL_STATUS (MSR 0x38E) register indicates which
 1129          * PMCs have a pending PMI interrupt.  We take a 'snapshot' of
 1130          * the current set of interrupting PMCs and process these
 1131          * after stopping them.
 1132          */
 1133         intrstatus = rdmsr(IA_GLOBAL_STATUS);
 1134         PMCDBG2(MDP,INT, 1, "cpu=%d intrstatus=%jx", cpu,
 1135             (uintmax_t) intrstatus);
 1136 
 1137         /*
 1138          * Stop PMCs unless hardware already done it.
 1139          */
 1140         if ((intrstatus & IA_GLOBAL_STATUS_FLAG_CTR_FRZ) == 0)
 1141                 wrmsr(IA_GLOBAL_CTRL, 0);
 1142 
 1143         cc = core_pcpu[cpu];
 1144         KASSERT(cc != NULL, ("[core,%d] null pcpu", __LINE__));
 1145 
 1146         /*
 1147          * Look for interrupts from fixed function PMCs.
 1148          */
 1149         for (n = 0, flag = (1ULL << IAF_OFFSET); n < core_iaf_npmc;
 1150              n++, flag <<= 1) {
 1151 
 1152                 if ((intrstatus & flag) == 0)
 1153                         continue;
 1154 
 1155                 found_interrupt = 1;
 1156 
 1157                 pm = cc->pc_corepmcs[n + core_iaf_ri].phw_pmc;
 1158                 if (pm == NULL || pm->pm_state != PMC_STATE_RUNNING ||
 1159                     !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 1160                         continue;
 1161 
 1162                 error = pmc_process_interrupt(PMC_HR, pm, tf);
 1163                 if (__predict_false(error))
 1164                         intrdisable |= flag;
 1165 
 1166                 v = iaf_reload_count_to_perfctr_value(pm->pm_sc.pm_reloadcount);
 1167 
 1168                 /* Reload sampling count. */
 1169                 wrmsr(IAF_CTR0 + n, v);
 1170 
 1171                 PMCDBG4(MDP,INT, 1, "iaf-intr cpu=%d error=%d v=%jx(%jx)", curcpu,
 1172                     error, (uintmax_t) v, (uintmax_t) rdpmc(IAF_RI_TO_MSR(n)));
 1173         }
 1174 
 1175         /*
 1176          * Process interrupts from the programmable counters.
 1177          */
 1178         for (n = 0, flag = 1; n < core_iap_npmc; n++, flag <<= 1) {
 1179                 if ((intrstatus & flag) == 0)
 1180                         continue;
 1181 
 1182                 found_interrupt = 1;
 1183 
 1184                 pm = cc->pc_corepmcs[n].phw_pmc;
 1185                 if (pm == NULL || pm->pm_state != PMC_STATE_RUNNING ||
 1186                     !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 1187                         continue;
 1188 
 1189                 error = pmc_process_interrupt(PMC_HR, pm, tf);
 1190                 if (__predict_false(error))
 1191                         intrdisable |= flag;
 1192 
 1193                 v = iap_reload_count_to_perfctr_value(pm->pm_sc.pm_reloadcount);
 1194 
 1195                 PMCDBG3(MDP,INT, 1, "iap-intr cpu=%d error=%d v=%jx", cpu, error,
 1196                     (uintmax_t) v);
 1197 
 1198                 /* Reload sampling count. */
 1199                 wrmsr(core_iap_wroffset + IAP_PMC0 + n, v);
 1200         }
 1201 
 1202         if (found_interrupt)
 1203                 counter_u64_add(pmc_stats.pm_intr_processed, 1);
 1204         else
 1205                 counter_u64_add(pmc_stats.pm_intr_ignored, 1);
 1206 
 1207         if (found_interrupt)
 1208                 lapic_reenable_pmc();
 1209 
 1210         /*
 1211          * Reenable all non-stalled PMCs.
 1212          */
 1213         if ((intrstatus & IA_GLOBAL_STATUS_FLAG_CTR_FRZ) == 0) {
 1214                 wrmsr(IA_GLOBAL_OVF_CTRL, intrstatus);
 1215                 cc->pc_globalctrl &= ~intrdisable;
 1216                 wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
 1217         } else {
 1218                 if (__predict_false(intrdisable)) {
 1219                         cc->pc_globalctrl &= ~intrdisable;
 1220                         wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
 1221                 }
 1222                 wrmsr(IA_GLOBAL_OVF_CTRL, intrstatus);
 1223         }
 1224 
 1225         PMCDBG4(MDP, INT, 1, "cpu=%d fixedctrl=%jx globalctrl=%jx status=%jx",
 1226             cpu, (uintmax_t) rdmsr(IAF_CTRL),
 1227             (uintmax_t) rdmsr(IA_GLOBAL_CTRL),
 1228             (uintmax_t) rdmsr(IA_GLOBAL_STATUS));
 1229 
 1230         return (found_interrupt);
 1231 }
 1232 
 1233 int
 1234 pmc_core_initialize(struct pmc_mdep *md, int maxcpu, int version_override)
 1235 {
 1236         int cpuid[CORE_CPUID_REQUEST_SIZE];
 1237         int flags, nflags;
 1238 
 1239         do_cpuid(CORE_CPUID_REQUEST, cpuid);
 1240 
 1241         core_cputype = md->pmd_cputype;
 1242         core_version = (version_override > 0) ? version_override :
 1243             cpuid[CORE_CPUID_EAX] & 0xFF;
 1244 
 1245         PMCDBG3(MDP,INI,1,"core-init cputype=%d ncpu=%d version=%d",
 1246             core_cputype, maxcpu, core_version);
 1247 
 1248         if (core_version < 1 || core_version > 5 ||
 1249             (core_cputype != PMC_CPU_INTEL_CORE && core_version == 1)) {
 1250                 /* Unknown PMC architecture. */
 1251                 printf("hwpc_core: unknown PMC architecture: %d\n",
 1252                     core_version);
 1253                 return (EPROGMISMATCH);
 1254         }
 1255 
 1256         core_iap_wroffset = 0;
 1257         if (cpu_feature2 & CPUID2_PDCM) {
 1258                 if (rdmsr(IA32_PERF_CAPABILITIES) & PERFCAP_FW_WRITE) {
 1259                         PMCDBG0(MDP, INI, 1,
 1260                             "core-init full-width write supported");
 1261                         core_iap_wroffset = IAP_A_PMC0 - IAP_PMC0;
 1262                 } else
 1263                         PMCDBG0(MDP, INI, 1,
 1264                             "core-init full-width write NOT supported");
 1265         } else
 1266                 PMCDBG0(MDP, INI, 1, "core-init pdcm not supported");
 1267 
 1268         core_pmcmask = 0;
 1269 
 1270         /*
 1271          * Initialize programmable counters.
 1272          */
 1273         core_iap_npmc = (cpuid[CORE_CPUID_EAX] >> 8) & 0xFF;
 1274         core_iap_width = (cpuid[CORE_CPUID_EAX] >> 16) & 0xFF;
 1275 
 1276         core_pmcmask |= ((1ULL << core_iap_npmc) - 1);
 1277 
 1278         nflags = (cpuid[CORE_CPUID_EAX] >> 24) & 0xFF;
 1279         flags = cpuid[CORE_CPUID_EBX] & ((1 << nflags) - 1);
 1280 
 1281         iap_initialize(md, maxcpu, core_iap_npmc, core_iap_width, flags);
 1282 
 1283         /*
 1284          * Initialize fixed function counters, if present.
 1285          */
 1286         if (core_version >= 2) {
 1287                 core_iaf_ri = core_iap_npmc;
 1288                 core_iaf_npmc = cpuid[CORE_CPUID_EDX] & 0x1F;
 1289                 core_iaf_width = (cpuid[CORE_CPUID_EDX] >> 5) & 0xFF;
 1290 
 1291                 iaf_initialize(md, maxcpu, core_iaf_npmc, core_iaf_width);
 1292                 core_pmcmask |= ((1ULL << core_iaf_npmc) - 1) << IAF_OFFSET;
 1293         }
 1294 
 1295         PMCDBG2(MDP,INI,1,"core-init pmcmask=0x%jx iafri=%d", core_pmcmask,
 1296             core_iaf_ri);
 1297 
 1298         core_pcpu = malloc(sizeof(*core_pcpu) * maxcpu, M_PMC,
 1299             M_ZERO | M_WAITOK);
 1300 
 1301         /*
 1302          * Choose the appropriate interrupt handler.
 1303          */
 1304         if (core_version >= 2)
 1305                 md->pmd_intr = core2_intr;
 1306         else
 1307                 md->pmd_intr = core_intr;
 1308 
 1309         md->pmd_pcpu_fini = NULL;
 1310         md->pmd_pcpu_init = NULL;
 1311 
 1312         return (0);
 1313 }
 1314 
 1315 void
 1316 pmc_core_finalize(struct pmc_mdep *md)
 1317 {
 1318         PMCDBG0(MDP,INI,1, "core-finalize");
 1319 
 1320         free(core_pcpu, M_PMC);
 1321         core_pcpu = NULL;
 1322 }

Cache object: 0a20300879da72fdb34f5ffb886f7443


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.