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  * Copyright (c) 2008 Joseph Koshy
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 /*
   28  * Intel Core, Core 2 and Atom PMCs.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/7.3/sys/dev/hwpmc/hwpmc_core.c 202015 2010-01-10 16:40:14Z fabient $");
   33 
   34 #include <sys/param.h>
   35 #include <sys/bus.h>
   36 #include <sys/pmc.h>
   37 #include <sys/pmckern.h>
   38 #include <sys/systm.h>
   39 
   40 #include <machine/intr_machdep.h>
   41 #include <machine/apicvar.h>
   42 #include <machine/cpu.h>
   43 #include <machine/cpufunc.h>
   44 #include <machine/specialreg.h>
   45 
   46 #define CORE_CPUID_REQUEST              0xA
   47 #define CORE_CPUID_REQUEST_SIZE         0x4
   48 #define CORE_CPUID_EAX                  0x0
   49 #define CORE_CPUID_EBX                  0x1
   50 #define CORE_CPUID_ECX                  0x2
   51 #define CORE_CPUID_EDX                  0x3
   52 
   53 #define IAF_PMC_CAPS                    \
   54         (PMC_CAP_READ | PMC_CAP_WRITE | PMC_CAP_INTERRUPT)
   55 #define IAF_RI_TO_MSR(RI)               ((RI) + (1 << 30))
   56 
   57 #define IAP_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | PMC_CAP_SYSTEM | \
   58     PMC_CAP_EDGE | PMC_CAP_THRESHOLD | PMC_CAP_READ | PMC_CAP_WRITE |    \
   59     PMC_CAP_INVERT | PMC_CAP_QUALIFIER | PMC_CAP_PRECISE)
   60 
   61 /*
   62  * "Architectural" events defined by Intel.  The values of these
   63  * symbols correspond to positions in the bitmask returned by
   64  * the CPUID.0AH instruction.
   65  */
   66 enum core_arch_events {
   67         CORE_AE_BRANCH_INSTRUCTION_RETIRED      = 5,
   68         CORE_AE_BRANCH_MISSES_RETIRED           = 6,
   69         CORE_AE_INSTRUCTION_RETIRED             = 1,
   70         CORE_AE_LLC_MISSES                      = 4,
   71         CORE_AE_LLC_REFERENCE                   = 3,
   72         CORE_AE_UNHALTED_REFERENCE_CYCLES       = 2,
   73         CORE_AE_UNHALTED_CORE_CYCLES            = 0
   74 };
   75 
   76 static enum pmc_cputype core_cputype;
   77 
   78 struct core_cpu {
   79         volatile uint32_t       pc_resync;
   80         volatile uint32_t       pc_iafctrl;     /* Fixed function control. */
   81         volatile uint64_t       pc_globalctrl;  /* Global control register. */
   82         struct pmc_hw           pc_corepmcs[];
   83 };
   84 
   85 static struct core_cpu **core_pcpu;
   86 
   87 static uint32_t core_architectural_events;
   88 static uint64_t core_pmcmask;
   89 
   90 static int core_iaf_ri;         /* relative index of fixed counters */
   91 static int core_iaf_width;
   92 static int core_iaf_npmc;
   93 
   94 static int core_iap_width;
   95 static int core_iap_npmc;
   96 
   97 static int
   98 core_pcpu_noop(struct pmc_mdep *md, int cpu)
   99 {
  100         (void) md;
  101         (void) cpu;
  102         return (0);
  103 }
  104 
  105 static int
  106 core_pcpu_init(struct pmc_mdep *md, int cpu)
  107 {
  108         struct pmc_cpu *pc;
  109         struct core_cpu *cc;
  110         struct pmc_hw *phw;
  111         int core_ri, n, npmc;
  112 
  113         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  114             ("[iaf,%d] insane cpu number %d", __LINE__, cpu));
  115 
  116         PMCDBG(MDP,INI,1,"core-init cpu=%d", cpu);
  117 
  118         core_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_ri;
  119         npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_num;
  120 
  121         if (core_cputype != PMC_CPU_INTEL_CORE)
  122                 npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF].pcd_num;
  123 
  124         cc = malloc(sizeof(struct core_cpu) + npmc * sizeof(struct pmc_hw),
  125             M_PMC, M_WAITOK | M_ZERO);
  126 
  127         core_pcpu[cpu] = cc;
  128         pc = pmc_pcpu[cpu];
  129 
  130         KASSERT(pc != NULL && cc != NULL,
  131             ("[core,%d] NULL per-cpu structures cpu=%d", __LINE__, cpu));
  132 
  133         for (n = 0, phw = cc->pc_corepmcs; n < npmc; n++, phw++) {
  134                 phw->phw_state    = PMC_PHW_FLAG_IS_ENABLED |
  135                     PMC_PHW_CPU_TO_STATE(cpu) |
  136                     PMC_PHW_INDEX_TO_STATE(n + core_ri);
  137                 phw->phw_pmc      = NULL;
  138                 pc->pc_hwpmcs[n + core_ri]  = phw;
  139         }
  140 
  141         return (0);
  142 }
  143 
  144 static int
  145 core_pcpu_fini(struct pmc_mdep *md, int cpu)
  146 {
  147         int core_ri, n, npmc;
  148         struct pmc_cpu *pc;
  149         struct core_cpu *cc;
  150 
  151         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  152             ("[core,%d] insane cpu number (%d)", __LINE__, cpu));
  153 
  154         PMCDBG(MDP,INI,1,"core-pcpu-fini cpu=%d", cpu);
  155 
  156         if ((cc = core_pcpu[cpu]) == NULL)
  157                 return (0);
  158 
  159         core_pcpu[cpu] = NULL;
  160 
  161         pc = pmc_pcpu[cpu];
  162 
  163         KASSERT(pc != NULL, ("[core,%d] NULL per-cpu %d state", __LINE__,
  164                 cpu));
  165 
  166         npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_num;
  167         core_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_ri;
  168 
  169         for (n = 0; n < npmc; n++)
  170                 wrmsr(IAP_EVSEL0 + n, 0);
  171 
  172         if (core_cputype != PMC_CPU_INTEL_CORE) {
  173                 wrmsr(IAF_CTRL, 0);
  174                 npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF].pcd_num;
  175         }
  176 
  177         for (n = 0; n < npmc; n++)
  178                 pc->pc_hwpmcs[n + core_ri] = NULL;
  179 
  180         free(cc, M_PMC);
  181 
  182         return (0);
  183 }
  184 
  185 /*
  186  * Fixed function counters.
  187  */
  188 
  189 static pmc_value_t
  190 iaf_perfctr_value_to_reload_count(pmc_value_t v)
  191 {
  192         v &= (1ULL << core_iaf_width) - 1;
  193         return (1ULL << core_iaf_width) - v;
  194 }
  195 
  196 static pmc_value_t
  197 iaf_reload_count_to_perfctr_value(pmc_value_t rlc)
  198 {
  199         return (1ULL << core_iaf_width) - rlc;
  200 }
  201 
  202 static int
  203 iaf_allocate_pmc(int cpu, int ri, struct pmc *pm,
  204     const struct pmc_op_pmcallocate *a)
  205 {
  206         enum pmc_event ev;
  207         uint32_t caps, flags, validflags;
  208 
  209         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  210             ("[core,%d] illegal CPU %d", __LINE__, cpu));
  211 
  212         PMCDBG(MDP,ALL,1, "iaf-allocate ri=%d reqcaps=0x%x", ri, pm->pm_caps);
  213 
  214         if (ri < 0 || ri > core_iaf_npmc)
  215                 return (EINVAL);
  216 
  217         caps = a->pm_caps;
  218 
  219         if (a->pm_class != PMC_CLASS_IAF ||
  220             (caps & IAF_PMC_CAPS) != caps)
  221                 return (EINVAL);
  222 
  223         ev = pm->pm_event;
  224         if (ev < PMC_EV_IAF_FIRST || ev > PMC_EV_IAF_LAST)
  225                 return (EINVAL);
  226 
  227         if (ev == PMC_EV_IAF_INSTR_RETIRED_ANY && ri != 0)
  228                 return (EINVAL);
  229         if (ev == PMC_EV_IAF_CPU_CLK_UNHALTED_CORE && ri != 1)
  230                 return (EINVAL);
  231         if (ev == PMC_EV_IAF_CPU_CLK_UNHALTED_REF && ri != 2)
  232                 return (EINVAL);
  233 
  234         flags = a->pm_md.pm_iaf.pm_iaf_flags;
  235 
  236         validflags = IAF_MASK;
  237 
  238         if (core_cputype != PMC_CPU_INTEL_ATOM)
  239                 validflags &= ~IAF_ANY;
  240 
  241         if ((flags & ~validflags) != 0)
  242                 return (EINVAL);
  243 
  244         if (caps & PMC_CAP_INTERRUPT)
  245                 flags |= IAF_PMI;
  246         if (caps & PMC_CAP_SYSTEM)
  247                 flags |= IAF_OS;
  248         if (caps & PMC_CAP_USER)
  249                 flags |= IAF_USR;
  250         if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
  251                 flags |= (IAF_OS | IAF_USR);
  252 
  253         pm->pm_md.pm_iaf.pm_iaf_ctrl = (flags << (ri * 4));
  254 
  255         PMCDBG(MDP,ALL,2, "iaf-allocate config=0x%jx",
  256             (uintmax_t) pm->pm_md.pm_iaf.pm_iaf_ctrl);
  257 
  258         return (0);
  259 }
  260 
  261 static int
  262 iaf_config_pmc(int cpu, int ri, struct pmc *pm)
  263 {
  264         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  265             ("[core,%d] illegal CPU %d", __LINE__, cpu));
  266 
  267         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  268             ("[core,%d] illegal row-index %d", __LINE__, ri));
  269 
  270         PMCDBG(MDP,CFG,1, "iaf-config cpu=%d ri=%d pm=%p", cpu, ri, pm);
  271 
  272         KASSERT(core_pcpu[cpu] != NULL, ("[core,%d] null per-cpu %d", __LINE__,
  273             cpu));
  274 
  275         core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc = pm;
  276 
  277         return (0);
  278 }
  279 
  280 static int
  281 iaf_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
  282 {
  283         int error;
  284         struct pmc_hw *phw;
  285         char iaf_name[PMC_NAME_MAX];
  286 
  287         phw = &core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri];
  288 
  289         (void) snprintf(iaf_name, sizeof(iaf_name), "IAF-%d", ri);
  290         if ((error = copystr(iaf_name, pi->pm_name, PMC_NAME_MAX,
  291             NULL)) != 0)
  292                 return (error);
  293 
  294         pi->pm_class = PMC_CLASS_IAF;
  295 
  296         if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
  297                 pi->pm_enabled = TRUE;
  298                 *ppmc          = phw->phw_pmc;
  299         } else {
  300                 pi->pm_enabled = FALSE;
  301                 *ppmc          = NULL;
  302         }
  303 
  304         return (0);
  305 }
  306 
  307 static int
  308 iaf_get_config(int cpu, int ri, struct pmc **ppm)
  309 {
  310         *ppm = core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
  311 
  312         return (0);
  313 }
  314 
  315 static int
  316 iaf_get_msr(int ri, uint32_t *msr)
  317 {
  318         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  319             ("[iaf,%d] ri %d out of range", __LINE__, ri));
  320 
  321         *msr = IAF_RI_TO_MSR(ri);
  322 
  323         return (0);
  324 }
  325 
  326 static int
  327 iaf_read_pmc(int cpu, int ri, pmc_value_t *v)
  328 {
  329         struct pmc *pm;
  330         pmc_value_t tmp;
  331 
  332         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  333             ("[core,%d] illegal cpu value %d", __LINE__, cpu));
  334         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  335             ("[core,%d] illegal row-index %d", __LINE__, ri));
  336 
  337         pm = core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
  338 
  339         KASSERT(pm,
  340             ("[core,%d] cpu %d ri %d(%d) pmc not configured", __LINE__, cpu,
  341                 ri, ri + core_iaf_ri));
  342 
  343         tmp = rdpmc(IAF_RI_TO_MSR(ri));
  344 
  345         if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
  346                 *v = iaf_perfctr_value_to_reload_count(tmp);
  347         else
  348                 *v = tmp;
  349 
  350         PMCDBG(MDP,REA,1, "iaf-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
  351             IAF_RI_TO_MSR(ri), *v);
  352 
  353         return (0);
  354 }
  355 
  356 static int
  357 iaf_release_pmc(int cpu, int ri, struct pmc *pmc)
  358 {
  359         PMCDBG(MDP,REL,1, "iaf-release cpu=%d ri=%d pm=%p", cpu, ri, pmc);
  360 
  361         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  362             ("[core,%d] illegal CPU value %d", __LINE__, cpu));
  363         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  364             ("[core,%d] illegal row-index %d", __LINE__, ri));
  365 
  366         KASSERT(core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc == NULL,
  367             ("[core,%d] PHW pmc non-NULL", __LINE__));
  368 
  369         return (0);
  370 }
  371 
  372 static int
  373 iaf_start_pmc(int cpu, int ri)
  374 {
  375         struct pmc *pm;
  376         struct core_cpu *iafc;
  377 
  378         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  379             ("[core,%d] illegal CPU value %d", __LINE__, cpu));
  380         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  381             ("[core,%d] illegal row-index %d", __LINE__, ri));
  382 
  383         PMCDBG(MDP,STA,1,"iaf-start cpu=%d ri=%d", cpu, ri);
  384 
  385         iafc = core_pcpu[cpu];
  386         pm = iafc->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
  387 
  388         iafc->pc_iafctrl |= pm->pm_md.pm_iaf.pm_iaf_ctrl;
  389 
  390         wrmsr(IAF_CTRL, iafc->pc_iafctrl);
  391 
  392         do {
  393                 iafc->pc_resync = 0;
  394                 iafc->pc_globalctrl |= (1ULL << (ri + IAF_OFFSET));
  395                 wrmsr(IA_GLOBAL_CTRL, iafc->pc_globalctrl);
  396         } while (iafc->pc_resync != 0);
  397 
  398         PMCDBG(MDP,STA,1,"iafctrl=%x(%x) globalctrl=%jx(%jx)",
  399             iafc->pc_iafctrl, (uint32_t) rdmsr(IAF_CTRL),
  400             iafc->pc_globalctrl, rdmsr(IA_GLOBAL_CTRL));
  401 
  402         return (0);
  403 }
  404 
  405 static int
  406 iaf_stop_pmc(int cpu, int ri)
  407 {
  408         uint32_t fc;
  409         struct core_cpu *iafc;
  410 
  411         PMCDBG(MDP,STO,1,"iaf-stop cpu=%d ri=%d", cpu, ri);
  412 
  413         iafc = core_pcpu[cpu];
  414 
  415         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  416             ("[core,%d] illegal CPU value %d", __LINE__, cpu));
  417         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  418             ("[core,%d] illegal row-index %d", __LINE__, ri));
  419 
  420         fc = (IAF_MASK << (ri * 4));
  421 
  422         if (core_cputype != PMC_CPU_INTEL_ATOM)
  423                 fc &= ~IAF_ANY;
  424 
  425         iafc->pc_iafctrl &= ~fc;
  426 
  427         PMCDBG(MDP,STO,1,"iaf-stop iafctrl=%x", iafc->pc_iafctrl);
  428         wrmsr(IAF_CTRL, iafc->pc_iafctrl);
  429 
  430         do {
  431                 iafc->pc_resync = 0;
  432                 iafc->pc_globalctrl &= ~(1ULL << (ri + IAF_OFFSET));
  433                 wrmsr(IA_GLOBAL_CTRL, iafc->pc_globalctrl);
  434         } while (iafc->pc_resync != 0);
  435 
  436         PMCDBG(MDP,STO,1,"iafctrl=%x(%x) globalctrl=%jx(%jx)",
  437             iafc->pc_iafctrl, (uint32_t) rdmsr(IAF_CTRL),
  438             iafc->pc_globalctrl, rdmsr(IA_GLOBAL_CTRL));
  439 
  440         return (0);
  441 }
  442 
  443 static int
  444 iaf_write_pmc(int cpu, int ri, pmc_value_t v)
  445 {
  446         struct core_cpu *cc;
  447         struct pmc *pm;
  448 
  449         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
  450             ("[core,%d] illegal cpu value %d", __LINE__, cpu));
  451         KASSERT(ri >= 0 && ri < core_iaf_npmc,
  452             ("[core,%d] illegal row-index %d", __LINE__, ri));
  453 
  454         cc = core_pcpu[cpu];
  455         pm = cc->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
  456 
  457         KASSERT(pm,
  458             ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, ri));
  459 
  460         if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
  461                 v = iaf_reload_count_to_perfctr_value(v);
  462 
  463         wrmsr(IAF_CTRL, 0);     /* Turn off fixed counters */
  464         wrmsr(IAF_CTR0 + ri, v);
  465         wrmsr(IAF_CTRL, cc->pc_iafctrl);
  466 
  467         PMCDBG(MDP,WRI,1, "iaf-write cpu=%d ri=%d msr=0x%x v=%jx iafctrl=%jx "
  468             "pmc=%jx", cpu, ri, IAF_RI_TO_MSR(ri), v,
  469             (uintmax_t) rdmsr(IAF_CTRL),
  470             (uintmax_t) rdpmc(IAF_RI_TO_MSR(ri)));
  471 
  472         return (0);
  473 }
  474 
  475 
  476 static void
  477 iaf_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth)
  478 {
  479         struct pmc_classdep *pcd;
  480 
  481         KASSERT(md != NULL, ("[iaf,%d] md is NULL", __LINE__));
  482 
  483         PMCDBG(MDP,INI,1, "%s", "iaf-initialize");
  484 
  485         pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF];
  486 
  487         pcd->pcd_caps   = IAF_PMC_CAPS;
  488         pcd->pcd_class  = PMC_CLASS_IAF;
  489         pcd->pcd_num    = npmc;
  490         pcd->pcd_ri     = md->pmd_npmc;
  491         pcd->pcd_width  = pmcwidth;
  492 
  493         pcd->pcd_allocate_pmc   = iaf_allocate_pmc;
  494         pcd->pcd_config_pmc     = iaf_config_pmc;
  495         pcd->pcd_describe       = iaf_describe;
  496         pcd->pcd_get_config     = iaf_get_config;
  497         pcd->pcd_get_msr        = iaf_get_msr;
  498         pcd->pcd_pcpu_fini      = core_pcpu_noop;
  499         pcd->pcd_pcpu_init      = core_pcpu_noop;
  500         pcd->pcd_read_pmc       = iaf_read_pmc;
  501         pcd->pcd_release_pmc    = iaf_release_pmc;
  502         pcd->pcd_start_pmc      = iaf_start_pmc;
  503         pcd->pcd_stop_pmc       = iaf_stop_pmc;
  504         pcd->pcd_write_pmc      = iaf_write_pmc;
  505 
  506         md->pmd_npmc           += npmc;
  507 }
  508 
  509 /*
  510  * Intel programmable PMCs.
  511  */
  512 
  513 /*
  514  * Event descriptor tables.
  515  *
  516  * For each event id, we track:
  517  *
  518  * 1. The CPUs that the event is valid for.
  519  *
  520  * 2. If the event uses a fixed UMASK, the value of the umask field.
  521  *    If the event doesn't use a fixed UMASK, a mask of legal bits
  522  *    to check against.
  523  */
  524 
  525 struct iap_event_descr {
  526         enum pmc_event  iap_ev;
  527         unsigned char   iap_evcode;
  528         unsigned char   iap_umask;
  529         unsigned char   iap_flags;
  530 };
  531 
  532 #define IAP_F_CC        (1 << 0)        /* CPU: Core */
  533 #define IAP_F_CC2       (1 << 1)        /* CPU: Core2 family */
  534 #define IAP_F_CC2E      (1 << 2)        /* CPU: Core2 Extreme only */
  535 #define IAP_F_CA        (1 << 3)        /* CPU: Atom */
  536 #define IAP_F_I7        (1 << 4)        /* CPU: Core i7 */
  537 #define IAP_F_FM        (1 << 5)        /* Fixed mask */
  538 
  539 #define IAP_F_ALLCPUS                                           \
  540     (IAP_F_CC | IAP_F_CC2 | IAP_F_CC2E | IAP_F_CA | IAP_F_I7)
  541 
  542 /* Sub fields of UMASK that this event supports. */
  543 #define IAP_M_CORE              (1 << 0) /* Core specificity */
  544 #define IAP_M_AGENT             (1 << 1) /* Agent specificity */
  545 #define IAP_M_PREFETCH          (1 << 2) /* Prefetch */
  546 #define IAP_M_MESI              (1 << 3) /* MESI */
  547 #define IAP_M_SNOOPRESPONSE     (1 << 4) /* Snoop response */
  548 #define IAP_M_SNOOPTYPE         (1 << 5) /* Snoop type */
  549 #define IAP_M_TRANSITION        (1 << 6) /* Transition */
  550 
  551 #define IAP_F_CORE              (0x3 << 14) /* Core specificity */
  552 #define IAP_F_AGENT             (0x1 << 13) /* Agent specificity */
  553 #define IAP_F_PREFETCH          (0x3 << 12) /* Prefetch */
  554 #define IAP_F_MESI              (0xF <<  8) /* MESI */
  555 #define IAP_F_SNOOPRESPONSE     (0xB <<  8) /* Snoop response */
  556 #define IAP_F_SNOOPTYPE         (0x3 <<  8) /* Snoop type */
  557 #define IAP_F_TRANSITION        (0x1 << 12) /* Transition */
  558 
  559 #define IAP_PREFETCH_RESERVED   (0x2 << 12)
  560 #define IAP_CORE_THIS           (0x1 << 14)
  561 #define IAP_CORE_ALL            (0x3 << 14)
  562 #define IAP_F_CMASK             0xFF000000
  563 
  564 static struct iap_event_descr iap_events[] = {
  565 #undef IAPDESCR
  566 #define IAPDESCR(N,EV,UM,FLAGS) {                                       \
  567         .iap_ev = PMC_EV_IAP_EVENT_##N,                                 \
  568         .iap_evcode = (EV),                                             \
  569         .iap_umask = (UM),                                              \
  570         .iap_flags = (FLAGS)                                            \
  571         }
  572 
  573     IAPDESCR(02H_81H, 0x02, 0x81, IAP_F_FM | IAP_F_CA),
  574 
  575     IAPDESCR(03H_00H, 0x03, 0x00, IAP_F_FM | IAP_F_CC),
  576     IAPDESCR(03H_02H, 0x03, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  577     IAPDESCR(03H_04H, 0x03, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  578     IAPDESCR(03H_08H, 0x03, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  579     IAPDESCR(03H_10H, 0x03, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  580     IAPDESCR(03H_20H, 0x03, 0x20, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  581 
  582     IAPDESCR(04H_00H, 0x04, 0x00, IAP_F_FM | IAP_F_CC),
  583     IAPDESCR(04H_01H, 0x04, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  584     IAPDESCR(04H_02H, 0x04, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  585     IAPDESCR(04H_08H, 0x04, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  586 
  587     IAPDESCR(05H_00H, 0x05, 0x00, IAP_F_FM | IAP_F_CC),
  588 
  589     IAPDESCR(06H_00H, 0x06, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  590 
  591     IAPDESCR(07H_00H, 0x07, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
  592     IAPDESCR(07H_01H, 0x07, 0x01, IAP_F_FM | IAP_F_ALLCPUS),
  593     IAPDESCR(07H_02H, 0x07, 0x02, IAP_F_FM | IAP_F_ALLCPUS),
  594     IAPDESCR(07H_03H, 0x07, 0x03, IAP_F_FM | IAP_F_ALLCPUS),
  595     IAPDESCR(07H_06H, 0x07, 0x06, IAP_F_FM | IAP_F_CA),
  596     IAPDESCR(07H_08H, 0x07, 0x08, IAP_F_FM | IAP_F_CA),
  597 
  598     IAPDESCR(08H_01H, 0x08, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  599     IAPDESCR(08H_02H, 0x08, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  600     IAPDESCR(08H_04H, 0x08, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  601     IAPDESCR(08H_05H, 0x08, 0x05, IAP_F_FM | IAP_F_CA),
  602     IAPDESCR(08H_06H, 0x08, 0x06, IAP_F_FM | IAP_F_CA),
  603     IAPDESCR(08H_07H, 0x08, 0x07, IAP_F_FM | IAP_F_CA),
  604     IAPDESCR(08H_08H, 0x08, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  605     IAPDESCR(08H_09H, 0x08, 0x09, IAP_F_FM | IAP_F_CA),
  606 
  607     IAPDESCR(09H_01H, 0x09, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  608     IAPDESCR(09H_02H, 0x09, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  609 
  610     IAPDESCR(0CH_01H, 0x0C, 0x01, IAP_F_FM | IAP_F_CC2 | IAP_F_I7),
  611     IAPDESCR(0CH_02H, 0x0C, 0x02, IAP_F_FM | IAP_F_CC2),
  612     IAPDESCR(0CH_03H, 0x0C, 0x03, IAP_F_FM | IAP_F_CA),
  613 
  614     IAPDESCR(10H_00H, 0x10, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  615     IAPDESCR(10H_01H, 0x10, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7),
  616     IAPDESCR(10H_81H, 0x10, 0x81, IAP_F_FM | IAP_F_CA),
  617 
  618     IAPDESCR(11H_00H, 0x11, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
  619     IAPDESCR(11H_01H, 0x11, 0x01, IAP_F_FM | IAP_F_CA),
  620     IAPDESCR(11H_81H, 0x11, 0x81, IAP_F_FM | IAP_F_CA),
  621 
  622     IAPDESCR(12H_00H, 0x12, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  623     IAPDESCR(12H_01H, 0x12, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7),
  624     IAPDESCR(12H_81H, 0x12, 0x81, IAP_F_FM | IAP_F_CA),
  625 
  626     IAPDESCR(13H_00H, 0x13, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  627     IAPDESCR(13H_01H, 0x13, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7),
  628     IAPDESCR(13H_81H, 0x13, 0x81, IAP_F_FM | IAP_F_CA),
  629 
  630     IAPDESCR(14H_00H, 0x14, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
  631     IAPDESCR(14H_01H, 0x14, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7),
  632 
  633     IAPDESCR(18H_00H, 0x18, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  634 
  635     IAPDESCR(19H_00H, 0x19, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  636     IAPDESCR(19H_01H, 0x19, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  637     IAPDESCR(19H_02H, 0x19, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  638 
  639     IAPDESCR(21H, 0x21, IAP_M_CORE, IAP_F_ALLCPUS),
  640     IAPDESCR(22H, 0x22, IAP_M_CORE, IAP_F_CC2),
  641     IAPDESCR(23H, 0x23, IAP_M_CORE, IAP_F_ALLCPUS),
  642     IAPDESCR(24H, 0x24, IAP_M_CORE | IAP_M_PREFETCH, IAP_F_ALLCPUS),
  643     IAPDESCR(25H, 0x25, IAP_M_CORE, IAP_F_ALLCPUS),
  644     IAPDESCR(26H, 0x26, IAP_M_CORE | IAP_M_PREFETCH, IAP_F_ALLCPUS),
  645     IAPDESCR(27H, 0x27, IAP_M_CORE | IAP_M_PREFETCH, IAP_F_ALLCPUS),
  646     IAPDESCR(28H, 0x28, IAP_M_CORE | IAP_M_MESI, IAP_F_ALLCPUS),
  647     IAPDESCR(29H, 0x29, IAP_M_CORE | IAP_M_MESI, IAP_F_CC),
  648     IAPDESCR(29H, 0x29, IAP_M_CORE | IAP_M_MESI | IAP_M_PREFETCH,
  649         IAP_F_CA | IAP_F_CC2),
  650     IAPDESCR(2AH, 0x2A, IAP_M_CORE | IAP_M_MESI, IAP_F_ALLCPUS),
  651     IAPDESCR(2BH, 0x2B, IAP_M_CORE | IAP_M_MESI, IAP_F_CA | IAP_F_CC2),
  652 
  653     IAPDESCR(2EH, 0x2E, IAP_M_CORE | IAP_M_MESI | IAP_M_PREFETCH,
  654         IAP_F_ALLCPUS),
  655     IAPDESCR(2EH_41H, 0x2E, 0x41, IAP_F_FM | IAP_F_ALLCPUS),
  656     IAPDESCR(2EH_4FH, 0x2E, 0x4F, IAP_F_FM | IAP_F_ALLCPUS),
  657 
  658     IAPDESCR(30H, 0x30, IAP_M_CORE | IAP_M_MESI | IAP_M_PREFETCH,
  659         IAP_F_ALLCPUS),
  660     IAPDESCR(32H, 0x32, IAP_M_CORE | IAP_M_MESI | IAP_M_PREFETCH, IAP_F_CC),
  661     IAPDESCR(32H, 0x32, IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
  662 
  663     IAPDESCR(3AH, 0x3A, IAP_M_TRANSITION, IAP_F_CC),
  664     IAPDESCR(3AH_00H, 0x3A, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  665 
  666     IAPDESCR(3BH_C0H, 0x3B, 0xC0, IAP_F_FM | IAP_F_ALLCPUS),
  667 
  668     IAPDESCR(3CH_00H, 0x3C, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  669     IAPDESCR(3CH_01H, 0x3C, 0x01, IAP_F_FM | IAP_F_ALLCPUS),
  670     IAPDESCR(3CH_02H, 0x3C, 0x02, IAP_F_FM | IAP_F_ALLCPUS),
  671 
  672     IAPDESCR(40H, 0x40, IAP_M_MESI, IAP_F_CC | IAP_F_CC2),
  673     IAPDESCR(40H_21H, 0x40, 0x21, IAP_F_FM | IAP_F_CA),
  674 
  675     IAPDESCR(41H, 0x41, IAP_M_MESI, IAP_F_CC | IAP_F_CC2),
  676     IAPDESCR(41H_22H, 0x41, 0x22, IAP_F_FM | IAP_F_CA),
  677 
  678     IAPDESCR(42H, 0x42, IAP_M_MESI, IAP_F_ALLCPUS),
  679     IAPDESCR(42H_10H, 0x42, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  680 
  681     IAPDESCR(43H_01H, 0x43, 0x01, IAP_F_FM | IAP_F_ALLCPUS),
  682     IAPDESCR(43H_02H, 0x43, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  683 
  684     IAPDESCR(44H_02H, 0x44, 0x02, IAP_F_FM | IAP_F_CC),
  685 
  686     IAPDESCR(45H_0FH, 0x45, 0x0F, IAP_F_FM | IAP_F_ALLCPUS),
  687 
  688     IAPDESCR(46H_00H, 0x46, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  689     IAPDESCR(47H_00H, 0x47, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  690     IAPDESCR(48H_00H, 0x48, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  691 
  692     IAPDESCR(49H_00H, 0x49, 0x00, IAP_F_FM | IAP_F_CC),
  693     IAPDESCR(49H_01H, 0x49, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  694     IAPDESCR(49H_02H, 0x49, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  695 
  696     IAPDESCR(4BH_00H, 0x4B, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  697     IAPDESCR(4BH_01H, 0x4B, 0x01, IAP_F_FM | IAP_F_ALLCPUS),
  698     IAPDESCR(4BH_02H, 0x4B, 0x02, IAP_F_FM | IAP_F_ALLCPUS),
  699     IAPDESCR(4BH_03H, 0x4B, 0x03, IAP_F_FM | IAP_F_CC),
  700 
  701     IAPDESCR(4CH_00H, 0x4C, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  702 
  703     IAPDESCR(4EH_10H, 0x4E, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  704 
  705     IAPDESCR(4FH_00H, 0x4F, 0x00, IAP_F_FM | IAP_F_CC),
  706 
  707     IAPDESCR(60H, 0x60, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
  708 
  709     IAPDESCR(61H, 0x61, IAP_M_AGENT, IAP_F_CA | IAP_F_CC2),
  710     IAPDESCR(61H_00H, 0x61, 0x00, IAP_F_FM | IAP_F_CC),
  711 
  712     IAPDESCR(62H, 0x62, IAP_M_AGENT, IAP_F_ALLCPUS),
  713     IAPDESCR(62H_00H, 0x62, 0x00, IAP_F_FM | IAP_F_CC),
  714 
  715     IAPDESCR(63H, 0x63, IAP_M_AGENT | IAP_M_CORE,
  716         IAP_F_CA | IAP_F_CC2),
  717     IAPDESCR(63H, 0x63, IAP_M_CORE, IAP_F_CC),
  718 
  719     IAPDESCR(64H, 0x64, IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
  720     IAPDESCR(64H_40H, 0x64, 0x40, IAP_F_FM | IAP_F_CC),
  721 
  722     IAPDESCR(65H, 0x65, IAP_M_AGENT | IAP_M_CORE,
  723         IAP_F_CA | IAP_F_CC2),
  724     IAPDESCR(65H, 0x65, IAP_M_CORE, IAP_F_CC),
  725 
  726     IAPDESCR(66H, 0x66, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
  727 
  728     IAPDESCR(67H, 0x67, IAP_M_AGENT | IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
  729     IAPDESCR(67H, 0x67, IAP_M_AGENT, IAP_F_CC),
  730 
  731     IAPDESCR(68H, 0x68, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
  732     IAPDESCR(69H, 0x69, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
  733     IAPDESCR(6AH, 0x6A, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
  734     IAPDESCR(6BH, 0x6B, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
  735     IAPDESCR(6CH, 0x6C, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
  736 
  737     IAPDESCR(6DH, 0x6D, IAP_M_AGENT | IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
  738     IAPDESCR(6DH, 0x6D, IAP_M_CORE, IAP_F_CC),
  739 
  740     IAPDESCR(6EH, 0x6E, IAP_M_AGENT | IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
  741     IAPDESCR(6EH, 0x6E, IAP_M_CORE, IAP_F_CC),
  742 
  743     IAPDESCR(6FH, 0x6F, IAP_M_AGENT | IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
  744     IAPDESCR(6FH, 0x6F, IAP_M_CORE, IAP_F_CC),
  745 
  746     IAPDESCR(70H, 0x70, IAP_M_AGENT | IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
  747     IAPDESCR(70H, 0x70, IAP_M_CORE, IAP_F_CC),
  748 
  749     IAPDESCR(77H, 0x77, IAP_M_AGENT | IAP_M_SNOOPRESPONSE,
  750         IAP_F_CA | IAP_F_CC2),
  751     IAPDESCR(77H, 0x77, IAP_M_AGENT | IAP_M_MESI, IAP_F_CC),
  752 
  753     IAPDESCR(78H, 0x78, IAP_M_CORE, IAP_F_CC),
  754     IAPDESCR(78H, 0x78, IAP_M_CORE | IAP_M_SNOOPTYPE, IAP_F_CA | IAP_F_CC2),
  755 
  756     IAPDESCR(7AH, 0x7A, IAP_M_AGENT, IAP_F_CA | IAP_F_CC2),
  757 
  758     IAPDESCR(7BH, 0x7B, IAP_M_AGENT, IAP_F_CA | IAP_F_CC2),
  759 
  760     IAPDESCR(7DH, 0x7D, IAP_M_CORE, IAP_F_ALLCPUS),
  761 
  762     IAPDESCR(7EH, 0x7E, IAP_M_AGENT | IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
  763     IAPDESCR(7EH_00H, 0x7E, 0x00, IAP_F_FM | IAP_F_CC),
  764 
  765     IAPDESCR(7FH, 0x7F, IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
  766 
  767     IAPDESCR(80H_00H, 0x80, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  768     IAPDESCR(80H_02H, 0x80, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_I7),
  769     IAPDESCR(80H_03H, 0x80, 0x03, IAP_F_FM | IAP_F_CA | IAP_F_I7),
  770 
  771     IAPDESCR(81H_00H, 0x81, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  772 
  773     IAPDESCR(82H_02H, 0x82, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  774     IAPDESCR(82H_04H, 0x82, 0x04, IAP_F_FM | IAP_F_CA),
  775     IAPDESCR(82H_10H, 0x82, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  776     IAPDESCR(82H_12H, 0x82, 0x12, IAP_F_FM | IAP_F_CC2),
  777     IAPDESCR(82H_40H, 0x82, 0x40, IAP_F_FM | IAP_F_CC2),
  778 
  779     IAPDESCR(83H_02H, 0x83, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  780 
  781     IAPDESCR(85H_00H, 0x85, 0x00, IAP_F_FM | IAP_F_CC),
  782 
  783     IAPDESCR(86H_00H, 0x86, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  784 
  785     IAPDESCR(87H_00H, 0x87, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  786 
  787     IAPDESCR(88H_00H, 0x88, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  788     IAPDESCR(89H_00H, 0x89, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  789     IAPDESCR(8AH_00H, 0x8A, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  790     IAPDESCR(8BH_00H, 0x8B, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  791     IAPDESCR(8CH_00H, 0x8C, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  792     IAPDESCR(8DH_00H, 0x8D, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  793     IAPDESCR(8EH_00H, 0x8E, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  794     IAPDESCR(8FH_00H, 0x8F, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  795 
  796     IAPDESCR(90H_00H, 0x90, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  797     IAPDESCR(91H_00H, 0x91, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  798     IAPDESCR(92H_00H, 0x92, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  799     IAPDESCR(93H_00H, 0x93, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  800     IAPDESCR(94H_00H, 0x94, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  801 
  802     IAPDESCR(97H_00H, 0x97, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  803     IAPDESCR(98H_00H, 0x98, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  804     IAPDESCR(A0H_00H, 0xA0, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  805 
  806     IAPDESCR(A1H_01H, 0xA1, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  807     IAPDESCR(A1H_02H, 0xA1, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  808     IAPDESCR(A1H_04H, 0xA1, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  809     IAPDESCR(A1H_08H, 0xA1, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  810     IAPDESCR(A1H_10H, 0xA1, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  811     IAPDESCR(A1H_20H, 0xA1, 0x20, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  812 
  813     IAPDESCR(A2H_00H, 0xA2, 0x00, IAP_F_FM | IAP_F_CC),
  814 
  815     IAPDESCR(AAH_01H, 0xAA, 0x01, IAP_F_FM | IAP_F_CC2),
  816     IAPDESCR(AAH_02H, 0xAA, 0x02, IAP_F_FM | IAP_F_CA),
  817     IAPDESCR(AAH_03H, 0xAA, 0x03, IAP_F_FM | IAP_F_CA),
  818     IAPDESCR(AAH_08H, 0xAA, 0x08, IAP_F_FM | IAP_F_CC2),
  819 
  820     IAPDESCR(ABH_01H, 0xAB, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  821     IAPDESCR(ABH_02H, 0xAB, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  822 
  823     IAPDESCR(B0H_00H, 0xB0, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  824     IAPDESCR(B0H_80H, 0xB0, 0x80, IAP_F_FM | IAP_F_CA | IAP_F_I7),
  825 
  826     IAPDESCR(B1H_00H, 0xB1, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  827     IAPDESCR(B1H_80H, 0xB1, 0x80, IAP_F_FM | IAP_F_CA | IAP_F_I7),
  828 
  829     IAPDESCR(B3H_01H, 0xB3, 0x01, IAP_F_FM | IAP_F_ALLCPUS),
  830     IAPDESCR(B3H_02H, 0xB3, 0x02, IAP_F_FM | IAP_F_ALLCPUS),
  831     IAPDESCR(B3H_04H, 0xB3, 0x04, IAP_F_FM | IAP_F_ALLCPUS),
  832     IAPDESCR(B3H_08H, 0xB3, 0x08, IAP_F_FM | IAP_F_ALLCPUS),
  833     IAPDESCR(B3H_10H, 0xB3, 0x10, IAP_F_FM | IAP_F_ALLCPUS),
  834     IAPDESCR(B3H_20H, 0xB3, 0x20, IAP_F_FM | IAP_F_ALLCPUS),
  835     IAPDESCR(B3H_81H, 0xB3, 0x81, IAP_F_FM | IAP_F_CA),
  836     IAPDESCR(B3H_82H, 0xB3, 0x82, IAP_F_FM | IAP_F_CA),
  837     IAPDESCR(B3H_84H, 0xB3, 0x84, IAP_F_FM | IAP_F_CA),
  838     IAPDESCR(B3H_88H, 0xB3, 0x88, IAP_F_FM | IAP_F_CA),
  839     IAPDESCR(B3H_90H, 0xB3, 0x90, IAP_F_FM | IAP_F_CA),
  840     IAPDESCR(B3H_A0H, 0xB3, 0xA0, IAP_F_FM | IAP_F_CA),
  841 
  842     IAPDESCR(C0H_00H, 0xC0, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  843     IAPDESCR(C0H_01H, 0xC0, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  844     IAPDESCR(C0H_02H, 0xC0, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  845     IAPDESCR(C0H_04H, 0xC0, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  846     IAPDESCR(C0H_08H, 0xC0, 0x08, IAP_F_FM | IAP_F_CC2E),
  847 
  848     IAPDESCR(C1H_00H, 0xC1, 0x00, IAP_F_FM | IAP_F_CC),
  849     IAPDESCR(C1H_01H, 0xC1, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  850     IAPDESCR(C1H_FEH, 0xC1, 0xFE, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  851 
  852     IAPDESCR(C2H_00H, 0xC2, 0x00, IAP_F_FM | IAP_F_CC),
  853     IAPDESCR(C2H_01H, 0xC2, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  854     IAPDESCR(C2H_02H, 0xC2, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  855     IAPDESCR(C2H_04H, 0xC2, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  856     IAPDESCR(C2H_07H, 0xC2, 0x07, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  857     IAPDESCR(C2H_08H, 0xC2, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  858     IAPDESCR(C2H_0FH, 0xC2, 0x0F, IAP_F_FM | IAP_F_CC2),
  859     IAPDESCR(C2H_10H, 0xC2, 0x10, IAP_F_FM | IAP_F_CA),
  860 
  861     IAPDESCR(C3H_00H, 0xC3, 0x00, IAP_F_FM | IAP_F_CC),
  862     IAPDESCR(C3H_01H, 0xC3, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  863     IAPDESCR(C3H_04H, 0xC3, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  864 
  865     IAPDESCR(C4H_00H, 0xC4, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  866     IAPDESCR(C4H_01H, 0xC4, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  867     IAPDESCR(C4H_02H, 0xC4, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  868     IAPDESCR(C4H_04H, 0xC4, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  869     IAPDESCR(C4H_08H, 0xC4, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  870     IAPDESCR(C4H_0CH, 0xC4, 0x0C, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  871     IAPDESCR(C4H_0FH, 0xC4, 0x0F, IAP_F_FM | IAP_F_CA),
  872 
  873     IAPDESCR(C5H_00H, 0xC5, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  874 
  875     IAPDESCR(C6H_00H, 0xC6, 0x00, IAP_F_FM | IAP_F_CC),
  876     IAPDESCR(C6H_01H, 0xC6, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  877     IAPDESCR(C6H_02H, 0xC6, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  878 
  879     IAPDESCR(C7H_00H, 0xC7, 0x00, IAP_F_FM | IAP_F_CC),
  880     IAPDESCR(C7H_01H, 0xC7, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  881     IAPDESCR(C7H_02H, 0xC7, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  882     IAPDESCR(C7H_04H, 0xC7, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  883     IAPDESCR(C7H_08H, 0xC7, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  884     IAPDESCR(C7H_10H, 0xC7, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  885     IAPDESCR(C7H_1FH, 0xC7, 0x1F, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  886 
  887     IAPDESCR(C8H_00H, 0xC8, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  888 
  889     IAPDESCR(C9H_00H, 0xC9, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  890 
  891     IAPDESCR(CAH_00H, 0xCA, 0x00, IAP_F_FM | IAP_F_CC),
  892     IAPDESCR(CAH_01H, 0xCA, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  893     IAPDESCR(CAH_02H, 0xCA, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  894     IAPDESCR(CAH_04H, 0xCA, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  895     IAPDESCR(CAH_08H, 0xCA, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  896 
  897     IAPDESCR(CBH_01H, 0xCB, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  898     IAPDESCR(CBH_02H, 0xCB, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  899     IAPDESCR(CBH_04H, 0xCB, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  900     IAPDESCR(CBH_08H, 0xCB, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  901     IAPDESCR(CBH_10H, 0xCB, 0x10, IAP_F_FM | IAP_F_CC2 | IAP_F_I7),
  902 
  903     IAPDESCR(CCH_00H, 0xCC, 0x00, IAP_F_FM | IAP_F_CC),
  904     IAPDESCR(CCH_01H, 0xCC, 0x01, IAP_F_FM | IAP_F_ALLCPUS),
  905     IAPDESCR(CCH_02H, 0xCC, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  906 
  907     IAPDESCR(CDH_00H, 0xCD, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  908     IAPDESCR(CEH_00H, 0xCE, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  909     IAPDESCR(CFH_00H, 0xCF, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  910 
  911     IAPDESCR(D0H_00H, 0xD0, 0x00, IAP_F_FM | IAP_F_CC),
  912 
  913     IAPDESCR(D2H_01H, 0xD2, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  914     IAPDESCR(D2H_02H, 0xD2, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  915     IAPDESCR(D2H_04H, 0xD2, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  916     IAPDESCR(D2H_08H, 0xD2, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  917     IAPDESCR(D2H_0FH, 0xD2, 0x0F, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  918     IAPDESCR(D2H_10H, 0xD2, 0x10, IAP_F_FM | IAP_F_CC2E),
  919 
  920     IAPDESCR(D4H_01H, 0xD4, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  921     IAPDESCR(D4H_02H, 0xD4, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  922     IAPDESCR(D4H_04H, 0xD4, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  923     IAPDESCR(D4H_08H, 0xD4, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  924     IAPDESCR(D4H_0FH, 0xD4, 0x0F, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  925 
  926     IAPDESCR(D5H_01H, 0xD5, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
  927     IAPDESCR(D5H_02H, 0xD5, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  928     IAPDESCR(D5H_04H, 0xD5, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  929     IAPDESCR(D5H_08H, 0xD5, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  930     IAPDESCR(D5H_0FH, 0xD5, 0x0F, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  931 
  932     IAPDESCR(D7H_00H, 0xD7, 0x00, IAP_F_FM | IAP_F_CC),
  933 
  934     IAPDESCR(D8H_00H, 0xD8, 0x00, IAP_F_FM | IAP_F_CC),
  935     IAPDESCR(D8H_01H, 0xD8, 0x01, IAP_F_FM | IAP_F_CC),
  936     IAPDESCR(D8H_02H, 0xD8, 0x02, IAP_F_FM | IAP_F_CC),
  937     IAPDESCR(D8H_03H, 0xD8, 0x03, IAP_F_FM | IAP_F_CC),
  938     IAPDESCR(D8H_04H, 0xD8, 0x04, IAP_F_FM | IAP_F_CC),
  939 
  940     IAPDESCR(D9H_00H, 0xD9, 0x00, IAP_F_FM | IAP_F_CC),
  941     IAPDESCR(D9H_01H, 0xD9, 0x01, IAP_F_FM | IAP_F_CC),
  942     IAPDESCR(D9H_02H, 0xD9, 0x02, IAP_F_FM | IAP_F_CC),
  943     IAPDESCR(D9H_03H, 0xD9, 0x03, IAP_F_FM | IAP_F_CC),
  944 
  945     IAPDESCR(DAH_00H, 0xDA, 0x00, IAP_F_FM | IAP_F_CC),
  946     IAPDESCR(DAH_01H, 0xDA, 0x01, IAP_F_FM | IAP_F_CC),
  947     IAPDESCR(DAH_02H, 0xDA, 0x02, IAP_F_FM | IAP_F_CC),
  948 
  949     IAPDESCR(DBH_00H, 0xDB, 0x00, IAP_F_FM | IAP_F_CC),
  950 
  951     IAPDESCR(DCH_01H, 0xDC, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  952     IAPDESCR(DCH_02H, 0xDC, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  953     IAPDESCR(DCH_04H, 0xDC, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  954     IAPDESCR(DCH_08H, 0xDC, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  955     IAPDESCR(DCH_10H, 0xDC, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  956     IAPDESCR(DCH_1FH, 0xDC, 0x1F, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
  957 
  958     IAPDESCR(E0H_00H, 0xE0, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
  959     IAPDESCR(E0H_01H, 0xE0, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7),
  960 
  961     IAPDESCR(E2H_00H, 0xE2, 0x00, IAP_F_FM | IAP_F_CC),
  962     IAPDESCR(E4H_00H, 0xE4, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  963 
  964     IAPDESCR(E6H_00H, 0xE6, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
  965     IAPDESCR(E6H_01H, 0xE6, 0x01, IAP_F_FM | IAP_F_CA),
  966 
  967     IAPDESCR(F0H_00H, 0xF0, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  968     IAPDESCR(F8H_00H, 0xF8, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
  969 
  970     /* Added with nehalem. */
  971     IAPDESCR(02H_01H, 0x02, 0x01, IAP_F_FM | IAP_F_I7),
  972     IAPDESCR(03H_01H, 0x03, 0x01, IAP_F_FM | IAP_F_I7),
  973     IAPDESCR(05H_01H, 0x05, 0x01, IAP_F_FM | IAP_F_I7),
  974     IAPDESCR(05H_02H, 0x05, 0x02, IAP_F_FM | IAP_F_I7),
  975     IAPDESCR(05H_03H, 0x05, 0x03, IAP_F_FM | IAP_F_I7),
  976     IAPDESCR(06H_01H, 0x06, 0x01, IAP_F_FM | IAP_F_I7),
  977     IAPDESCR(06H_02H, 0x06, 0x02, IAP_F_FM | IAP_F_I7),
  978     IAPDESCR(06H_04H, 0x06, 0x04, IAP_F_FM | IAP_F_I7),
  979     IAPDESCR(06H_08H, 0x06, 0x08, IAP_F_FM | IAP_F_I7),
  980     IAPDESCR(06H_0FH, 0x06, 0x0F, IAP_F_FM | IAP_F_I7),
  981     IAPDESCR(08H_10H, 0x08, 0x10, IAP_F_FM | IAP_F_I7),
  982     IAPDESCR(08H_20H, 0x08, 0x20, IAP_F_FM | IAP_F_I7),
  983     IAPDESCR(08H_40H, 0x08, 0x40, IAP_F_FM | IAP_F_I7),
  984     IAPDESCR(08H_80H, 0x08, 0x80, IAP_F_FM | IAP_F_I7),
  985     IAPDESCR(09H_04H, 0x09, 0x04, IAP_F_FM | IAP_F_I7),
  986     IAPDESCR(09H_08H, 0x09, 0x08, IAP_F_FM | IAP_F_I7),
  987     IAPDESCR(0BH_01H, 0x0B, 0x01, IAP_F_FM | IAP_F_I7),
  988     IAPDESCR(0BH_02H, 0x0B, 0x02, IAP_F_FM | IAP_F_I7),
  989     IAPDESCR(0EH_01H, 0x0E, 0x01, IAP_F_FM | IAP_F_I7),
  990     IAPDESCR(0EH_02H, 0x0E, 0x02, IAP_F_FM | IAP_F_I7),
  991     IAPDESCR(0FH_02H, 0x0F, 0x02, IAP_F_FM | IAP_F_I7),
  992     IAPDESCR(0FH_08H, 0x0F, 0x08, IAP_F_FM | IAP_F_I7),
  993     IAPDESCR(0FH_10H, 0x0F, 0x10, IAP_F_FM | IAP_F_I7),
  994     IAPDESCR(0FH_20H, 0x0F, 0x20, IAP_F_FM | IAP_F_I7),
  995     IAPDESCR(10H_02H, 0x10, 0x02, IAP_F_FM | IAP_F_I7),
  996     IAPDESCR(10H_04H, 0x10, 0x04, IAP_F_FM | IAP_F_I7),
  997     IAPDESCR(10H_08H, 0x10, 0x08, IAP_F_FM | IAP_F_I7),
  998     IAPDESCR(10H_10H, 0x10, 0x10, IAP_F_FM | IAP_F_I7),
  999     IAPDESCR(10H_20H, 0x10, 0x20, IAP_F_FM | IAP_F_I7),
 1000     IAPDESCR(10H_40H, 0x10, 0x40, IAP_F_FM | IAP_F_I7),
 1001     IAPDESCR(10H_80H, 0x10, 0x80, IAP_F_FM | IAP_F_I7),
 1002     IAPDESCR(12H_02H, 0x12, 0x02, IAP_F_FM | IAP_F_I7),
 1003     IAPDESCR(12H_04H, 0x12, 0x04, IAP_F_FM | IAP_F_I7),
 1004     IAPDESCR(12H_08H, 0x12, 0x08, IAP_F_FM | IAP_F_I7),
 1005     IAPDESCR(12H_10H, 0x12, 0x10, IAP_F_FM | IAP_F_I7),
 1006     IAPDESCR(12H_20H, 0x12, 0x20, IAP_F_FM | IAP_F_I7),
 1007     IAPDESCR(12H_40H, 0x12, 0x40, IAP_F_FM | IAP_F_I7),
 1008     IAPDESCR(13H_02H, 0x13, 0x02, IAP_F_FM | IAP_F_I7),
 1009     IAPDESCR(13H_04H, 0x13, 0x04, IAP_F_FM | IAP_F_I7),
 1010     IAPDESCR(13H_07H, 0x13, 0x07, IAP_F_FM | IAP_F_I7),
 1011     IAPDESCR(14H_02H, 0x14, 0x02, IAP_F_FM | IAP_F_I7),
 1012     IAPDESCR(17H_01H, 0x17, 0x01, IAP_F_FM | IAP_F_I7),
 1013     IAPDESCR(18H_01H, 0x18, 0x01, IAP_F_FM | IAP_F_I7),
 1014     IAPDESCR(1DH_01H, 0x1D, 0x01, IAP_F_FM | IAP_F_I7),
 1015     IAPDESCR(1DH_02H, 0x1D, 0x02, IAP_F_FM | IAP_F_I7),
 1016     IAPDESCR(1DH_04H, 0x1D, 0x04, IAP_F_FM | IAP_F_I7),
 1017     IAPDESCR(1EH_01H, 0x1E, 0x01, IAP_F_FM | IAP_F_I7),
 1018     IAPDESCR(24H_01H, 0x24, 0x01, IAP_F_FM | IAP_F_I7),
 1019     IAPDESCR(24H_02H, 0x24, 0x02, IAP_F_FM | IAP_F_I7),
 1020     IAPDESCR(24H_03H, 0x24, 0x03, IAP_F_FM | IAP_F_I7),
 1021     IAPDESCR(24H_04H, 0x24, 0x04, IAP_F_FM | IAP_F_I7),
 1022     IAPDESCR(24H_08H, 0x24, 0x08, IAP_F_FM | IAP_F_I7),
 1023     IAPDESCR(24H_0CH, 0x24, 0x0C, IAP_F_FM | IAP_F_I7),
 1024     IAPDESCR(24H_10H, 0x24, 0x10, IAP_F_FM | IAP_F_I7),
 1025     IAPDESCR(24H_20H, 0x24, 0x20, IAP_F_FM | IAP_F_I7),
 1026     IAPDESCR(24H_30H, 0x24, 0x30, IAP_F_FM | IAP_F_I7),
 1027     IAPDESCR(24H_40H, 0x24, 0x40, IAP_F_FM | IAP_F_I7),
 1028     IAPDESCR(24H_80H, 0x24, 0x80, IAP_F_FM | IAP_F_I7),
 1029     IAPDESCR(24H_AAH, 0x24, 0xAA, IAP_F_FM | IAP_F_I7),
 1030     IAPDESCR(24H_C0H, 0x24, 0xC0, IAP_F_FM | IAP_F_I7),
 1031     IAPDESCR(24H_FFH, 0x24, 0xFF, IAP_F_FM | IAP_F_I7),
 1032     IAPDESCR(26H_01H, 0x26, 0x01, IAP_F_FM | IAP_F_I7),
 1033     IAPDESCR(26H_02H, 0x26, 0x02, IAP_F_FM | IAP_F_I7),
 1034     IAPDESCR(26H_04H, 0x26, 0x04, IAP_F_FM | IAP_F_I7),
 1035     IAPDESCR(26H_08H, 0x26, 0x08, IAP_F_FM | IAP_F_I7),
 1036     IAPDESCR(26H_0FH, 0x26, 0x0F, IAP_F_FM | IAP_F_I7),
 1037     IAPDESCR(26H_10H, 0x26, 0x10, IAP_F_FM | IAP_F_I7),
 1038     IAPDESCR(26H_20H, 0x26, 0x20, IAP_F_FM | IAP_F_I7),
 1039     IAPDESCR(26H_40H, 0x26, 0x40, IAP_F_FM | IAP_F_I7),
 1040     IAPDESCR(26H_80H, 0x26, 0x80, IAP_F_FM | IAP_F_I7),
 1041     IAPDESCR(26H_F0H, 0x26, 0xF0, IAP_F_FM | IAP_F_I7),
 1042     IAPDESCR(26H_FFH, 0x26, 0xFF, IAP_F_FM | IAP_F_I7),
 1043     IAPDESCR(27H_01H, 0x27, 0x01, IAP_F_FM | IAP_F_I7),
 1044     IAPDESCR(27H_02H, 0x27, 0x02, IAP_F_FM | IAP_F_I7),
 1045     IAPDESCR(27H_04H, 0x27, 0x04, IAP_F_FM | IAP_F_I7),
 1046     IAPDESCR(27H_08H, 0x27, 0x08, IAP_F_FM | IAP_F_I7),
 1047     IAPDESCR(27H_0EH, 0x27, 0x0E, IAP_F_FM | IAP_F_I7),
 1048     IAPDESCR(27H_0FH, 0x27, 0x0F, IAP_F_FM | IAP_F_I7),
 1049     IAPDESCR(27H_10H, 0x27, 0x10, IAP_F_FM | IAP_F_I7),
 1050     IAPDESCR(27H_20H, 0x27, 0x20, IAP_F_FM | IAP_F_I7),
 1051     IAPDESCR(27H_40H, 0x27, 0x40, IAP_F_FM | IAP_F_I7),
 1052     IAPDESCR(27H_80H, 0x27, 0x80, IAP_F_FM | IAP_F_I7),
 1053     IAPDESCR(27H_E0H, 0x27, 0xE0, IAP_F_FM | IAP_F_I7),
 1054     IAPDESCR(27H_F0H, 0x27, 0xF0, IAP_F_FM | IAP_F_I7),
 1055     IAPDESCR(28H_01H, 0x28, 0x01, IAP_F_FM | IAP_F_I7),
 1056     IAPDESCR(28H_02H, 0x28, 0x02, IAP_F_FM | IAP_F_I7),
 1057     IAPDESCR(28H_04H, 0x28, 0x04, IAP_F_FM | IAP_F_I7),
 1058     IAPDESCR(28H_08H, 0x28, 0x08, IAP_F_FM | IAP_F_I7),
 1059     IAPDESCR(28H_0FH, 0x28, 0x0F, IAP_F_FM | IAP_F_I7),
 1060     IAPDESCR(3DH_01H, 0x3D, 0x01, IAP_F_FM | IAP_F_I7),
 1061     IAPDESCR(40H_01H, 0x40, 0x01, IAP_F_FM | IAP_F_I7),
 1062     IAPDESCR(40H_02H, 0x40, 0x02, IAP_F_FM | IAP_F_I7),
 1063     IAPDESCR(40H_04H, 0x40, 0x04, IAP_F_FM | IAP_F_I7),
 1064     IAPDESCR(40H_08H, 0x40, 0x08, IAP_F_FM | IAP_F_I7),
 1065     IAPDESCR(40H_0FH, 0x40, 0x0F, IAP_F_FM | IAP_F_I7),
 1066     IAPDESCR(41H_01H, 0x41, 0x01, IAP_F_FM | IAP_F_I7),
 1067     IAPDESCR(41H_02H, 0x41, 0x02, IAP_F_FM | IAP_F_I7),
 1068     IAPDESCR(41H_04H, 0x41, 0x04, IAP_F_FM | IAP_F_I7),
 1069     IAPDESCR(41H_08H, 0x41, 0x08, IAP_F_FM | IAP_F_I7),
 1070     IAPDESCR(41H_0FH, 0x41, 0x0F, IAP_F_FM | IAP_F_I7),
 1071     IAPDESCR(42H_01H, 0x42, 0x01, IAP_F_FM | IAP_F_I7),
 1072     IAPDESCR(42H_02H, 0x42, 0x02, IAP_F_FM | IAP_F_I7),
 1073     IAPDESCR(42H_04H, 0x42, 0x04, IAP_F_FM | IAP_F_I7),
 1074     IAPDESCR(42H_08H, 0x42, 0x08, IAP_F_FM | IAP_F_I7),
 1075     IAPDESCR(48H_02H, 0x48, 0x02, IAP_F_FM | IAP_F_I7),
 1076     IAPDESCR(49H_10H, 0x49, 0x10, IAP_F_FM | IAP_F_I7),
 1077     IAPDESCR(49H_20H, 0x49, 0x20, IAP_F_FM | IAP_F_I7),
 1078     IAPDESCR(49H_40H, 0x49, 0x40, IAP_F_FM | IAP_F_I7),
 1079     IAPDESCR(49H_80H, 0x49, 0x80, IAP_F_FM | IAP_F_I7),
 1080     IAPDESCR(4BH_08H, 0x4B, 0x08, IAP_F_FM | IAP_F_I7),
 1081     IAPDESCR(4CH_01H, 0x4C, 0x01, IAP_F_FM | IAP_F_I7),
 1082     IAPDESCR(4DH_01H, 0x4D, 0x01, IAP_F_FM | IAP_F_I7),
 1083     IAPDESCR(4EH_01H, 0x4E, 0x01, IAP_F_FM | IAP_F_I7),
 1084     IAPDESCR(4EH_02H, 0x4E, 0x02, IAP_F_FM | IAP_F_I7),
 1085     IAPDESCR(4EH_04H, 0x4E, 0x04, IAP_F_FM | IAP_F_I7),
 1086     IAPDESCR(4FH_02H, 0x4F, 0x02, IAP_F_FM | IAP_F_I7),
 1087     IAPDESCR(4FH_04H, 0x4F, 0x04, IAP_F_FM | IAP_F_I7),
 1088     IAPDESCR(4FH_08H, 0x4F, 0x08, IAP_F_FM | IAP_F_I7),
 1089     IAPDESCR(51H_01H, 0x51, 0x01, IAP_F_FM | IAP_F_I7),
 1090     IAPDESCR(51H_02H, 0x51, 0x02, IAP_F_FM | IAP_F_I7),
 1091     IAPDESCR(51H_04H, 0x51, 0x04, IAP_F_FM | IAP_F_I7),
 1092     IAPDESCR(51H_08H, 0x51, 0x08, IAP_F_FM | IAP_F_I7),
 1093     IAPDESCR(52H_01H, 0x52, 0x01, IAP_F_FM | IAP_F_I7),
 1094     IAPDESCR(53H_01H, 0x53, 0x01, IAP_F_FM | IAP_F_I7),
 1095     IAPDESCR(60H_01H, 0x60, 0x01, IAP_F_FM | IAP_F_I7),
 1096     IAPDESCR(60H_02H, 0x60, 0x02, IAP_F_FM | IAP_F_I7),
 1097     IAPDESCR(60H_04H, 0x60, 0x04, IAP_F_FM | IAP_F_I7),
 1098     IAPDESCR(60H_08H, 0x60, 0x08, IAP_F_FM | IAP_F_I7),
 1099     IAPDESCR(63H_01H, 0x63, 0x01, IAP_F_FM | IAP_F_I7),
 1100     IAPDESCR(63H_02H, 0x63, 0x02, IAP_F_FM | IAP_F_I7),
 1101     IAPDESCR(6CH_01H, 0x6C, 0x01, IAP_F_FM | IAP_F_I7),
 1102     IAPDESCR(80H_01H, 0x80, 0x01, IAP_F_FM | IAP_F_I7),
 1103     IAPDESCR(80H_04H, 0x80, 0x04, IAP_F_FM | IAP_F_I7),
 1104     IAPDESCR(80H_10H, 0x80, 0x10, IAP_F_FM | IAP_F_I7),
 1105     IAPDESCR(81H_01H, 0x81, 0x01, IAP_F_FM | IAP_F_I7),
 1106     IAPDESCR(81H_02H, 0x81, 0x02, IAP_F_FM | IAP_F_I7),
 1107     IAPDESCR(82H_01H, 0x82, 0x01, IAP_F_FM | IAP_F_I7),
 1108     IAPDESCR(83H_01H, 0x83, 0x01, IAP_F_FM | IAP_F_I7),
 1109     IAPDESCR(85H_01H, 0x85, 0x01, IAP_F_FM | IAP_F_I7),
 1110     IAPDESCR(85H_02H, 0x85, 0x02, IAP_F_FM | IAP_F_I7),
 1111     IAPDESCR(85H_04H, 0x85, 0x04, IAP_F_FM | IAP_F_I7),
 1112     IAPDESCR(85H_10H, 0x85, 0x10, IAP_F_FM | IAP_F_I7),
 1113     IAPDESCR(85H_20H, 0x85, 0x20, IAP_F_FM | IAP_F_I7),
 1114     IAPDESCR(85H_40H, 0x85, 0x40, IAP_F_FM | IAP_F_I7),
 1115     IAPDESCR(85H_80H, 0x85, 0x80, IAP_F_FM | IAP_F_I7),
 1116     IAPDESCR(87H_01H, 0x87, 0x01, IAP_F_FM | IAP_F_I7),
 1117     IAPDESCR(87H_02H, 0x87, 0x02, IAP_F_FM | IAP_F_I7),
 1118     IAPDESCR(87H_04H, 0x87, 0x04, IAP_F_FM | IAP_F_I7),
 1119     IAPDESCR(87H_08H, 0x87, 0x08, IAP_F_FM | IAP_F_I7),
 1120     IAPDESCR(87H_0FH, 0x87, 0x0F, IAP_F_FM | IAP_F_I7),
 1121     IAPDESCR(88H_01H, 0x88, 0x01, IAP_F_FM | IAP_F_I7),
 1122     IAPDESCR(88H_02H, 0x88, 0x02, IAP_F_FM | IAP_F_I7),
 1123     IAPDESCR(88H_04H, 0x88, 0x04, IAP_F_FM | IAP_F_I7),
 1124     IAPDESCR(88H_07H, 0x88, 0x07, IAP_F_FM | IAP_F_I7),
 1125     IAPDESCR(88H_08H, 0x88, 0x08, IAP_F_FM | IAP_F_I7),
 1126     IAPDESCR(88H_10H, 0x88, 0x10, IAP_F_FM | IAP_F_I7),
 1127     IAPDESCR(88H_20H, 0x88, 0x20, IAP_F_FM | IAP_F_I7),
 1128     IAPDESCR(88H_30H, 0x88, 0x30, IAP_F_FM | IAP_F_I7),
 1129     IAPDESCR(88H_40H, 0x88, 0x40, IAP_F_FM | IAP_F_I7),
 1130     IAPDESCR(89H_01H, 0x89, 0x01, IAP_F_FM | IAP_F_I7),
 1131     IAPDESCR(89H_02H, 0x89, 0x02, IAP_F_FM | IAP_F_I7),
 1132     IAPDESCR(89H_04H, 0x89, 0x04, IAP_F_FM | IAP_F_I7),
 1133     IAPDESCR(89H_07H, 0x89, 0x07, IAP_F_FM | IAP_F_I7),
 1134     IAPDESCR(89H_08H, 0x89, 0x08, IAP_F_FM | IAP_F_I7),
 1135     IAPDESCR(89H_10H, 0x89, 0x10, IAP_F_FM | IAP_F_I7),
 1136     IAPDESCR(89H_20H, 0x89, 0x20, IAP_F_FM | IAP_F_I7),
 1137     IAPDESCR(89H_30H, 0x89, 0x30, IAP_F_FM | IAP_F_I7),
 1138     IAPDESCR(89H_40H, 0x89, 0x40, IAP_F_FM | IAP_F_I7),
 1139     IAPDESCR(89H_7FH, 0x89, 0x7F, IAP_F_FM | IAP_F_I7),
 1140     IAPDESCR(A2H_01H, 0xA2, 0x01, IAP_F_FM | IAP_F_I7),
 1141     IAPDESCR(A2H_02H, 0xA2, 0x02, IAP_F_FM | IAP_F_I7),
 1142     IAPDESCR(A2H_04H, 0xA2, 0x04, IAP_F_FM | IAP_F_I7),
 1143     IAPDESCR(A2H_08H, 0xA2, 0x08, IAP_F_FM | IAP_F_I7),
 1144     IAPDESCR(A2H_10H, 0xA2, 0x10, IAP_F_FM | IAP_F_I7),
 1145     IAPDESCR(A2H_20H, 0xA2, 0x20, IAP_F_FM | IAP_F_I7),
 1146     IAPDESCR(A2H_40H, 0xA2, 0x40, IAP_F_FM | IAP_F_I7),
 1147     IAPDESCR(A2H_80H, 0xA2, 0x80, IAP_F_FM | IAP_F_I7),
 1148     IAPDESCR(A6H_01H, 0xA6, 0x01, IAP_F_FM | IAP_F_I7),
 1149     IAPDESCR(A7H_01H, 0xA7, 0x01, IAP_F_FM | IAP_F_I7),
 1150     IAPDESCR(A8H_01H, 0xA8, 0x01, IAP_F_FM | IAP_F_I7),
 1151     IAPDESCR(B0H_01H, 0xB0, 0x01, IAP_F_FM | IAP_F_I7),
 1152     IAPDESCR(B0H_02H, 0xB0, 0x02, IAP_F_FM | IAP_F_I7),
 1153     IAPDESCR(B0H_04H, 0xB0, 0x04, IAP_F_FM | IAP_F_I7),
 1154     IAPDESCR(B0H_08H, 0xB0, 0x08, IAP_F_FM | IAP_F_I7),
 1155     IAPDESCR(B0H_20H, 0xB0, 0x20, IAP_F_FM | IAP_F_I7),
 1156     IAPDESCR(B0H_40H, 0xB0, 0x40, IAP_F_FM | IAP_F_I7),
 1157     IAPDESCR(B1H_01H, 0xB1, 0x01, IAP_F_FM | IAP_F_I7),
 1158     IAPDESCR(B1H_02H, 0xB1, 0x02, IAP_F_FM | IAP_F_I7),
 1159     IAPDESCR(B1H_04H, 0xB1, 0x04, IAP_F_FM | IAP_F_I7),
 1160     IAPDESCR(B1H_08H, 0xB1, 0x08, IAP_F_FM | IAP_F_I7),
 1161     IAPDESCR(B1H_10H, 0xB1, 0x10, IAP_F_FM | IAP_F_I7),
 1162     IAPDESCR(B1H_20H, 0xB1, 0x20, IAP_F_FM | IAP_F_I7),
 1163     IAPDESCR(B1H_40H, 0xB1, 0x40, IAP_F_FM | IAP_F_I7),
 1164     IAPDESCR(B2H_01H, 0xB2, 0x01, IAP_F_FM | IAP_F_I7),
 1165     IAPDESCR(B7H_01H, 0xB7, 0x01, IAP_F_FM | IAP_F_I7),
 1166     IAPDESCR(B8H_01H, 0xB8, 0x01, IAP_F_FM | IAP_F_I7),
 1167     IAPDESCR(B8H_02H, 0xB8, 0x02, IAP_F_FM | IAP_F_I7),
 1168     IAPDESCR(B8H_04H, 0xB8, 0x04, IAP_F_FM | IAP_F_I7),
 1169     IAPDESCR(BAH_01H, 0xBA, 0x01, IAP_F_FM | IAP_F_I7),
 1170     IAPDESCR(BAH_02H, 0xBA, 0x02, IAP_F_FM | IAP_F_I7),
 1171     IAPDESCR(C3H_02H, 0xC3, 0x02, IAP_F_FM | IAP_F_I7),
 1172     IAPDESCR(C3H_10H, 0xC3, 0x10, IAP_F_FM | IAP_F_I7),
 1173     IAPDESCR(C5H_02H, 0xC5, 0x02, IAP_F_FM | IAP_F_I7),
 1174     IAPDESCR(C8H_20H, 0xC8, 0x20, IAP_F_FM | IAP_F_I7),
 1175     IAPDESCR(CBH_40H, 0xCB, 0x40, IAP_F_FM | IAP_F_I7),
 1176     IAPDESCR(CBH_80H, 0xCB, 0x80, IAP_F_FM | IAP_F_I7),
 1177     IAPDESCR(CCH_03H, 0xCC, 0x03, IAP_F_FM | IAP_F_I7),
 1178     IAPDESCR(D0H_01H, 0xD0, 0x01, IAP_F_FM | IAP_F_I7),
 1179     IAPDESCR(D1H_02H, 0xD1, 0x02, IAP_F_FM | IAP_F_I7),
 1180     IAPDESCR(D1H_04H, 0xD1, 0x04, IAP_F_FM | IAP_F_I7),
 1181     IAPDESCR(D1H_08H, 0xD1, 0x08, IAP_F_FM | IAP_F_I7),
 1182     IAPDESCR(DBH_01H, 0xDB, 0x01, IAP_F_FM | IAP_F_I7),
 1183     IAPDESCR(E4H_01H, 0xE4, 0x01, IAP_F_FM | IAP_F_I7),
 1184     IAPDESCR(E5H_01H, 0xE5, 0x01, IAP_F_FM | IAP_F_I7),
 1185     IAPDESCR(E6H_01H, 0xE6, 0x01, IAP_F_FM | IAP_F_I7),
 1186     IAPDESCR(E6H_02H, 0xE6, 0x02, IAP_F_FM | IAP_F_I7),
 1187     IAPDESCR(E8H_01H, 0xE8, 0x01, IAP_F_FM | IAP_F_I7),
 1188     IAPDESCR(E8H_02H, 0xE8, 0x02, IAP_F_FM | IAP_F_I7),
 1189     IAPDESCR(E8H_03H, 0xE8, 0x03, IAP_F_FM | IAP_F_I7),
 1190     IAPDESCR(F0H_01H, 0xF0, 0x01, IAP_F_FM | IAP_F_I7),
 1191     IAPDESCR(F0H_02H, 0xF0, 0x02, IAP_F_FM | IAP_F_I7),
 1192     IAPDESCR(F0H_04H, 0xF0, 0x04, IAP_F_FM | IAP_F_I7),
 1193     IAPDESCR(F0H_08H, 0xF0, 0x08, IAP_F_FM | IAP_F_I7),
 1194     IAPDESCR(F0H_10H, 0xF0, 0x10, IAP_F_FM | IAP_F_I7),
 1195     IAPDESCR(F0H_20H, 0xF0, 0x20, IAP_F_FM | IAP_F_I7),
 1196     IAPDESCR(F0H_40H, 0xF0, 0x40, IAP_F_FM | IAP_F_I7),
 1197     IAPDESCR(F0H_80H, 0xF0, 0x80, IAP_F_FM | IAP_F_I7),
 1198     IAPDESCR(F1H_02H, 0xF1, 0x02, IAP_F_FM | IAP_F_I7),
 1199     IAPDESCR(F1H_04H, 0xF1, 0x04, IAP_F_FM | IAP_F_I7),
 1200     IAPDESCR(F1H_07H, 0xF1, 0x07, IAP_F_FM | IAP_F_I7),
 1201     IAPDESCR(F2H_01H, 0xF2, 0x01, IAP_F_FM | IAP_F_I7),
 1202     IAPDESCR(F2H_02H, 0xF2, 0x02, IAP_F_FM | IAP_F_I7),
 1203     IAPDESCR(F2H_04H, 0xF2, 0x04, IAP_F_FM | IAP_F_I7),
 1204     IAPDESCR(F2H_08H, 0xF2, 0x08, IAP_F_FM | IAP_F_I7),
 1205     IAPDESCR(F2H_0FH, 0xF2, 0x0F, IAP_F_FM | IAP_F_I7),
 1206     IAPDESCR(F3H_01H, 0xF3, 0x01, IAP_F_FM | IAP_F_I7),
 1207     IAPDESCR(F3H_02H, 0xF3, 0x02, IAP_F_FM | IAP_F_I7),
 1208     IAPDESCR(F3H_04H, 0xF3, 0x04, IAP_F_FM | IAP_F_I7),
 1209     IAPDESCR(F3H_08H, 0xF3, 0x08, IAP_F_FM | IAP_F_I7),
 1210     IAPDESCR(F3H_10H, 0xF3, 0x10, IAP_F_FM | IAP_F_I7),
 1211     IAPDESCR(F3H_20H, 0xF3, 0x20, IAP_F_FM | IAP_F_I7),
 1212     IAPDESCR(F4H_01H, 0xF4, 0x01, IAP_F_FM | IAP_F_I7),
 1213     IAPDESCR(F4H_02H, 0xF4, 0x02, IAP_F_FM | IAP_F_I7),
 1214     IAPDESCR(F4H_04H, 0xF4, 0x04, IAP_F_FM | IAP_F_I7),
 1215     IAPDESCR(F4H_08H, 0xF4, 0x08, IAP_F_FM | IAP_F_I7),
 1216     IAPDESCR(F4H_10H, 0xF4, 0x10, IAP_F_FM | IAP_F_I7),
 1217     IAPDESCR(F6H_01H, 0xF6, 0x01, IAP_F_FM | IAP_F_I7),
 1218     IAPDESCR(F7H_01H, 0xF7, 0x01, IAP_F_FM | IAP_F_I7),
 1219     IAPDESCR(F7H_02H, 0xF7, 0x02, IAP_F_FM | IAP_F_I7),
 1220     IAPDESCR(F7H_04H, 0xF7, 0x04, IAP_F_FM | IAP_F_I7),
 1221     IAPDESCR(F8H_01H, 0xF8, 0x01, IAP_F_FM | IAP_F_I7),
 1222     IAPDESCR(FDH_01H, 0xFD, 0x01, IAP_F_FM | IAP_F_I7),
 1223     IAPDESCR(FDH_02H, 0xFD, 0x02, IAP_F_FM | IAP_F_I7),
 1224     IAPDESCR(FDH_04H, 0xFD, 0x04, IAP_F_FM | IAP_F_I7),
 1225     IAPDESCR(FDH_08H, 0xFD, 0x08, IAP_F_FM | IAP_F_I7),
 1226     IAPDESCR(FDH_10H, 0xFD, 0x10, IAP_F_FM | IAP_F_I7),
 1227     IAPDESCR(FDH_20H, 0xFD, 0x20, IAP_F_FM | IAP_F_I7),
 1228     IAPDESCR(FDH_40H, 0xFD, 0x40, IAP_F_FM | IAP_F_I7),
 1229 };
 1230 
 1231 static const int niap_events = sizeof(iap_events) / sizeof(iap_events[0]);
 1232 
 1233 static pmc_value_t
 1234 iap_perfctr_value_to_reload_count(pmc_value_t v)
 1235 {
 1236         v &= (1ULL << core_iap_width) - 1;
 1237         return (1ULL << core_iap_width) - v;
 1238 }
 1239 
 1240 static pmc_value_t
 1241 iap_reload_count_to_perfctr_value(pmc_value_t rlc)
 1242 {
 1243         return (1ULL << core_iap_width) - rlc;
 1244 }
 1245 
 1246 static int
 1247 iap_pmc_has_overflowed(int ri)
 1248 {
 1249         uint64_t v;
 1250 
 1251         /*
 1252          * We treat a Core (i.e., Intel architecture v1) PMC as has
 1253          * having overflowed if its MSB is zero.
 1254          */
 1255         v = rdpmc(ri);
 1256         return ((v & (1ULL << (core_iap_width - 1))) == 0);
 1257 }
 1258 
 1259 /*
 1260  * Check an event against the set of supported architectural events.
 1261  *
 1262  * Returns 1 if the event is architectural and unsupported on this
 1263  * CPU.  Returns 0 otherwise.
 1264  */
 1265 
 1266 static int
 1267 iap_architectural_event_is_unsupported(enum pmc_event pe)
 1268 {
 1269         enum core_arch_events ae;
 1270 
 1271         switch (pe) {
 1272         case PMC_EV_IAP_EVENT_3CH_00H:
 1273                 ae = CORE_AE_UNHALTED_CORE_CYCLES;
 1274                 break;
 1275         case PMC_EV_IAP_EVENT_C0H_00H:
 1276                 ae = CORE_AE_INSTRUCTION_RETIRED;
 1277                 break;
 1278         case PMC_EV_IAP_EVENT_3CH_01H:
 1279                 ae = CORE_AE_UNHALTED_REFERENCE_CYCLES;
 1280                 break;
 1281         case PMC_EV_IAP_EVENT_2EH_4FH:
 1282                 ae = CORE_AE_LLC_REFERENCE;
 1283                 break;
 1284         case PMC_EV_IAP_EVENT_2EH_41H:
 1285                 ae = CORE_AE_LLC_MISSES;
 1286                 break;
 1287         case PMC_EV_IAP_EVENT_C4H_00H:
 1288                 ae = CORE_AE_BRANCH_INSTRUCTION_RETIRED;
 1289                 break;
 1290         case PMC_EV_IAP_EVENT_C5H_00H:
 1291                 ae = CORE_AE_BRANCH_MISSES_RETIRED;
 1292                 break;
 1293 
 1294         default:        /* Non architectural event. */
 1295                 return (0);
 1296         }
 1297 
 1298         return ((core_architectural_events & (1 << ae)) == 0);
 1299 }
 1300 
 1301 static int
 1302 iap_event_ok_on_counter(enum pmc_event pe, int ri)
 1303 {
 1304         uint32_t mask;
 1305 
 1306         switch (pe) {
 1307                 /*
 1308                  * Events valid only on counter 0.
 1309                  */
 1310         case PMC_EV_IAP_EVENT_10H_00H:
 1311         case PMC_EV_IAP_EVENT_14H_00H:
 1312         case PMC_EV_IAP_EVENT_18H_00H:
 1313         case PMC_EV_IAP_EVENT_C1H_00H:
 1314         case PMC_EV_IAP_EVENT_CBH_01H:
 1315         case PMC_EV_IAP_EVENT_CBH_02H:
 1316                 mask = (1 << 0);
 1317                 break;
 1318 
 1319                 /*
 1320                  * Events valid only on counter 1.
 1321                  */
 1322         case PMC_EV_IAP_EVENT_11H_00H:
 1323         case PMC_EV_IAP_EVENT_12H_00H:
 1324         case PMC_EV_IAP_EVENT_13H_00H:
 1325                 mask = (1 << 1);
 1326                 break;
 1327 
 1328         default:
 1329                 mask = ~0;      /* Any row index is ok. */
 1330         }
 1331 
 1332         return (mask & (1 << ri));
 1333 }
 1334 
 1335 static int
 1336 iap_allocate_pmc(int cpu, int ri, struct pmc *pm,
 1337     const struct pmc_op_pmcallocate *a)
 1338 {
 1339         int n;
 1340         enum pmc_event ev;
 1341         struct iap_event_descr *ie;
 1342         uint32_t c, caps, config, cpuflag, evsel, mask;
 1343 
 1344         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 1345             ("[core,%d] illegal CPU %d", __LINE__, cpu));
 1346         KASSERT(ri >= 0 && ri < core_iap_npmc,
 1347             ("[core,%d] illegal row-index value %d", __LINE__, ri));
 1348 
 1349         /* check requested capabilities */
 1350         caps = a->pm_caps;
 1351         if ((IAP_PMC_CAPS & caps) != caps)
 1352                 return (EPERM);
 1353 
 1354         ev = pm->pm_event;
 1355 
 1356         if (iap_architectural_event_is_unsupported(ev))
 1357                 return (EOPNOTSUPP);
 1358 
 1359         if (iap_event_ok_on_counter(ev, ri) == 0)
 1360                 return (EINVAL);
 1361 
 1362         /*
 1363          * Look for an event descriptor with matching CPU and event id
 1364          * fields.
 1365          */
 1366 
 1367         switch (core_cputype) {
 1368         default:
 1369         case PMC_CPU_INTEL_ATOM:
 1370                 cpuflag = IAP_F_CA;
 1371                 break;
 1372         case PMC_CPU_INTEL_CORE:
 1373                 cpuflag = IAP_F_CC;
 1374                 break;
 1375         case PMC_CPU_INTEL_CORE2:
 1376                 cpuflag = IAP_F_CC2;
 1377                 break;
 1378         case PMC_CPU_INTEL_CORE2EXTREME:
 1379                 cpuflag = IAP_F_CC2 | IAP_F_CC2E;
 1380                 break;
 1381         case PMC_CPU_INTEL_COREI7:
 1382                 cpuflag = IAP_F_I7;
 1383                 break;
 1384         }
 1385 
 1386         for (n = 0, ie = iap_events; n < niap_events; n++, ie++)
 1387                 if (ie->iap_ev == ev && ie->iap_flags & cpuflag)
 1388                         break;
 1389 
 1390         if (n == niap_events)
 1391                 return (EINVAL);
 1392 
 1393         /*
 1394          * A matching event descriptor has been found, so start
 1395          * assembling the contents of the event select register.
 1396          */
 1397         evsel = ie->iap_evcode;
 1398 
 1399         config = a->pm_md.pm_iap.pm_iap_config & ~IAP_F_CMASK;
 1400 
 1401         /*
 1402          * If the event uses a fixed umask value, reject any umask
 1403          * bits set by the user.
 1404          */
 1405         if (ie->iap_flags & IAP_F_FM) {
 1406 
 1407                 if (IAP_UMASK(config) != 0)
 1408                         return (EINVAL);
 1409 
 1410                 evsel |= (ie->iap_umask << 8);
 1411 
 1412         } else {
 1413 
 1414                 /*
 1415                  * Otherwise, the UMASK value needs to be taken from
 1416                  * the MD fields of the allocation request.  Reject
 1417                  * requests that specify reserved bits.
 1418                  */
 1419 
 1420                 mask = 0;
 1421 
 1422                 if (ie->iap_umask & IAP_M_CORE) {
 1423                         if ((c = (config & IAP_F_CORE)) != IAP_CORE_ALL &&
 1424                             c != IAP_CORE_THIS)
 1425                                 return (EINVAL);
 1426                         mask |= IAP_F_CORE;
 1427                 }
 1428 
 1429                 if (ie->iap_umask & IAP_M_AGENT)
 1430                         mask |= IAP_F_AGENT;
 1431 
 1432                 if (ie->iap_umask & IAP_M_PREFETCH) {
 1433 
 1434                         if ((c = (config & IAP_F_PREFETCH)) ==
 1435                             IAP_PREFETCH_RESERVED)
 1436                                 return (EINVAL);
 1437 
 1438                         mask |= IAP_F_PREFETCH;
 1439                 }
 1440 
 1441                 if (ie->iap_umask & IAP_M_MESI)
 1442                         mask |= IAP_F_MESI;
 1443 
 1444                 if (ie->iap_umask & IAP_M_SNOOPRESPONSE)
 1445                         mask |= IAP_F_SNOOPRESPONSE;
 1446 
 1447                 if (ie->iap_umask & IAP_M_SNOOPTYPE)
 1448                         mask |= IAP_F_SNOOPTYPE;
 1449 
 1450                 if (ie->iap_umask & IAP_M_TRANSITION)
 1451                         mask |= IAP_F_TRANSITION;
 1452 
 1453                 /*
 1454                  * If bits outside of the allowed set of umask bits
 1455                  * are set, reject the request.
 1456                  */
 1457                 if (config & ~mask)
 1458                         return (EINVAL);
 1459 
 1460                 evsel |= (config & mask);
 1461 
 1462         }
 1463 
 1464         /*
 1465          * Only Atom CPUs support the 'ANY' qualifier.
 1466          */
 1467         if (core_cputype == PMC_CPU_INTEL_ATOM)
 1468                 evsel |= (config & IAP_ANY);
 1469         else if (config & IAP_ANY)
 1470                 return (EINVAL);
 1471 
 1472         if (caps & PMC_CAP_THRESHOLD)
 1473                 evsel |= (a->pm_md.pm_iap.pm_iap_config & IAP_F_CMASK);
 1474         if (caps & PMC_CAP_USER)
 1475                 evsel |= IAP_USR;
 1476         if (caps & PMC_CAP_SYSTEM)
 1477                 evsel |= IAP_OS;
 1478         if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
 1479                 evsel |= (IAP_OS | IAP_USR);
 1480         if (caps & PMC_CAP_EDGE)
 1481                 evsel |= IAP_EDGE;
 1482         if (caps & PMC_CAP_INVERT)
 1483                 evsel |= IAP_INV;
 1484         if (caps & PMC_CAP_INTERRUPT)
 1485                 evsel |= IAP_INT;
 1486 
 1487         pm->pm_md.pm_iap.pm_iap_evsel = evsel;
 1488 
 1489         return (0);
 1490 }
 1491 
 1492 static int
 1493 iap_config_pmc(int cpu, int ri, struct pmc *pm)
 1494 {
 1495         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 1496             ("[core,%d] illegal CPU %d", __LINE__, cpu));
 1497 
 1498         KASSERT(ri >= 0 && ri < core_iap_npmc,
 1499             ("[core,%d] illegal row-index %d", __LINE__, ri));
 1500 
 1501         PMCDBG(MDP,CFG,1, "iap-config cpu=%d ri=%d pm=%p", cpu, ri, pm);
 1502 
 1503         KASSERT(core_pcpu[cpu] != NULL, ("[core,%d] null per-cpu %d", __LINE__,
 1504             cpu));
 1505 
 1506         core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc = pm;
 1507 
 1508         return (0);
 1509 }
 1510 
 1511 static int
 1512 iap_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
 1513 {
 1514         int error;
 1515         struct pmc_hw *phw;
 1516         char iap_name[PMC_NAME_MAX];
 1517 
 1518         phw = &core_pcpu[cpu]->pc_corepmcs[ri];
 1519 
 1520         (void) snprintf(iap_name, sizeof(iap_name), "IAP-%d", ri);
 1521         if ((error = copystr(iap_name, pi->pm_name, PMC_NAME_MAX,
 1522             NULL)) != 0)
 1523                 return (error);
 1524 
 1525         pi->pm_class = PMC_CLASS_IAP;
 1526 
 1527         if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
 1528                 pi->pm_enabled = TRUE;
 1529                 *ppmc          = phw->phw_pmc;
 1530         } else {
 1531                 pi->pm_enabled = FALSE;
 1532                 *ppmc          = NULL;
 1533         }
 1534 
 1535         return (0);
 1536 }
 1537 
 1538 static int
 1539 iap_get_config(int cpu, int ri, struct pmc **ppm)
 1540 {
 1541         *ppm = core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc;
 1542 
 1543         return (0);
 1544 }
 1545 
 1546 static int
 1547 iap_get_msr(int ri, uint32_t *msr)
 1548 {
 1549         KASSERT(ri >= 0 && ri < core_iap_npmc,
 1550             ("[iap,%d] ri %d out of range", __LINE__, ri));
 1551 
 1552         *msr = ri;
 1553 
 1554         return (0);
 1555 }
 1556 
 1557 static int
 1558 iap_read_pmc(int cpu, int ri, pmc_value_t *v)
 1559 {
 1560         struct pmc *pm;
 1561         pmc_value_t tmp;
 1562 
 1563         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 1564             ("[core,%d] illegal cpu value %d", __LINE__, cpu));
 1565         KASSERT(ri >= 0 && ri < core_iap_npmc,
 1566             ("[core,%d] illegal row-index %d", __LINE__, ri));
 1567 
 1568         pm = core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc;
 1569 
 1570         KASSERT(pm,
 1571             ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu,
 1572                 ri));
 1573 
 1574         tmp = rdpmc(ri);
 1575         if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 1576                 *v = iap_perfctr_value_to_reload_count(tmp);
 1577         else
 1578                 *v = tmp;
 1579 
 1580         PMCDBG(MDP,REA,1, "iap-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
 1581             ri, *v);
 1582 
 1583         return (0);
 1584 }
 1585 
 1586 static int
 1587 iap_release_pmc(int cpu, int ri, struct pmc *pm)
 1588 {
 1589         (void) pm;
 1590 
 1591         PMCDBG(MDP,REL,1, "iap-release cpu=%d ri=%d pm=%p", cpu, ri,
 1592             pm);
 1593 
 1594         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 1595             ("[core,%d] illegal CPU value %d", __LINE__, cpu));
 1596         KASSERT(ri >= 0 && ri < core_iap_npmc,
 1597             ("[core,%d] illegal row-index %d", __LINE__, ri));
 1598 
 1599         KASSERT(core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc
 1600             == NULL, ("[core,%d] PHW pmc non-NULL", __LINE__));
 1601 
 1602         return (0);
 1603 }
 1604 
 1605 static int
 1606 iap_start_pmc(int cpu, int ri)
 1607 {
 1608         struct pmc *pm;
 1609         uint32_t evsel;
 1610         struct core_cpu *cc;
 1611 
 1612         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 1613             ("[core,%d] illegal CPU value %d", __LINE__, cpu));
 1614         KASSERT(ri >= 0 && ri < core_iap_npmc,
 1615             ("[core,%d] illegal row-index %d", __LINE__, ri));
 1616 
 1617         cc = core_pcpu[cpu];
 1618         pm = cc->pc_corepmcs[ri].phw_pmc;
 1619 
 1620         KASSERT(pm,
 1621             ("[core,%d] starting cpu%d,ri%d with no pmc configured",
 1622                 __LINE__, cpu, ri));
 1623 
 1624         PMCDBG(MDP,STA,1, "iap-start cpu=%d ri=%d", cpu, ri);
 1625 
 1626         evsel = pm->pm_md.pm_iap.pm_iap_evsel;
 1627 
 1628         PMCDBG(MDP,STA,2, "iap-start/2 cpu=%d ri=%d evselmsr=0x%x evsel=0x%x",
 1629             cpu, ri, IAP_EVSEL0 + ri, evsel);
 1630 
 1631         wrmsr(IAP_EVSEL0 + ri, evsel | IAP_EN);
 1632 
 1633         if (core_cputype == PMC_CPU_INTEL_CORE)
 1634                 return (0);
 1635 
 1636         do {
 1637                 cc->pc_resync = 0;
 1638                 cc->pc_globalctrl |= (1ULL << ri);
 1639                 wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
 1640         } while (cc->pc_resync != 0);
 1641 
 1642         return (0);
 1643 }
 1644 
 1645 static int
 1646 iap_stop_pmc(int cpu, int ri)
 1647 {
 1648         struct pmc *pm;
 1649         struct core_cpu *cc;
 1650 
 1651         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 1652             ("[core,%d] illegal cpu value %d", __LINE__, cpu));
 1653         KASSERT(ri >= 0 && ri < core_iap_npmc,
 1654             ("[core,%d] illegal row index %d", __LINE__, ri));
 1655 
 1656         cc = core_pcpu[cpu];
 1657         pm = cc->pc_corepmcs[ri].phw_pmc;
 1658 
 1659         KASSERT(pm,
 1660             ("[core,%d] cpu%d ri%d no configured PMC to stop", __LINE__,
 1661                 cpu, ri));
 1662 
 1663         PMCDBG(MDP,STO,1, "iap-stop cpu=%d ri=%d", cpu, ri);
 1664 
 1665         wrmsr(IAP_EVSEL0 + ri, 0);      /* stop hw */
 1666 
 1667         if (core_cputype == PMC_CPU_INTEL_CORE)
 1668                 return (0);
 1669 
 1670         do {
 1671                 cc->pc_resync = 0;
 1672                 cc->pc_globalctrl &= ~(1ULL << ri);
 1673                 wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
 1674         } while (cc->pc_resync != 0);
 1675 
 1676         return (0);
 1677 }
 1678 
 1679 static int
 1680 iap_write_pmc(int cpu, int ri, pmc_value_t v)
 1681 {
 1682         struct pmc *pm;
 1683         struct core_cpu *cc;
 1684 
 1685         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 1686             ("[core,%d] illegal cpu value %d", __LINE__, cpu));
 1687         KASSERT(ri >= 0 && ri < core_iap_npmc,
 1688             ("[core,%d] illegal row index %d", __LINE__, ri));
 1689 
 1690         cc = core_pcpu[cpu];
 1691         pm = cc->pc_corepmcs[ri].phw_pmc;
 1692 
 1693         KASSERT(pm,
 1694             ("[core,%d] cpu%d ri%d no configured PMC to stop", __LINE__,
 1695                 cpu, ri));
 1696 
 1697         PMCDBG(MDP,WRI,1, "iap-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri,
 1698             IAP_PMC0 + ri, v);
 1699 
 1700         if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 1701                 v = iap_reload_count_to_perfctr_value(v);
 1702 
 1703         /*
 1704          * Write the new value to the counter.  The counter will be in
 1705          * a stopped state when the pcd_write() entry point is called.
 1706          */
 1707 
 1708         wrmsr(IAP_PMC0 + ri, v);
 1709 
 1710         return (0);
 1711 }
 1712 
 1713 
 1714 static void
 1715 iap_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth,
 1716     int flags)
 1717 {
 1718         struct pmc_classdep *pcd;
 1719 
 1720         KASSERT(md != NULL, ("[iap,%d] md is NULL", __LINE__));
 1721 
 1722         PMCDBG(MDP,INI,1, "%s", "iap-initialize");
 1723 
 1724         /* Remember the set of architectural events supported. */
 1725         core_architectural_events = ~flags;
 1726 
 1727         pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP];
 1728 
 1729         pcd->pcd_caps   = IAP_PMC_CAPS;
 1730         pcd->pcd_class  = PMC_CLASS_IAP;
 1731         pcd->pcd_num    = npmc;
 1732         pcd->pcd_ri     = md->pmd_npmc;
 1733         pcd->pcd_width  = pmcwidth;
 1734 
 1735         pcd->pcd_allocate_pmc   = iap_allocate_pmc;
 1736         pcd->pcd_config_pmc     = iap_config_pmc;
 1737         pcd->pcd_describe       = iap_describe;
 1738         pcd->pcd_get_config     = iap_get_config;
 1739         pcd->pcd_get_msr        = iap_get_msr;
 1740         pcd->pcd_pcpu_fini      = core_pcpu_fini;
 1741         pcd->pcd_pcpu_init      = core_pcpu_init;
 1742         pcd->pcd_read_pmc       = iap_read_pmc;
 1743         pcd->pcd_release_pmc    = iap_release_pmc;
 1744         pcd->pcd_start_pmc      = iap_start_pmc;
 1745         pcd->pcd_stop_pmc       = iap_stop_pmc;
 1746         pcd->pcd_write_pmc      = iap_write_pmc;
 1747 
 1748         md->pmd_npmc           += npmc;
 1749 }
 1750 
 1751 static int
 1752 core_intr(int cpu, struct trapframe *tf)
 1753 {
 1754         pmc_value_t v;
 1755         struct pmc *pm;
 1756         struct core_cpu *cc;
 1757         int error, found_interrupt, ri;
 1758 
 1759         PMCDBG(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf,
 1760             TRAPF_USERMODE(tf));
 1761 
 1762         found_interrupt = 0;
 1763         cc = core_pcpu[cpu];
 1764 
 1765         for (ri = 0; ri < core_iap_npmc; ri++) {
 1766 
 1767                 if ((pm = cc->pc_corepmcs[ri].phw_pmc) == NULL ||
 1768                     !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 1769                         continue;
 1770 
 1771                 if (!iap_pmc_has_overflowed(ri))
 1772                         continue;
 1773 
 1774                 found_interrupt = 1;
 1775 
 1776                 if (pm->pm_state != PMC_STATE_RUNNING)
 1777                         continue;
 1778 
 1779                 error = pmc_process_interrupt(cpu, pm, tf,
 1780                     TRAPF_USERMODE(tf));
 1781 
 1782                 v = pm->pm_sc.pm_reloadcount;
 1783                 v = iaf_reload_count_to_perfctr_value(v);
 1784 
 1785                 /*
 1786                  * Stop the counter, reload it but only restart it if
 1787                  * the PMC is not stalled.
 1788                  */
 1789                 wrmsr(IAP_EVSEL0 + ri, 0);
 1790                 wrmsr(IAP_PMC0 + ri, v);
 1791 
 1792                 if (error)
 1793                         continue;
 1794 
 1795                 wrmsr(IAP_EVSEL0 + ri,
 1796                     pm->pm_md.pm_iap.pm_iap_evsel | IAP_EN);
 1797         }
 1798 
 1799         if (found_interrupt)
 1800                 lapic_reenable_pmc();
 1801 
 1802         atomic_add_int(found_interrupt ? &pmc_stats.pm_intr_processed :
 1803             &pmc_stats.pm_intr_ignored, 1);
 1804 
 1805         return (found_interrupt);
 1806 }
 1807 
 1808 static int
 1809 core2_intr(int cpu, struct trapframe *tf)
 1810 {
 1811         int error, found_interrupt, n;
 1812         uint64_t flag, intrstatus, intrenable;
 1813         struct pmc *pm;
 1814         struct core_cpu *cc;
 1815         pmc_value_t v;
 1816 
 1817         PMCDBG(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf,
 1818             TRAPF_USERMODE(tf));
 1819 
 1820         /*
 1821          * The IA_GLOBAL_STATUS (MSR 0x38E) register indicates which
 1822          * PMCs have a pending PMI interrupt.  We take a 'snapshot' of
 1823          * the current set of interrupting PMCs and process these
 1824          * after stopping them.
 1825          */
 1826         intrstatus = rdmsr(IA_GLOBAL_STATUS);
 1827         intrenable = intrstatus & core_pmcmask;
 1828 
 1829         PMCDBG(MDP,INT, 1, "cpu=%d intrstatus=%jx", cpu,
 1830             (uintmax_t) intrstatus);
 1831 
 1832         found_interrupt = 0;
 1833         cc = core_pcpu[cpu];
 1834 
 1835         KASSERT(cc != NULL, ("[core,%d] null pcpu", __LINE__));
 1836 
 1837         cc->pc_globalctrl &= ~intrenable;
 1838         cc->pc_resync = 1;      /* MSRs now potentially out of sync. */
 1839 
 1840         /*
 1841          * Stop PMCs and clear overflow status bits.
 1842          */
 1843         wrmsr(IA_GLOBAL_CTRL, 0);
 1844         wrmsr(IA_GLOBAL_OVF_CTRL, intrenable |
 1845             IA_GLOBAL_STATUS_FLAG_OVFBUF |
 1846             IA_GLOBAL_STATUS_FLAG_CONDCHG);
 1847 
 1848         /*
 1849          * Look for interrupts from fixed function PMCs.
 1850          */
 1851         for (n = 0, flag = (1ULL << IAF_OFFSET); n < core_iaf_npmc;
 1852              n++, flag <<= 1) {
 1853 
 1854                 if ((intrstatus & flag) == 0)
 1855                         continue;
 1856 
 1857                 found_interrupt = 1;
 1858 
 1859                 pm = cc->pc_corepmcs[n + core_iaf_ri].phw_pmc;
 1860                 if (pm == NULL || pm->pm_state != PMC_STATE_RUNNING ||
 1861                     !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 1862                         continue;
 1863 
 1864                 error = pmc_process_interrupt(cpu, pm, tf,
 1865                     TRAPF_USERMODE(tf));
 1866 
 1867                 v = iaf_reload_count_to_perfctr_value(pm->pm_sc.pm_reloadcount);
 1868 
 1869                 /* Reload sampling count. */
 1870                 wrmsr(IAF_CTR0 + n, v);
 1871 
 1872                 PMCDBG(MDP,INT, 1, "iaf-intr cpu=%d error=%d v=%jx(%jx)", cpu, error,
 1873                     (uintmax_t) v, (uintmax_t) rdpmc(IAF_RI_TO_MSR(n)));
 1874 
 1875                 if (error)
 1876                         intrenable &= ~flag;
 1877         }
 1878 
 1879         /*
 1880          * Process interrupts from the programmable counters.
 1881          */
 1882         for (n = 0, flag = 1; n < core_iap_npmc; n++, flag <<= 1) {
 1883                 if ((intrstatus & flag) == 0)
 1884                         continue;
 1885 
 1886                 found_interrupt = 1;
 1887 
 1888                 pm = cc->pc_corepmcs[n].phw_pmc;
 1889                 if (pm == NULL || pm->pm_state != PMC_STATE_RUNNING ||
 1890                     !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 1891                         continue;
 1892 
 1893                 error = pmc_process_interrupt(cpu, pm, tf,
 1894                     TRAPF_USERMODE(tf));
 1895                 if (error)
 1896                         intrenable &= ~flag;
 1897 
 1898                 v = iap_reload_count_to_perfctr_value(pm->pm_sc.pm_reloadcount);
 1899 
 1900                 PMCDBG(MDP,INT, 1, "iap-intr cpu=%d error=%d v=%jx", cpu, error,
 1901                     (uintmax_t) v);
 1902 
 1903                 /* Reload sampling count. */
 1904                 wrmsr(IAP_PMC0 + n, v);
 1905         }
 1906 
 1907         /*
 1908          * Reenable all non-stalled PMCs.
 1909          */
 1910         PMCDBG(MDP,INT, 1, "cpu=%d intrenable=%jx", cpu,
 1911             (uintmax_t) intrenable);
 1912 
 1913         cc->pc_globalctrl |= intrenable;
 1914 
 1915         wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
 1916 
 1917         PMCDBG(MDP,INT, 1, "cpu=%d fixedctrl=%jx globalctrl=%jx status=%jx "
 1918             "ovf=%jx", cpu, (uintmax_t) rdmsr(IAF_CTRL),
 1919             (uintmax_t) rdmsr(IA_GLOBAL_CTRL),
 1920             (uintmax_t) rdmsr(IA_GLOBAL_STATUS),
 1921             (uintmax_t) rdmsr(IA_GLOBAL_OVF_CTRL));
 1922 
 1923         if (found_interrupt)
 1924                 lapic_reenable_pmc();
 1925 
 1926         atomic_add_int(found_interrupt ? &pmc_stats.pm_intr_processed :
 1927             &pmc_stats.pm_intr_ignored, 1);
 1928 
 1929         return (found_interrupt);
 1930 }
 1931 
 1932 int
 1933 pmc_core_initialize(struct pmc_mdep *md, int maxcpu)
 1934 {
 1935         int cpuid[CORE_CPUID_REQUEST_SIZE];
 1936         int ipa_version, flags, nflags;
 1937 
 1938         do_cpuid(CORE_CPUID_REQUEST, cpuid);
 1939 
 1940         ipa_version = cpuid[CORE_CPUID_EAX] & 0xFF;
 1941 
 1942         PMCDBG(MDP,INI,1,"core-init cputype=%d ncpu=%d ipa-version=%d",
 1943             md->pmd_cputype, maxcpu, ipa_version);
 1944 
 1945         if (ipa_version < 1 || ipa_version > 3) /* Unknown PMC architecture. */
 1946                 return (EPROGMISMATCH);
 1947 
 1948         core_cputype = md->pmd_cputype;
 1949 
 1950         core_pmcmask = 0;
 1951 
 1952         /*
 1953          * Initialize programmable counters.
 1954          */
 1955         KASSERT(ipa_version >= 1,
 1956             ("[core,%d] ipa_version %d too small", __LINE__, ipa_version));
 1957 
 1958         core_iap_npmc = (cpuid[CORE_CPUID_EAX] >> 8) & 0xFF;
 1959         core_iap_width = (cpuid[CORE_CPUID_EAX] >> 16) & 0xFF;
 1960 
 1961         core_pmcmask |= ((1ULL << core_iap_npmc) - 1);
 1962 
 1963         nflags = (cpuid[CORE_CPUID_EAX] >> 24) & 0xFF;
 1964         flags = cpuid[CORE_CPUID_EBX] & ((1 << nflags) - 1);
 1965 
 1966         iap_initialize(md, maxcpu, core_iap_npmc, core_iap_width, flags);
 1967 
 1968         /*
 1969          * Initialize fixed function counters, if present.
 1970          */
 1971         if (core_cputype != PMC_CPU_INTEL_CORE) {
 1972                 KASSERT(ipa_version >= 2,
 1973                     ("[core,%d] ipa_version %d too small", __LINE__,
 1974                         ipa_version));
 1975 
 1976                 core_iaf_ri = core_iap_npmc;
 1977                 core_iaf_npmc = cpuid[CORE_CPUID_EDX] & 0x1F;
 1978                 core_iaf_width = (cpuid[CORE_CPUID_EDX] >> 5) & 0xFF;
 1979 
 1980                 if (core_iaf_npmc > 0) {
 1981                         iaf_initialize(md, maxcpu, core_iaf_npmc,
 1982                             core_iaf_width);
 1983                         core_pmcmask |= ((1ULL << core_iaf_npmc) - 1) <<
 1984                             IAF_OFFSET;
 1985                 } else {
 1986                         /*
 1987                          * Adjust the number of classes exported to
 1988                          * user space.
 1989                          */
 1990                         md->pmd_nclass--;
 1991                         KASSERT(md->pmd_nclass == 2,
 1992                             ("[core,%d] unexpected nclass %d", __LINE__,
 1993                                 md->pmd_nclass));
 1994                 }
 1995         }
 1996 
 1997         PMCDBG(MDP,INI,1,"core-init pmcmask=0x%jx iafri=%d", core_pmcmask,
 1998             core_iaf_ri);
 1999 
 2000         core_pcpu = malloc(sizeof(struct core_cpu **) * maxcpu, M_PMC,
 2001             M_ZERO | M_WAITOK);
 2002 
 2003         /*
 2004          * Choose the appropriate interrupt handler.
 2005          */
 2006         if (ipa_version == 1)
 2007                 md->pmd_intr = core_intr;
 2008         else
 2009                 md->pmd_intr = core2_intr;
 2010 
 2011         md->pmd_pcpu_fini = NULL;
 2012         md->pmd_pcpu_init = NULL;
 2013 
 2014         return (0);
 2015 }
 2016 
 2017 void
 2018 pmc_core_finalize(struct pmc_mdep *md)
 2019 {
 2020         PMCDBG(MDP,INI,1, "%s", "core-finalize");
 2021 
 2022         free(core_pcpu, M_PMC);
 2023         core_pcpu = NULL;
 2024 }

Cache object: 0916b4e4dd25caf0a889e2c309a15574


[ 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.