aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/hwpmc
diff options
context:
space:
mode:
authorFabien Thomas <fabient@FreeBSD.org>2009-06-07 10:00:35 +0000
committerFabien Thomas <fabient@FreeBSD.org>2009-06-07 10:00:35 +0000
commit0daa13da2cc92fe2e572359be36c097dbfb15cd5 (patch)
tree7a525335db9e18d2198a022a0ba8f51b5dbf3bed /sys/dev/hwpmc
parentae96b43bc16761abca4920adc31f3c6e61e99619 (diff)
Notes
Diffstat (limited to 'sys/dev/hwpmc')
-rw-r--r--sys/dev/hwpmc/hwpmc_amd.c425
-rw-r--r--sys/dev/hwpmc/hwpmc_amd.h8
-rw-r--r--sys/dev/hwpmc/hwpmc_arm.c26
-rw-r--r--sys/dev/hwpmc/hwpmc_core.c1988
-rw-r--r--sys/dev/hwpmc/hwpmc_core.h121
-rw-r--r--sys/dev/hwpmc/hwpmc_ia64.c26
-rw-r--r--sys/dev/hwpmc/hwpmc_intel.c269
-rw-r--r--sys/dev/hwpmc/hwpmc_logging.c137
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c827
-rw-r--r--sys/dev/hwpmc/hwpmc_pentium.c10
-rw-r--r--sys/dev/hwpmc/hwpmc_pentium.h5
-rw-r--r--sys/dev/hwpmc/hwpmc_piv.c539
-rw-r--r--sys/dev/hwpmc/hwpmc_piv.h7
-rw-r--r--sys/dev/hwpmc/hwpmc_powerpc.c26
-rw-r--r--sys/dev/hwpmc/hwpmc_ppro.c409
-rw-r--r--sys/dev/hwpmc/hwpmc_ppro.h5
-rw-r--r--sys/dev/hwpmc/hwpmc_sparc64.c26
-rw-r--r--sys/dev/hwpmc/hwpmc_tsc.c388
-rw-r--r--sys/dev/hwpmc/hwpmc_tsc.h43
-rw-r--r--sys/dev/hwpmc/hwpmc_x86.c264
-rw-r--r--sys/dev/hwpmc/pmc_events.h2325
21 files changed, 6305 insertions, 1569 deletions
diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c
index b7cdee808ceb..268904b6f349 100644
--- a/sys/dev/hwpmc/hwpmc_amd.c
+++ b/sys/dev/hwpmc/hwpmc_amd.c
@@ -1,7 +1,11 @@
/*-
- * Copyright (c) 2003-2005 Joseph Koshy
+ * Copyright (c) 2003-2008 Joseph Koshy
+ * Copyright (c) 2007 The FreeBSD Foundation
* All rights reserved.
*
+ * Portions of this software were developed by A. Joseph Koshy under
+ * sponsorship from the FreeBSD Foundation and Google, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -22,7 +26,6 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
*/
#include <sys/cdefs.h>
@@ -35,12 +38,13 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/pmc.h>
+#include <sys/pmckern.h>
#include <sys/smp.h>
#include <sys/systm.h>
+#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/md_var.h>
-#include <machine/pmc_mdep.h>
#include <machine/specialreg.h>
#ifdef DEBUG
@@ -59,18 +63,6 @@ static struct amd_descr amd_pmcdesc[AMD_NPMCS] =
{
.pm_descr =
{
- .pd_name = "TSC",
- .pd_class = PMC_CLASS_TSC,
- .pd_caps = PMC_CAP_READ,
- .pd_width = 64
- },
- .pm_evsel = MSR_TSC,
- .pm_perfctr = 0 /* unused */
- },
-
- {
- .pm_descr =
- {
.pd_name = "",
.pd_class = -1,
.pd_caps = AMD_PMC_CAPS,
@@ -253,6 +245,16 @@ const int amd_event_codes_size =
sizeof(amd_event_codes) / sizeof(amd_event_codes[0]);
/*
+ * Per-processor information
+ */
+
+struct amd_cpu {
+ struct pmc_hw pc_amdpmcs[AMD_NPMCS];
+};
+
+static struct amd_cpu **amd_pcpu;
+
+/*
* read a pmc register
*/
@@ -262,17 +264,17 @@ amd_read_pmc(int cpu, int ri, pmc_value_t *v)
enum pmc_mode mode;
const struct amd_descr *pd;
struct pmc *pm;
- const struct pmc_hw *phw;
pmc_value_t tmp;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[amd,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < AMD_NPMCS,
("[amd,%d] illegal row-index %d", __LINE__, ri));
+ KASSERT(amd_pcpu[cpu],
+ ("[amd,%d] null per-cpu, cpu %d", __LINE__, cpu));
- phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
- pd = &amd_pmcdesc[ri];
- pm = phw->phw_pmc;
+ pm = amd_pcpu[cpu]->pc_amdpmcs[ri].phw_pmc;
+ pd = &amd_pmcdesc[ri];
KASSERT(pm != NULL,
("[amd,%d] No owner for HWPMC [cpu%d,pmc%d]", __LINE__,
@@ -282,15 +284,6 @@ amd_read_pmc(int cpu, int ri, pmc_value_t *v)
PMCDBG(MDP,REA,1,"amd-read id=%d class=%d", ri, pd->pm_descr.pd_class);
- /* Reading the TSC is a special case */
- if (pd->pm_descr.pd_class == PMC_CLASS_TSC) {
- KASSERT(PMC_IS_COUNTING_MODE(mode),
- ("[amd,%d] TSC counter in non-counting mode", __LINE__));
- *v = rdtsc();
- PMCDBG(MDP,REA,2,"amd-read id=%d -> %jd", ri, *v);
- return 0;
- }
-
#ifdef DEBUG
KASSERT(pd->pm_descr.pd_class == amd_pmc_class,
("[amd,%d] unknown PMC class (%d)", __LINE__,
@@ -298,12 +291,15 @@ amd_read_pmc(int cpu, int ri, pmc_value_t *v)
#endif
tmp = rdmsr(pd->pm_perfctr); /* RDMSR serializes */
- if (PMC_IS_SAMPLING_MODE(mode))
- *v = AMD_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp);
- else
- *v = tmp;
+ PMCDBG(MDP,REA,2,"amd-read (pre-munge) id=%d -> %jd", ri, tmp);
+ if (PMC_IS_SAMPLING_MODE(mode)) {
+ /* Sign extend 48 bit value to 64 bits. */
+ tmp = (pmc_value_t) (((int64_t) tmp << 16) >> 16);
+ tmp = AMD_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp);
+ }
+ *v = tmp;
- PMCDBG(MDP,REA,2,"amd-read id=%d -> %jd", ri, *v);
+ PMCDBG(MDP,REA,2,"amd-read (post-munge) id=%d -> %jd", ri, *v);
return 0;
}
@@ -316,18 +312,16 @@ static int
amd_write_pmc(int cpu, int ri, pmc_value_t v)
{
const struct amd_descr *pd;
- struct pmc *pm;
- const struct pmc_hw *phw;
enum pmc_mode mode;
+ struct pmc *pm;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[amd,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < AMD_NPMCS,
("[amd,%d] illegal row-index %d", __LINE__, ri));
- phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
- pd = &amd_pmcdesc[ri];
- pm = phw->phw_pmc;
+ pm = amd_pcpu[cpu]->pc_amdpmcs[ri].phw_pmc;
+ pd = &amd_pmcdesc[ri];
KASSERT(pm != NULL,
("[amd,%d] PMC not owned (cpu%d,pmc%d)", __LINE__,
@@ -335,9 +329,6 @@ amd_write_pmc(int cpu, int ri, pmc_value_t v)
mode = PMC_TO_MODE(pm);
- if (pd->pm_descr.pd_class == PMC_CLASS_TSC)
- return 0;
-
#ifdef DEBUG
KASSERT(pd->pm_descr.pd_class == amd_pmc_class,
("[amd,%d] unknown PMC class (%d)", __LINE__,
@@ -367,12 +358,12 @@ amd_config_pmc(int cpu, int ri, struct pmc *pm)
PMCDBG(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm);
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[amd,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < AMD_NPMCS,
("[amd,%d] illegal row-index %d", __LINE__, ri));
- phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
+ phw = &amd_pcpu[cpu]->pc_amdpmcs[ri];
KASSERT(pm == NULL || phw->phw_pmc == NULL,
("[amd,%d] pm=%p phw->pm=%p hwpmc not unconfigured",
@@ -389,7 +380,7 @@ amd_config_pmc(int cpu, int ri, struct pmc *pm)
static int
amd_get_config(int cpu, int ri, struct pmc **ppm)
{
- *ppm = pmc_pcpu[cpu]->pc_hwpmcs[ri]->phw_pmc;
+ *ppm = amd_pcpu[cpu]->pc_amdpmcs[ri].phw_pmc;
return 0;
}
@@ -449,7 +440,7 @@ amd_allocate_pmc(int cpu, int ri, struct pmc *pm,
(void) cpu;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[amd,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < AMD_NPMCS,
("[amd,%d] illegal row index %d", __LINE__, ri));
@@ -466,18 +457,6 @@ amd_allocate_pmc(int cpu, int ri, struct pmc *pm,
if ((pd->pd_caps & caps) != caps)
return EPERM;
- if (pd->pd_class == PMC_CLASS_TSC) {
- /* TSC's are always allocated in system-wide counting mode */
- if (a->pm_ev != PMC_EV_TSC_TSC ||
- a->pm_mode != PMC_MODE_SC)
- return EINVAL;
- return 0;
- }
-
-#ifdef DEBUG
- KASSERT(pd->pd_class == amd_pmc_class,
- ("[amd,%d] Unknown PMC class (%d)", __LINE__, pd->pd_class));
-#endif
pe = a->pm_ev;
@@ -543,12 +522,12 @@ amd_release_pmc(int cpu, int ri, struct pmc *pmc)
(void) pmc;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[amd,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < AMD_NPMCS,
("[amd,%d] illegal row-index %d", __LINE__, ri));
- phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
+ phw = &amd_pcpu[cpu]->pc_amdpmcs[ri];
KASSERT(phw->phw_pmc == NULL,
("[amd,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc));
@@ -575,12 +554,12 @@ amd_start_pmc(int cpu, int ri)
struct pmc_hw *phw;
const struct amd_descr *pd;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[amd,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < AMD_NPMCS,
("[amd,%d] illegal row-index %d", __LINE__, ri));
- phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
+ phw = &amd_pcpu[cpu]->pc_amdpmcs[ri];
pm = phw->phw_pmc;
pd = &amd_pmcdesc[ri];
@@ -590,15 +569,6 @@ amd_start_pmc(int cpu, int ri)
PMCDBG(MDP,STA,1,"amd-start cpu=%d ri=%d", cpu, ri);
- if (pd->pm_descr.pd_class == PMC_CLASS_TSC)
- return 0; /* TSCs are always running */
-
-#ifdef DEBUG
- KASSERT(pd->pm_descr.pd_class == amd_pmc_class,
- ("[amd,%d] unknown PMC class (%d)", __LINE__,
- pd->pm_descr.pd_class));
-#endif
-
KASSERT(AMD_PMC_IS_STOPPED(pd->pm_evsel),
("[amd,%d] pmc%d,cpu%d: Starting active PMC \"%s\"", __LINE__,
ri, cpu, pd->pm_descr.pd_name));
@@ -624,29 +594,18 @@ amd_stop_pmc(int cpu, int ri)
const struct amd_descr *pd;
uint64_t config;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[amd,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < AMD_NPMCS,
("[amd,%d] illegal row-index %d", __LINE__, ri));
- phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
+ phw = &amd_pcpu[cpu]->pc_amdpmcs[ri];
pm = phw->phw_pmc;
pd = &amd_pmcdesc[ri];
KASSERT(pm != NULL,
("[amd,%d] cpu%d,pmc%d no PMC to stop", __LINE__,
cpu, ri));
-
- /* can't stop a TSC */
- if (pd->pm_descr.pd_class == PMC_CLASS_TSC)
- return 0;
-
-#ifdef DEBUG
- KASSERT(pd->pm_descr.pd_class == amd_pmc_class,
- ("[amd,%d] unknown PMC class (%d)", __LINE__,
- pd->pm_descr.pd_class));
-#endif
-
KASSERT(!AMD_PMC_IS_STOPPED(pd->pm_evsel),
("[amd,%d] PMC%d, CPU%d \"%s\" already stopped",
__LINE__, ri, cpu, pd->pm_descr.pd_name));
@@ -667,28 +626,26 @@ amd_stop_pmc(int cpu, int ri)
*/
static int
-amd_intr(int cpu, uintptr_t eip, int usermode)
+amd_intr(int cpu, struct trapframe *tf)
{
- int i, error, retval, ri;
+ int i, error, retval;
uint32_t config, evsel, perfctr;
struct pmc *pm;
- struct pmc_cpu *pc;
- struct pmc_hw *phw;
+ struct amd_cpu *pac;
pmc_value_t v;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[amd,%d] out of range CPU %d", __LINE__, cpu));
- PMCDBG(MDP,INT,1, "cpu=%d eip=%p um=%d", cpu, (void *) eip,
- usermode);
+ PMCDBG(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf,
+ TRAPF_USERMODE(tf));
retval = 0;
- pc = pmc_pcpu[cpu];
+ pac = amd_pcpu[cpu];
/*
* look for all PMCs that have interrupted:
- * - skip over the TSC [PMC#0]
* - look for a running, sampling PMC which has overflowed
* and which has a valid 'struct pmc' association
*
@@ -696,30 +653,26 @@ amd_intr(int cpu, uintptr_t eip, int usermode)
*
* If multiple PMCs interrupt at the same time, the AMD64
* processor appears to deliver as many NMIs as there are
- * outstanding PMC interrupts. Thus we need to only process
- * one interrupt at a time.
+ * outstanding PMC interrupts. So we process only one NMI
+ * interrupt at a time.
*/
- for (i = 0; retval == 0 && i < AMD_NPMCS-1; i++) {
+ for (i = 0; retval == 0 && i < AMD_NPMCS; i++) {
- ri = i + 1; /* row index; TSC is at ri == 0 */
+ if ((pm = pac->pc_amdpmcs[i].phw_pmc) == NULL ||
+ !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) {
+ continue;
+ }
if (!AMD_PMC_HAS_OVERFLOWED(i))
continue;
- phw = pc->pc_hwpmcs[ri];
-
- KASSERT(phw != NULL, ("[amd,%d] null PHW pointer", __LINE__));
+ retval = 1; /* Found an interrupting PMC. */
- if ((pm = phw->phw_pmc) == NULL ||
- pm->pm_state != PMC_STATE_RUNNING ||
- !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) {
+ if (pm->pm_state != PMC_STATE_RUNNING)
continue;
- }
- retval = 1; /* found an interrupting PMC */
-
- /* stop the PMC, reload count */
+ /* Stop the PMC, reload count. */
evsel = AMD_PMC_EVSEL_0 + i;
perfctr = AMD_PMC_PERFCTR_0 + i;
v = pm->pm_sc.pm_reloadcount;
@@ -733,8 +686,8 @@ amd_intr(int cpu, uintptr_t eip, int usermode)
wrmsr(evsel, config & ~AMD_PMC_ENABLE);
wrmsr(perfctr, AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(v));
- /* restart the counter if there was no error during logging */
- error = pmc_process_interrupt(cpu, pm, eip, usermode);
+ /* Restart the counter if logging succeeded. */
+ error = pmc_process_interrupt(cpu, pm, tf, TRAPF_USERMODE(tf));
if (error == 0)
wrmsr(evsel, config | AMD_PMC_ENABLE);
}
@@ -742,7 +695,7 @@ amd_intr(int cpu, uintptr_t eip, int usermode)
atomic_add_int(retval ? &pmc_stats.pm_intr_processed :
&pmc_stats.pm_intr_ignored, 1);
- return retval;
+ return (retval);
}
/*
@@ -756,12 +709,12 @@ amd_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
const struct amd_descr *pd;
struct pmc_hw *phw;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[amd,%d] illegal CPU %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < AMD_NPMCS,
("[amd,%d] row-index %d out of range", __LINE__, ri));
- phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
+ phw = &amd_pcpu[cpu]->pc_amdpmcs[ri];
pd = &amd_pmcdesc[ri];
if ((error = copystr(pd->pm_descr.pd_name, pi->pm_name,
@@ -796,63 +749,53 @@ amd_get_msr(int ri, uint32_t *msr)
("[amd,%d] ri %d out of range", __LINE__, ri));
*msr = amd_pmcdesc[ri].pm_perfctr - AMD_PMC_PERFCTR_0;
- return 0;
+
+ return (0);
}
/*
* processor dependent initialization.
*/
-/*
- * Per-processor data structure
- *
- * [common stuff]
- * [5 struct pmc_hw pointers]
- * [5 struct pmc_hw structures]
- */
-
-struct amd_cpu {
- struct pmc_cpu pc_common;
- struct pmc_hw *pc_hwpmcs[AMD_NPMCS];
- struct pmc_hw pc_amdpmcs[AMD_NPMCS];
-};
-
-
static int
-amd_init(int cpu)
+amd_pcpu_init(struct pmc_mdep *md, int cpu)
{
- int n;
- struct amd_cpu *pcs;
+ int classindex, first_ri, n;
+ struct pmc_cpu *pc;
+ struct amd_cpu *pac;
struct pmc_hw *phw;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[amd,%d] insane cpu number %d", __LINE__, cpu));
PMCDBG(MDP,INI,1,"amd-init cpu=%d", cpu);
- MALLOC(pcs, struct amd_cpu *, sizeof(struct amd_cpu), M_PMC,
+ amd_pcpu[cpu] = pac = malloc(sizeof(struct amd_cpu), M_PMC,
M_WAITOK|M_ZERO);
- phw = &pcs->pc_amdpmcs[0];
-
/*
- * Initialize the per-cpu mutex and set the content of the
- * hardware descriptors to a known state.
+ * Set the content of the hardware descriptors to a known
+ * state and initialize pointers in the MI per-cpu descriptor.
*/
+ pc = pmc_pcpu[cpu];
+#if defined(__amd64__)
+ classindex = PMC_MDEP_CLASS_INDEX_K8;
+#elif defined(__i386__)
+ classindex = md->pmd_cputype == PMC_CPU_AMD_K8 ?
+ PMC_MDEP_CLASS_INDEX_K8 : PMC_MDEP_CLASS_INDEX_K7;
+#endif
+ first_ri = md->pmd_classdep[classindex].pcd_ri;
+
+ KASSERT(pc != NULL, ("[amd,%d] NULL per-cpu pointer", __LINE__));
- for (n = 0; n < AMD_NPMCS; n++, phw++) {
+ for (n = 0, phw = pac->pc_amdpmcs; n < AMD_NPMCS; n++, phw++) {
phw->phw_state = PMC_PHW_FLAG_IS_ENABLED |
PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(n);
phw->phw_pmc = NULL;
- pcs->pc_hwpmcs[n] = phw;
+ pc->pc_hwpmcs[n + first_ri] = phw;
}
- /* Mark the TSC as shareable */
- pcs->pc_hwpmcs[0]->phw_state |= PMC_PHW_FLAG_IS_SHAREABLE;
-
- pmc_pcpu[cpu] = (struct pmc_cpu *) pcs;
-
- return 0;
+ return (0);
}
@@ -862,13 +805,14 @@ amd_init(int cpu)
*/
static int
-amd_cleanup(int cpu)
+amd_pcpu_fini(struct pmc_mdep *md, int cpu)
{
- int i;
+ int classindex, first_ri, i;
uint32_t evsel;
- struct pmc_cpu *pcs;
+ struct pmc_cpu *pc;
+ struct amd_cpu *pac;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[amd,%d] insane cpu number (%d)", __LINE__, cpu));
PMCDBG(MDP,INI,1,"amd-cleanup cpu=%d", cpu);
@@ -876,7 +820,6 @@ amd_cleanup(int cpu)
/*
* First, turn off all PMCs on this CPU.
*/
-
for (i = 0; i < 4; i++) { /* XXX this loop is now not needed */
evsel = rdmsr(AMD_PMC_EVSEL_0 + i);
evsel &= ~AMD_PMC_ENABLE;
@@ -886,25 +829,42 @@ amd_cleanup(int cpu)
/*
* Next, free up allocated space.
*/
+ if ((pac = amd_pcpu[cpu]) == NULL)
+ return (0);
- if ((pcs = pmc_pcpu[cpu]) == NULL)
- return 0;
+ amd_pcpu[cpu] = NULL;
#ifdef DEBUG
- /* check the TSC */
- KASSERT(pcs->pc_hwpmcs[0]->phw_pmc == NULL,
- ("[amd,%d] CPU%d,PMC0 still in use", __LINE__, cpu));
- for (i = 1; i < AMD_NPMCS; i++) {
- KASSERT(pcs->pc_hwpmcs[i]->phw_pmc == NULL,
+ for (i = 0; i < AMD_NPMCS; i++) {
+ KASSERT(pac->pc_amdpmcs[i].phw_pmc == NULL,
("[amd,%d] CPU%d/PMC%d in use", __LINE__, cpu, i));
KASSERT(AMD_PMC_IS_STOPPED(AMD_PMC_EVSEL_0 + (i-1)),
("[amd,%d] CPU%d/PMC%d not stopped", __LINE__, cpu, i));
}
#endif
- pmc_pcpu[cpu] = NULL;
- FREE(pcs, M_PMC);
- return 0;
+ pc = pmc_pcpu[cpu];
+ KASSERT(pc != NULL, ("[amd,%d] NULL per-cpu state", __LINE__));
+
+#if defined(__amd64__)
+ classindex = PMC_MDEP_CLASS_INDEX_K8;
+#elif defined(__i386__)
+ classindex = md->pmd_cputype == PMC_CPU_AMD_K8 ? PMC_MDEP_CLASS_INDEX_K8 :
+ PMC_MDEP_CLASS_INDEX_K7;
+#endif
+ first_ri = md->pmd_classdep[classindex].pcd_ri;
+
+ /*
+ * Reset pointers in the MI 'per-cpu' state.
+ */
+ for (i = 0; i < AMD_NPMCS; i++) {
+ pc->pc_hwpmcs[i + first_ri] = NULL;
+ }
+
+
+ free(pac, M_PMC);
+
+ return (0);
}
/*
@@ -914,11 +874,12 @@ amd_cleanup(int cpu)
struct pmc_mdep *
pmc_amd_initialize(void)
{
+ int classindex, error, i, nclasses, ncpus;
+ struct pmc_classdep *pcd;
enum pmc_cputype cputype;
- enum pmc_class class;
struct pmc_mdep *pmc_mdep;
+ enum pmc_class class;
char *name;
- int i;
/*
* The presence of hardware performance counters on the AMD
@@ -931,12 +892,16 @@ pmc_amd_initialize(void)
class = cputype = -1;
name = NULL;
switch (cpu_id & 0xF00) {
+#if defined(__i386__)
case 0x600: /* Athlon(tm) processor */
+ classindex = PMC_MDEP_CLASS_INDEX_K7;
cputype = PMC_CPU_AMD_K7;
class = PMC_CLASS_K7;
name = "K7";
break;
+#endif
case 0xF00: /* Athlon64/Opteron processor */
+ classindex = PMC_MDEP_CLASS_INDEX_K8;
cputype = PMC_CPU_AMD_K8;
class = PMC_CLASS_K8;
name = "K8";
@@ -952,53 +917,121 @@ pmc_amd_initialize(void)
amd_pmc_class = class;
#endif
- MALLOC(pmc_mdep, struct pmc_mdep *, sizeof(struct pmc_mdep),
+ /*
+ * Allocate space for pointers to PMC HW descriptors and for
+ * the MDEP structure used by MI code.
+ */
+ amd_pcpu = malloc(sizeof(struct amd_cpu *) * pmc_cpu_max(), M_PMC,
+ M_WAITOK|M_ZERO);
+
+ /*
+ * These processors have two classes of PMCs: the TSC and
+ * programmable PMCs.
+ */
+ nclasses = 2;
+ pmc_mdep = malloc(sizeof(struct pmc_mdep) + nclasses * sizeof (struct pmc_classdep),
M_PMC, M_WAITOK|M_ZERO);
- pmc_mdep->pmd_cputype = cputype;
- pmc_mdep->pmd_npmc = AMD_NPMCS;
+ pmc_mdep->pmd_cputype = cputype;
+ pmc_mdep->pmd_nclass = nclasses;
- /* this processor has two classes of usable PMCs */
- pmc_mdep->pmd_nclass = 2;
+ ncpus = pmc_cpu_max();
- /* TSC */
- pmc_mdep->pmd_classes[0].pm_class = PMC_CLASS_TSC;
- pmc_mdep->pmd_classes[0].pm_caps = PMC_CAP_READ;
- pmc_mdep->pmd_classes[0].pm_width = 64;
+ /* Initialize the TSC. */
+ error = pmc_tsc_initialize(pmc_mdep, ncpus);
+ if (error)
+ goto error;
- /* AMD K7/K8 PMCs */
- pmc_mdep->pmd_classes[1].pm_class = class;
- pmc_mdep->pmd_classes[1].pm_caps = AMD_PMC_CAPS;
- pmc_mdep->pmd_classes[1].pm_width = 48;
+ /* Initialize AMD K7 and K8 PMC handling. */
+ pcd = &pmc_mdep->pmd_classdep[classindex];
- pmc_mdep->pmd_nclasspmcs[0] = 1;
- pmc_mdep->pmd_nclasspmcs[1] = (AMD_NPMCS-1);
+ pcd->pcd_caps = AMD_PMC_CAPS;
+ pcd->pcd_class = class;
+ pcd->pcd_num = AMD_NPMCS;
+ pcd->pcd_ri = pmc_mdep->pmd_npmc;
+ pcd->pcd_width = 48;
/* fill in the correct pmc name and class */
- for (i = 1; i < AMD_NPMCS; i++) {
+ for (i = 0; i < AMD_NPMCS; i++) {
(void) snprintf(amd_pmcdesc[i].pm_descr.pd_name,
sizeof(amd_pmcdesc[i].pm_descr.pd_name), "%s-%d",
- name, i-1);
+ name, i);
amd_pmcdesc[i].pm_descr.pd_class = class;
}
- pmc_mdep->pmd_init = amd_init;
- pmc_mdep->pmd_cleanup = amd_cleanup;
- pmc_mdep->pmd_switch_in = amd_switch_in;
- pmc_mdep->pmd_switch_out = amd_switch_out;
- pmc_mdep->pmd_read_pmc = amd_read_pmc;
- pmc_mdep->pmd_write_pmc = amd_write_pmc;
- pmc_mdep->pmd_config_pmc = amd_config_pmc;
- pmc_mdep->pmd_get_config = amd_get_config;
- pmc_mdep->pmd_allocate_pmc = amd_allocate_pmc;
- pmc_mdep->pmd_release_pmc = amd_release_pmc;
- pmc_mdep->pmd_start_pmc = amd_start_pmc;
- pmc_mdep->pmd_stop_pmc = amd_stop_pmc;
- pmc_mdep->pmd_intr = amd_intr;
- pmc_mdep->pmd_describe = amd_describe;
- pmc_mdep->pmd_get_msr = amd_get_msr; /* i386 */
+ pcd->pcd_allocate_pmc = amd_allocate_pmc;
+ pcd->pcd_config_pmc = amd_config_pmc;
+ pcd->pcd_describe = amd_describe;
+ pcd->pcd_get_config = amd_get_config;
+ pcd->pcd_get_msr = amd_get_msr;
+ pcd->pcd_pcpu_fini = amd_pcpu_fini;
+ pcd->pcd_pcpu_init = amd_pcpu_init;
+ pcd->pcd_read_pmc = amd_read_pmc;
+ pcd->pcd_release_pmc = amd_release_pmc;
+ pcd->pcd_start_pmc = amd_start_pmc;
+ pcd->pcd_stop_pmc = amd_stop_pmc;
+ pcd->pcd_write_pmc = amd_write_pmc;
+
+ pmc_mdep->pmd_pcpu_init = NULL;
+ pmc_mdep->pmd_pcpu_fini = NULL;
+ pmc_mdep->pmd_intr = amd_intr;
+ pmc_mdep->pmd_switch_in = amd_switch_in;
+ pmc_mdep->pmd_switch_out = amd_switch_out;
+
+ pmc_mdep->pmd_npmc += AMD_NPMCS;
PMCDBG(MDP,INI,0,"%s","amd-initialize");
- return pmc_mdep;
+ return (pmc_mdep);
+
+ error:
+ if (error) {
+ free(pmc_mdep, M_PMC);
+ pmc_mdep = NULL;
+ }
+
+ return (NULL);
+}
+
+/*
+ * Finalization code for AMD CPUs.
+ */
+
+void
+pmc_amd_finalize(struct pmc_mdep *md)
+{
+#if defined(INVARIANTS)
+ int classindex, i, ncpus, pmcclass;
+#endif
+
+ pmc_tsc_finalize(md);
+
+ KASSERT(amd_pcpu != NULL, ("[amd,%d] NULL per-cpu array pointer",
+ __LINE__));
+
+#if defined(INVARIANTS)
+ switch (md->pmd_cputype) {
+#if defined(__i386__)
+ case PMC_CPU_AMD_K7:
+ classindex = PMC_MDEP_CLASS_INDEX_K7;
+ pmcclass = PMC_CLASS_K7;
+ break;
+#endif
+ default:
+ classindex = PMC_MDEP_CLASS_INDEX_K8;
+ pmcclass = PMC_CLASS_K8;
+ }
+
+ KASSERT(md->pmd_classdep[classindex].pcd_class == pmcclass,
+ ("[amd,%d] pmc class mismatch", __LINE__));
+
+ ncpus = pmc_cpu_max();
+
+ for (i = 0; i < ncpus; i++)
+ KASSERT(amd_pcpu[i] == NULL, ("[amd,%d] non-null pcpu",
+ __LINE__));
+#endif
+
+ free(amd_pcpu, M_PMC);
+ amd_pcpu = NULL;
}
diff --git a/sys/dev/hwpmc/hwpmc_amd.h b/sys/dev/hwpmc/hwpmc_amd.h
index aa6417b81d7a..b995dbe08c95 100644
--- a/sys/dev/hwpmc/hwpmc_amd.h
+++ b/sys/dev/hwpmc/hwpmc_amd.h
@@ -44,7 +44,7 @@
#define AMD_PMC_PERFCTR_3 0xC0010007
-#define AMD_NPMCS 5 /* 1 TSC + 4 PMCs */
+#define AMD_NPMCS 4
#define AMD_PMC_COUNTERMASK 0xFF000000
#define AMD_PMC_TO_COUNTER(x) (((x) << 24) & AMD_PMC_COUNTERMASK)
@@ -93,11 +93,5 @@ struct pmc_md_amd_pmc {
uint32_t pm_amd_evsel;
};
-/*
- * Prototypes
- */
-
-struct pmc_mdep *pmc_amd_initialize(void); /* AMD K7/K8 PMCs */
-
#endif /* _KERNEL */
#endif /* _DEV_HWPMC_AMD_H_ */
diff --git a/sys/dev/hwpmc/hwpmc_arm.c b/sys/dev/hwpmc/hwpmc_arm.c
index af905b66924e..ce1caf69e108 100644
--- a/sys/dev/hwpmc/hwpmc_arm.c
+++ b/sys/dev/hwpmc/hwpmc_arm.c
@@ -38,3 +38,29 @@ pmc_md_initialize()
{
return NULL;
}
+
+void
+pmc_md_finalize(struct pmc_mdep *md)
+{
+ (void) md;
+}
+
+int
+pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
+ struct trapframe *tf)
+{
+ (void) cc;
+ (void) maxsamples;
+ (void) tf;
+ return (0);
+}
+
+int
+pmc_save_user_callchain(uintptr_t *cc, int maxsamples,
+ struct trapframe *tf)
+{
+ (void) cc;
+ (void) maxsamples;
+ (void) tf;
+ return (0);
+}
diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c
new file mode 100644
index 000000000000..214e42cb4b06
--- /dev/null
+++ b/sys/dev/hwpmc/hwpmc_core.c
@@ -0,0 +1,1988 @@
+/*-
+ * Copyright (c) 2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Intel Core, Core 2 and Atom PMCs.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/pmc.h>
+#include <sys/pmckern.h>
+#include <sys/systm.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/specialreg.h>
+
+#define CORE_CPUID_REQUEST 0xA
+#define CORE_CPUID_REQUEST_SIZE 0x4
+#define CORE_CPUID_EAX 0x0
+#define CORE_CPUID_EBX 0x1
+#define CORE_CPUID_ECX 0x2
+#define CORE_CPUID_EDX 0x3
+
+#define IAF_PMC_CAPS \
+ (PMC_CAP_READ | PMC_CAP_WRITE | PMC_CAP_INTERRUPT)
+#define IAF_RI_TO_MSR(RI) ((RI) + (1 << 30))
+
+#define IAP_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | PMC_CAP_SYSTEM | \
+ PMC_CAP_EDGE | PMC_CAP_THRESHOLD | PMC_CAP_READ | PMC_CAP_WRITE | \
+ PMC_CAP_INVERT | PMC_CAP_QUALIFIER | PMC_CAP_PRECISE)
+
+/*
+ * "Architectural" events defined by Intel. The values of these
+ * symbols correspond to positions in the bitmask returned by
+ * the CPUID.0AH instruction.
+ */
+enum core_arch_events {
+ CORE_AE_BRANCH_INSTRUCTION_RETIRED = 5,
+ CORE_AE_BRANCH_MISSES_RETIRED = 6,
+ CORE_AE_INSTRUCTION_RETIRED = 1,
+ CORE_AE_LLC_MISSES = 4,
+ CORE_AE_LLC_REFERENCE = 3,
+ CORE_AE_UNHALTED_REFERENCE_CYCLES = 2,
+ CORE_AE_UNHALTED_CORE_CYCLES = 0
+};
+
+static enum pmc_cputype core_cputype;
+
+struct core_cpu {
+ volatile uint32_t pc_resync;
+ volatile uint32_t pc_iafctrl; /* Fixed function control. */
+ volatile uint64_t pc_globalctrl; /* Global control register. */
+ struct pmc_hw pc_corepmcs[];
+};
+
+static struct core_cpu **core_pcpu;
+
+static uint32_t core_architectural_events;
+static uint64_t core_pmcmask;
+
+static int core_iaf_ri; /* relative index of fixed counters */
+static int core_iaf_width;
+static int core_iaf_npmc;
+
+static int core_iap_width;
+static int core_iap_npmc;
+
+static int
+core_pcpu_noop(struct pmc_mdep *md, int cpu)
+{
+ (void) md;
+ (void) cpu;
+ return (0);
+}
+
+static int
+core_pcpu_init(struct pmc_mdep *md, int cpu)
+{
+ struct pmc_cpu *pc;
+ struct core_cpu *cc;
+ struct pmc_hw *phw;
+ int core_ri, n, npmc;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[iaf,%d] insane cpu number %d", __LINE__, cpu));
+
+ PMCDBG(MDP,INI,1,"core-init cpu=%d", cpu);
+
+ core_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_ri;
+ npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_num;
+
+ if (core_cputype != PMC_CPU_INTEL_CORE)
+ npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF].pcd_num;
+
+ cc = malloc(sizeof(struct core_cpu) + npmc * sizeof(struct pmc_hw),
+ M_PMC, M_WAITOK | M_ZERO);
+
+ core_pcpu[cpu] = cc;
+ pc = pmc_pcpu[cpu];
+
+ KASSERT(pc != NULL && cc != NULL,
+ ("[core,%d] NULL per-cpu structures cpu=%d", __LINE__, cpu));
+
+ for (n = 0, phw = cc->pc_corepmcs; n < npmc; n++, phw++) {
+ phw->phw_state = PMC_PHW_FLAG_IS_ENABLED |
+ PMC_PHW_CPU_TO_STATE(cpu) |
+ PMC_PHW_INDEX_TO_STATE(n + core_ri);
+ phw->phw_pmc = NULL;
+ pc->pc_hwpmcs[n + core_ri] = phw;
+ }
+
+ return (0);
+}
+
+static int
+core_pcpu_fini(struct pmc_mdep *md, int cpu)
+{
+ int core_ri, n, npmc;
+ struct pmc_cpu *pc;
+ struct core_cpu *cc;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] insane cpu number (%d)", __LINE__, cpu));
+
+ PMCDBG(MDP,INI,1,"core-pcpu-fini cpu=%d", cpu);
+
+ if ((cc = core_pcpu[cpu]) == NULL)
+ return (0);
+
+ core_pcpu[cpu] = NULL;
+
+ pc = pmc_pcpu[cpu];
+
+ KASSERT(pc != NULL, ("[core,%d] NULL per-cpu %d state", __LINE__,
+ cpu));
+
+ npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_num;
+ core_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_ri;
+
+ for (n = 0; n < npmc; n++)
+ wrmsr(IAP_EVSEL0 + n, 0);
+
+ if (core_cputype != PMC_CPU_INTEL_CORE) {
+ wrmsr(IAF_CTRL, 0);
+ npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF].pcd_num;
+ }
+
+ for (n = 0; n < npmc; n++)
+ pc->pc_hwpmcs[n + core_ri] = NULL;
+
+ free(cc, M_PMC);
+
+ return (0);
+}
+
+/*
+ * Fixed function counters.
+ */
+
+static pmc_value_t
+iaf_perfctr_value_to_reload_count(pmc_value_t v)
+{
+ v &= (1ULL << core_iaf_width) - 1;
+ return (1ULL << core_iaf_width) - v;
+}
+
+static pmc_value_t
+iaf_reload_count_to_perfctr_value(pmc_value_t rlc)
+{
+ return (1ULL << core_iaf_width) - rlc;
+}
+
+static int
+iaf_allocate_pmc(int cpu, int ri, struct pmc *pm,
+ const struct pmc_op_pmcallocate *a)
+{
+ enum pmc_event ev;
+ uint32_t caps, flags, validflags;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal CPU %d", __LINE__, cpu));
+
+ PMCDBG(MDP,ALL,1, "iaf-allocate ri=%d reqcaps=0x%x", ri, pm->pm_caps);
+
+ if (ri < 0 || ri > core_iaf_npmc)
+ return (EINVAL);
+
+ caps = a->pm_caps;
+
+ if (a->pm_class != PMC_CLASS_IAF ||
+ (caps & IAF_PMC_CAPS) != caps)
+ return (EINVAL);
+
+ ev = pm->pm_event;
+ if (ev < PMC_EV_IAF_FIRST || ev > PMC_EV_IAF_LAST)
+ return (EINVAL);
+
+ if (ev == PMC_EV_IAF_INSTR_RETIRED_ANY && ri != 0)
+ return (EINVAL);
+ if (ev == PMC_EV_IAF_CPU_CLK_UNHALTED_CORE && ri != 1)
+ return (EINVAL);
+ if (ev == PMC_EV_IAF_CPU_CLK_UNHALTED_REF && ri != 2)
+ return (EINVAL);
+
+ flags = a->pm_md.pm_iaf.pm_iaf_flags;
+
+ validflags = IAF_MASK;
+
+ if (core_cputype != PMC_CPU_INTEL_ATOM)
+ validflags &= ~IAF_ANY;
+
+ if ((flags & ~validflags) != 0)
+ return (EINVAL);
+
+ if (caps & PMC_CAP_INTERRUPT)
+ flags |= IAF_PMI;
+ if (caps & PMC_CAP_SYSTEM)
+ flags |= IAF_OS;
+ if (caps & PMC_CAP_USER)
+ flags |= IAF_USR;
+ if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
+ flags |= (IAF_OS | IAF_USR);
+
+ pm->pm_md.pm_iaf.pm_iaf_ctrl = (flags << (ri * 4));
+
+ PMCDBG(MDP,ALL,2, "iaf-allocate config=0x%jx",
+ (uintmax_t) pm->pm_md.pm_iaf.pm_iaf_ctrl);
+
+ return (0);
+}
+
+static int
+iaf_config_pmc(int cpu, int ri, struct pmc *pm)
+{
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal CPU %d", __LINE__, cpu));
+
+ KASSERT(ri >= 0 && ri < core_iaf_npmc,
+ ("[core,%d] illegal row-index %d", __LINE__, ri));
+
+ PMCDBG(MDP,CFG,1, "iaf-config cpu=%d ri=%d pm=%p", cpu, ri, pm);
+
+ KASSERT(core_pcpu[cpu] != NULL, ("[core,%d] null per-cpu %d", __LINE__,
+ cpu));
+
+ core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc = pm;
+
+ return (0);
+}
+
+static int
+iaf_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
+{
+ int error;
+ struct pmc_hw *phw;
+ char iaf_name[PMC_NAME_MAX];
+
+ phw = &core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri];
+
+ (void) snprintf(iaf_name, sizeof(iaf_name), "IAF-%d", ri);
+ if ((error = copystr(iaf_name, pi->pm_name, PMC_NAME_MAX,
+ NULL)) != 0)
+ return (error);
+
+ pi->pm_class = PMC_CLASS_IAF;
+
+ if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
+ pi->pm_enabled = TRUE;
+ *ppmc = phw->phw_pmc;
+ } else {
+ pi->pm_enabled = FALSE;
+ *ppmc = NULL;
+ }
+
+ return (0);
+}
+
+static int
+iaf_get_config(int cpu, int ri, struct pmc **ppm)
+{
+ *ppm = core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
+
+ return (0);
+}
+
+static int
+iaf_get_msr(int ri, uint32_t *msr)
+{
+ KASSERT(ri >= 0 && ri < core_iaf_npmc,
+ ("[iaf,%d] ri %d out of range", __LINE__, ri));
+
+ *msr = IAF_RI_TO_MSR(ri);
+
+ return (0);
+}
+
+static int
+iaf_read_pmc(int cpu, int ri, pmc_value_t *v)
+{
+ struct pmc *pm;
+ pmc_value_t tmp;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal cpu value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < core_iaf_npmc,
+ ("[core,%d] illegal row-index %d", __LINE__, ri));
+
+ pm = core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
+
+ KASSERT(pm,
+ ("[core,%d] cpu %d ri %d(%d) pmc not configured", __LINE__, cpu,
+ ri, ri + core_iaf_ri));
+
+ tmp = rdpmc(IAF_RI_TO_MSR(ri));
+
+ if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+ *v = iaf_perfctr_value_to_reload_count(tmp);
+ else
+ *v = tmp;
+
+ PMCDBG(MDP,REA,1, "iaf-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
+ IAF_RI_TO_MSR(ri), *v);
+
+ return (0);
+}
+
+static int
+iaf_release_pmc(int cpu, int ri, struct pmc *pmc)
+{
+ PMCDBG(MDP,REL,1, "iaf-release cpu=%d ri=%d pm=%p", cpu, ri, pmc);
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal CPU value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < core_iaf_npmc,
+ ("[core,%d] illegal row-index %d", __LINE__, ri));
+
+ KASSERT(core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc == NULL,
+ ("[core,%d] PHW pmc non-NULL", __LINE__));
+
+ return (0);
+}
+
+static int
+iaf_start_pmc(int cpu, int ri)
+{
+ struct pmc *pm;
+ struct core_cpu *iafc;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal CPU value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < core_iaf_npmc,
+ ("[core,%d] illegal row-index %d", __LINE__, ri));
+
+ PMCDBG(MDP,STA,1,"iaf-start cpu=%d ri=%d", cpu, ri);
+
+ iafc = core_pcpu[cpu];
+ pm = iafc->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
+
+ iafc->pc_iafctrl |= pm->pm_md.pm_iaf.pm_iaf_ctrl;
+
+ wrmsr(IAF_CTRL, iafc->pc_iafctrl);
+
+ do {
+ iafc->pc_resync = 0;
+ iafc->pc_globalctrl |= (1ULL << (ri + IAF_OFFSET));
+ wrmsr(IA_GLOBAL_CTRL, iafc->pc_globalctrl);
+ } while (iafc->pc_resync != 0);
+
+ PMCDBG(MDP,STA,1,"iafctrl=%x(%x) globalctrl=%jx(%jx)",
+ iafc->pc_iafctrl, (uint32_t) rdmsr(IAF_CTRL),
+ iafc->pc_globalctrl, rdmsr(IA_GLOBAL_CTRL));
+
+ return (0);
+}
+
+static int
+iaf_stop_pmc(int cpu, int ri)
+{
+ uint32_t fc;
+ struct core_cpu *iafc;
+
+ PMCDBG(MDP,STO,1,"iaf-stop cpu=%d ri=%d", cpu, ri);
+
+ iafc = core_pcpu[cpu];
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal CPU value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < core_iaf_npmc,
+ ("[core,%d] illegal row-index %d", __LINE__, ri));
+
+ fc = (IAF_MASK << (ri * 4));
+
+ if (core_cputype != PMC_CPU_INTEL_ATOM)
+ fc &= ~IAF_ANY;
+
+ iafc->pc_iafctrl &= ~fc;
+
+ PMCDBG(MDP,STO,1,"iaf-stop iafctrl=%x", iafc->pc_iafctrl);
+ wrmsr(IAF_CTRL, iafc->pc_iafctrl);
+
+ do {
+ iafc->pc_resync = 0;
+ iafc->pc_globalctrl &= ~(1ULL << (ri + IAF_OFFSET));
+ wrmsr(IA_GLOBAL_CTRL, iafc->pc_globalctrl);
+ } while (iafc->pc_resync != 0);
+
+ PMCDBG(MDP,STO,1,"iafctrl=%x(%x) globalctrl=%jx(%jx)",
+ iafc->pc_iafctrl, (uint32_t) rdmsr(IAF_CTRL),
+ iafc->pc_globalctrl, rdmsr(IA_GLOBAL_CTRL));
+
+ return (0);
+}
+
+static int
+iaf_write_pmc(int cpu, int ri, pmc_value_t v)
+{
+ struct core_cpu *cc;
+ struct pmc *pm;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal cpu value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < core_iaf_npmc,
+ ("[core,%d] illegal row-index %d", __LINE__, ri));
+
+ cc = core_pcpu[cpu];
+ pm = cc->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
+
+ KASSERT(pm,
+ ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, ri));
+
+ if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+ v = iaf_reload_count_to_perfctr_value(v);
+
+ wrmsr(IAF_CTRL, 0); /* Turn off fixed counters */
+ wrmsr(IAF_CTR0 + ri, v);
+ wrmsr(IAF_CTRL, cc->pc_iafctrl);
+
+ PMCDBG(MDP,WRI,1, "iaf-write cpu=%d ri=%d msr=0x%x v=%jx iafctrl=%jx "
+ "pmc=%jx", cpu, ri, IAF_RI_TO_MSR(ri), v,
+ (uintmax_t) rdmsr(IAF_CTRL),
+ (uintmax_t) rdpmc(IAF_RI_TO_MSR(ri)));
+
+ return (0);
+}
+
+
+static void
+iaf_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth)
+{
+ struct pmc_classdep *pcd;
+
+ KASSERT(md != NULL, ("[iaf,%d] md is NULL", __LINE__));
+
+ PMCDBG(MDP,INI,1, "%s", "iaf-initialize");
+
+ pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF];
+
+ pcd->pcd_caps = IAF_PMC_CAPS;
+ pcd->pcd_class = PMC_CLASS_IAF;
+ pcd->pcd_num = npmc;
+ pcd->pcd_ri = md->pmd_npmc;
+ pcd->pcd_width = pmcwidth;
+
+ pcd->pcd_allocate_pmc = iaf_allocate_pmc;
+ pcd->pcd_config_pmc = iaf_config_pmc;
+ pcd->pcd_describe = iaf_describe;
+ pcd->pcd_get_config = iaf_get_config;
+ pcd->pcd_get_msr = iaf_get_msr;
+ pcd->pcd_pcpu_fini = core_pcpu_noop;
+ pcd->pcd_pcpu_init = core_pcpu_noop;
+ pcd->pcd_read_pmc = iaf_read_pmc;
+ pcd->pcd_release_pmc = iaf_release_pmc;
+ pcd->pcd_start_pmc = iaf_start_pmc;
+ pcd->pcd_stop_pmc = iaf_stop_pmc;
+ pcd->pcd_write_pmc = iaf_write_pmc;
+
+ md->pmd_npmc += npmc;
+}
+
+/*
+ * Intel programmable PMCs.
+ */
+
+/*
+ * Event descriptor tables.
+ *
+ * For each event id, we track:
+ *
+ * 1. The CPUs that the event is valid for.
+ *
+ * 2. If the event uses a fixed UMASK, the value of the umask field.
+ * If the event doesn't use a fixed UMASK, a mask of legal bits
+ * to check against.
+ */
+
+struct iap_event_descr {
+ enum pmc_event iap_ev;
+ unsigned char iap_evcode;
+ unsigned char iap_umask;
+ unsigned char iap_flags;
+};
+
+#define IAP_F_CC (1 << 0) /* CPU: Core */
+#define IAP_F_CC2 (1 << 1) /* CPU: Core2 family */
+#define IAP_F_CC2E (1 << 2) /* CPU: Core2 Extreme only */
+#define IAP_F_CA (1 << 3) /* CPU: Atom */
+#define IAP_F_I7 (1 << 4) /* CPU: Core i7 */
+#define IAP_F_FM (1 << 5) /* Fixed mask */
+
+#define IAP_F_ALLCPUS \
+ (IAP_F_CC | IAP_F_CC2 | IAP_F_CC2E | IAP_F_CA | IAP_F_I7)
+
+/* Sub fields of UMASK that this event supports. */
+#define IAP_M_CORE (1 << 0) /* Core specificity */
+#define IAP_M_AGENT (1 << 1) /* Agent specificity */
+#define IAP_M_PREFETCH (1 << 2) /* Prefetch */
+#define IAP_M_MESI (1 << 3) /* MESI */
+#define IAP_M_SNOOPRESPONSE (1 << 4) /* Snoop response */
+#define IAP_M_SNOOPTYPE (1 << 5) /* Snoop type */
+#define IAP_M_TRANSITION (1 << 6) /* Transition */
+
+#define IAP_F_CORE (0x3 << 14) /* Core specificity */
+#define IAP_F_AGENT (0x1 << 13) /* Agent specificity */
+#define IAP_F_PREFETCH (0x3 << 12) /* Prefetch */
+#define IAP_F_MESI (0xF << 8) /* MESI */
+#define IAP_F_SNOOPRESPONSE (0xB << 8) /* Snoop response */
+#define IAP_F_SNOOPTYPE (0x3 << 8) /* Snoop type */
+#define IAP_F_TRANSITION (0x1 << 12) /* Transition */
+
+#define IAP_PREFETCH_RESERVED (0x2 << 12)
+#define IAP_CORE_THIS (0x1 << 14)
+#define IAP_CORE_ALL (0x3 << 14)
+#define IAP_F_CMASK 0xFF000000
+
+static struct iap_event_descr iap_events[] = {
+#undef IAPDESCR
+#define IAPDESCR(N,EV,UM,FLAGS) { \
+ .iap_ev = PMC_EV_IAP_EVENT_##N, \
+ .iap_evcode = (EV), \
+ .iap_umask = (UM), \
+ .iap_flags = (FLAGS) \
+ }
+
+ IAPDESCR(02H_81H, 0x02, 0x81, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(03H_00H, 0x03, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(03H_02H, 0x03, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(03H_04H, 0x03, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(03H_08H, 0x03, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(03H_10H, 0x03, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(03H_20H, 0x03, 0x20, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(04H_00H, 0x04, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(04H_01H, 0x04, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(04H_02H, 0x04, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(04H_08H, 0x04, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(05H_00H, 0x05, 0x00, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(06H_00H, 0x06, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(07H_00H, 0x07, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
+ IAPDESCR(07H_01H, 0x07, 0x01, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(07H_02H, 0x07, 0x02, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(07H_03H, 0x07, 0x03, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(07H_06H, 0x07, 0x06, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(07H_08H, 0x07, 0x08, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(08H_01H, 0x08, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(08H_02H, 0x08, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(08H_04H, 0x08, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(08H_05H, 0x08, 0x05, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(08H_06H, 0x08, 0x06, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(08H_07H, 0x08, 0x07, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(08H_08H, 0x08, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(08H_09H, 0x08, 0x09, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(09H_01H, 0x09, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(09H_02H, 0x09, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+
+ IAPDESCR(0CH_01H, 0x0C, 0x01, IAP_F_FM | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(0CH_02H, 0x0C, 0x02, IAP_F_FM | IAP_F_CC2),
+ IAPDESCR(0CH_03H, 0x0C, 0x03, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(10H_00H, 0x10, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(10H_01H, 0x10, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7),
+ IAPDESCR(10H_81H, 0x10, 0x81, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(11H_00H, 0x11, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
+ IAPDESCR(11H_01H, 0x11, 0x01, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(11H_81H, 0x11, 0x81, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(12H_00H, 0x12, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(12H_01H, 0x12, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7),
+ IAPDESCR(12H_81H, 0x12, 0x81, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(13H_00H, 0x13, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(13H_01H, 0x13, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7),
+ IAPDESCR(13H_81H, 0x13, 0x81, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(14H_00H, 0x14, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
+ IAPDESCR(14H_01H, 0x14, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7),
+
+ IAPDESCR(18H_00H, 0x18, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(19H_00H, 0x19, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(19H_01H, 0x19, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(19H_02H, 0x19, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(21H, 0x21, IAP_M_CORE, IAP_F_ALLCPUS),
+ IAPDESCR(22H, 0x22, IAP_M_CORE, IAP_F_CC2),
+ IAPDESCR(23H, 0x23, IAP_M_CORE, IAP_F_ALLCPUS),
+ IAPDESCR(24H, 0x24, IAP_M_CORE | IAP_M_PREFETCH, IAP_F_ALLCPUS),
+ IAPDESCR(25H, 0x25, IAP_M_CORE, IAP_F_ALLCPUS),
+ IAPDESCR(26H, 0x26, IAP_M_CORE | IAP_M_PREFETCH, IAP_F_ALLCPUS),
+ IAPDESCR(27H, 0x27, IAP_M_CORE | IAP_M_PREFETCH, IAP_F_ALLCPUS),
+ IAPDESCR(28H, 0x28, IAP_M_CORE | IAP_M_MESI, IAP_F_ALLCPUS),
+ IAPDESCR(29H, 0x29, IAP_M_CORE | IAP_M_MESI, IAP_F_CC),
+ IAPDESCR(29H, 0x29, IAP_M_CORE | IAP_M_MESI | IAP_M_PREFETCH,
+ IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(2AH, 0x2A, IAP_M_CORE | IAP_M_MESI, IAP_F_ALLCPUS),
+ IAPDESCR(2BH, 0x2B, IAP_M_CORE | IAP_M_MESI, IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(2EH, 0x2E, IAP_M_CORE | IAP_M_MESI | IAP_M_PREFETCH,
+ IAP_F_ALLCPUS),
+ IAPDESCR(2EH_41H, 0x2E, 0x41, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(2EH_4FH, 0x2E, 0x4F, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(30H, 0x30, IAP_M_CORE | IAP_M_MESI | IAP_M_PREFETCH,
+ IAP_F_ALLCPUS),
+ IAPDESCR(32H, 0x32, IAP_M_CORE | IAP_M_MESI | IAP_M_PREFETCH, IAP_F_CC),
+ IAPDESCR(32H, 0x32, IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(3AH, 0x3A, IAP_M_TRANSITION, IAP_F_CC),
+ IAPDESCR(3AH_00H, 0x3A, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(3BH_C0H, 0x3B, 0xC0, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(3CH_00H, 0x3C, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(3CH_01H, 0x3C, 0x01, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(3CH_02H, 0x3C, 0x02, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(40H, 0x40, IAP_M_MESI, IAP_F_CC),
+ IAPDESCR(40H_21H, 0x40, 0x21, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(41H, 0x41, IAP_M_MESI, IAP_F_CC | IAP_F_CC2),
+ IAPDESCR(41H_22H, 0x41, 0x22, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(42H, 0x42, IAP_M_MESI, IAP_F_ALLCPUS),
+ IAPDESCR(42H_10H, 0x42, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(43H_01H, 0x43, 0x01, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(43H_02H, 0x43, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+
+ IAPDESCR(44H_02H, 0x44, 0x02, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(45H_0FH, 0x45, 0x0F, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(46H_00H, 0x46, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(47H_00H, 0x47, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(48H_00H, 0x48, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(49H_00H, 0x49, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(49H_01H, 0x49, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(49H_02H, 0x49, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+
+ IAPDESCR(4BH_00H, 0x4B, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(4BH_01H, 0x4B, 0x01, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(4BH_02H, 0x4B, 0x02, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(4BH_03H, 0x4B, 0x03, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(4CH_00H, 0x4C, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(4EH_10H, 0x4E, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(4FH_00H, 0x4F, 0x00, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(60H, 0x60, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
+
+ IAPDESCR(61H, 0x61, IAP_M_AGENT, IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(61H_00H, 0x61, 0x00, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(62H, 0x62, IAP_M_AGENT, IAP_F_ALLCPUS),
+ IAPDESCR(62H_00H, 0x62, 0x00, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(63H, 0x63, IAP_M_AGENT | IAP_M_CORE,
+ IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(63H, 0x63, IAP_M_CORE, IAP_F_CC),
+
+ IAPDESCR(64H, 0x64, IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(64H_40H, 0x64, 0x40, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(65H, 0x65, IAP_M_AGENT | IAP_M_CORE,
+ IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(65H, 0x65, IAP_M_CORE, IAP_F_CC),
+
+ IAPDESCR(66H, 0x66, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
+
+ IAPDESCR(67H, 0x67, IAP_M_AGENT | IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(67H, 0x67, IAP_M_AGENT, IAP_F_CC),
+
+ IAPDESCR(68H, 0x68, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
+ IAPDESCR(69H, 0x69, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
+ IAPDESCR(6AH, 0x6A, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
+ IAPDESCR(6BH, 0x6B, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
+ IAPDESCR(6CH, 0x6C, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUS),
+
+ IAPDESCR(6DH, 0x6D, IAP_M_AGENT | IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(6DH, 0x6D, IAP_M_CORE, IAP_F_CC),
+
+ IAPDESCR(6EH, 0x6E, IAP_M_AGENT | IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(6EH, 0x6E, IAP_M_CORE, IAP_F_CC),
+
+ IAPDESCR(6FH, 0x6F, IAP_M_AGENT | IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(6FH, 0x6F, IAP_M_CORE, IAP_F_CC),
+
+ IAPDESCR(70H, 0x70, IAP_M_AGENT | IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(70H, 0x70, IAP_M_CORE, IAP_F_CC),
+
+ IAPDESCR(77H, 0x77, IAP_M_AGENT | IAP_M_SNOOPRESPONSE,
+ IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(77H, 0x77, IAP_M_AGENT | IAP_M_MESI, IAP_F_CC),
+
+ IAPDESCR(78H, 0x78, IAP_M_CORE, IAP_F_CC),
+ IAPDESCR(78H, 0x78, IAP_M_CORE | IAP_M_SNOOPTYPE, IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(7AH, 0x7A, IAP_M_AGENT, IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(7BH, 0x7B, IAP_M_AGENT, IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(7DH, 0x7D, IAP_M_CORE, IAP_F_ALLCPUS),
+
+ IAPDESCR(7EH, 0x7E, IAP_M_AGENT | IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(7EH_00H, 0x7E, 0x00, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(7FH, 0x7F, IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(80H_00H, 0x80, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(80H_02H, 0x80, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_I7),
+ IAPDESCR(80H_03H, 0x80, 0x03, IAP_F_FM | IAP_F_CA | IAP_F_I7),
+
+ IAPDESCR(81H_00H, 0x81, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(82H_02H, 0x82, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(82H_04H, 0x82, 0x04, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(82H_10H, 0x82, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(82H_12H, 0x82, 0x12, IAP_F_FM | IAP_F_CC2),
+ IAPDESCR(82H_40H, 0x82, 0x40, IAP_F_FM | IAP_F_CC2),
+
+ IAPDESCR(83H_02H, 0x83, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(85H_00H, 0x85, 0x00, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(86H_00H, 0x86, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(87H_00H, 0x87, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(88H_00H, 0x88, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(89H_00H, 0x89, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(8AH_00H, 0x8A, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(8BH_00H, 0x8B, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(8CH_00H, 0x8C, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(8DH_00H, 0x8D, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(8EH_00H, 0x8E, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(8FH_00H, 0x8F, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(90H_00H, 0x90, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(91H_00H, 0x91, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(92H_00H, 0x92, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(93H_00H, 0x93, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(94H_00H, 0x94, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(97H_00H, 0x97, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(98H_00H, 0x98, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(A0H_00H, 0xA0, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(A1H_01H, 0xA1, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(A1H_02H, 0xA1, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(A1H_04H, 0xA1, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(A1H_08H, 0xA1, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(A1H_10H, 0xA1, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(A1H_20H, 0xA1, 0x20, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(A2H_00H, 0xA2, 0x00, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(AAH_01H, 0xAA, 0x01, IAP_F_FM | IAP_F_CC2),
+ IAPDESCR(AAH_02H, 0xAA, 0x02, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(AAH_03H, 0xAA, 0x03, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(AAH_08H, 0xAA, 0x08, IAP_F_FM | IAP_F_CC2),
+
+ IAPDESCR(ABH_01H, 0xAB, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(ABH_02H, 0xAB, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(B0H_00H, 0xB0, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(B0H_80H, 0xB0, 0x80, IAP_F_FM | IAP_F_CA | IAP_F_I7),
+
+ IAPDESCR(B1H_00H, 0xB1, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(B1H_80H, 0xB1, 0x80, IAP_F_FM | IAP_F_CA | IAP_F_I7),
+
+ IAPDESCR(B3H_01H, 0xB3, 0x01, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(B3H_02H, 0xB3, 0x02, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(B3H_04H, 0xB3, 0x04, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(B3H_08H, 0xB3, 0x08, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(B3H_10H, 0xB3, 0x10, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(B3H_20H, 0xB3, 0x20, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(B3H_81H, 0xB3, 0x81, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(B3H_82H, 0xB3, 0x82, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(B3H_84H, 0xB3, 0x84, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(B3H_88H, 0xB3, 0x88, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(B3H_90H, 0xB3, 0x90, IAP_F_FM | IAP_F_CA),
+ IAPDESCR(B3H_A0H, 0xB3, 0xA0, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(C0H_00H, 0xC0, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(C0H_01H, 0xC0, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C0H_02H, 0xC0, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C0H_04H, 0xC0, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(C0H_08H, 0xC0, 0x08, IAP_F_FM | IAP_F_CC2E),
+
+ IAPDESCR(C1H_00H, 0xC1, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(C1H_01H, 0xC1, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(C1H_FEH, 0xC1, 0xFE, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(C2H_00H, 0xC2, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(C2H_01H, 0xC2, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C2H_02H, 0xC2, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C2H_04H, 0xC2, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C2H_07H, 0xC2, 0x07, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(C2H_08H, 0xC2, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(C2H_0FH, 0xC2, 0x0F, IAP_F_FM | IAP_F_CC2),
+ IAPDESCR(C2H_10H, 0xC2, 0x10, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(C3H_00H, 0xC3, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(C3H_01H, 0xC3, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C3H_04H, 0xC3, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+
+ IAPDESCR(C4H_00H, 0xC4, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(C4H_01H, 0xC4, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C4H_02H, 0xC4, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C4H_04H, 0xC4, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C4H_08H, 0xC4, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(C4H_0CH, 0xC4, 0x0C, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(C4H_0FH, 0xC4, 0x0F, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(C5H_00H, 0xC5, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(C6H_00H, 0xC6, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(C6H_01H, 0xC6, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(C6H_02H, 0xC6, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(C7H_00H, 0xC7, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(C7H_01H, 0xC7, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C7H_02H, 0xC7, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C7H_04H, 0xC7, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C7H_08H, 0xC7, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C7H_10H, 0xC7, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(C7H_1FH, 0xC7, 0x1F, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(C8H_00H, 0xC8, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(C9H_00H, 0xC9, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(CAH_00H, 0xCA, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(CAH_01H, 0xCA, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(CAH_02H, 0xCA, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(CAH_04H, 0xCA, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(CAH_08H, 0xCA, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(CBH_01H, 0xCB, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(CBH_02H, 0xCB, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(CBH_04H, 0xCB, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(CBH_08H, 0xCB, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(CBH_10H, 0xCB, 0x10, IAP_F_FM | IAP_F_CC2 | IAP_F_I7),
+
+ IAPDESCR(CCH_00H, 0xCC, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(CCH_01H, 0xCC, 0x01, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(CCH_02H, 0xCC, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+
+ IAPDESCR(CDH_00H, 0xCD, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(CEH_00H, 0xCE, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(CFH_00H, 0xCF, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(D0H_00H, 0xD0, 0x00, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(D2H_01H, 0xD2, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(D2H_02H, 0xD2, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(D2H_04H, 0xD2, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(D2H_08H, 0xD2, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(D2H_0FH, 0xD2, 0x0F, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(D2H_10H, 0xD2, 0x10, IAP_F_FM | IAP_F_CC2E),
+
+ IAPDESCR(D4H_01H, 0xD4, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(D4H_02H, 0xD4, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(D4H_04H, 0xD4, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(D4H_08H, 0xD4, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(D4H_0FH, 0xD4, 0x0F, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(D5H_01H, 0xD5, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7),
+ IAPDESCR(D5H_02H, 0xD5, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(D5H_04H, 0xD5, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(D5H_08H, 0xD5, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(D5H_0FH, 0xD5, 0x0F, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(D7H_00H, 0xD7, 0x00, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(D8H_00H, 0xD8, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(D8H_01H, 0xD8, 0x01, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(D8H_02H, 0xD8, 0x02, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(D8H_03H, 0xD8, 0x03, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(D8H_04H, 0xD8, 0x04, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(D9H_00H, 0xD9, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(D9H_01H, 0xD9, 0x01, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(D9H_02H, 0xD9, 0x02, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(D9H_03H, 0xD9, 0x03, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(DAH_00H, 0xDA, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(DAH_01H, 0xDA, 0x01, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(DAH_02H, 0xDA, 0x02, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(DBH_00H, 0xDB, 0x00, IAP_F_FM | IAP_F_CC),
+
+ IAPDESCR(DCH_01H, 0xDC, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(DCH_02H, 0xDC, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(DCH_04H, 0xDC, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(DCH_08H, 0xDC, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(DCH_10H, 0xDC, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(DCH_1FH, 0xDC, 0x1F, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(E0H_00H, 0xE0, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
+ IAPDESCR(E0H_01H, 0xE0, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7),
+
+ IAPDESCR(E2H_00H, 0xE2, 0x00, IAP_F_FM | IAP_F_CC),
+ IAPDESCR(E4H_00H, 0xE4, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+
+ IAPDESCR(E6H_00H, 0xE6, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
+ IAPDESCR(E6H_01H, 0xE6, 0x01, IAP_F_FM | IAP_F_CA),
+
+ IAPDESCR(F0H_00H, 0xF0, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(F8H_00H, 0xF8, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+
+ /* Added with nehalem. */
+ IAPDESCR(02H_01H, 0x02, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(03H_01H, 0x03, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(05H_01H, 0x05, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(05H_02H, 0x05, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(05H_03H, 0x05, 0x03, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(06H_01H, 0x06, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(06H_02H, 0x06, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(06H_04H, 0x06, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(06H_08H, 0x06, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(06H_0FH, 0x06, 0x0F, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(08H_10H, 0x08, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(08H_20H, 0x08, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(08H_40H, 0x08, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(08H_80H, 0x08, 0x80, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(09H_04H, 0x09, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(09H_08H, 0x09, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(0BH_01H, 0x0B, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(0BH_02H, 0x0B, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(0EH_01H, 0x0E, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(0EH_02H, 0x0E, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(0FH_02H, 0x0F, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(0FH_08H, 0x0F, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(0FH_10H, 0x0F, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(0FH_20H, 0x0F, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(10H_02H, 0x10, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(10H_04H, 0x10, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(10H_08H, 0x10, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(10H_10H, 0x10, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(10H_20H, 0x10, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(10H_40H, 0x10, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(10H_80H, 0x10, 0x80, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(12H_02H, 0x12, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(12H_04H, 0x12, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(12H_08H, 0x12, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(12H_10H, 0x12, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(12H_20H, 0x12, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(12H_40H, 0x12, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(13H_02H, 0x13, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(13H_04H, 0x13, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(13H_07H, 0x13, 0x07, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(14H_02H, 0x14, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(17H_01H, 0x17, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(18H_01H, 0x18, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(1DH_01H, 0x1D, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(1DH_02H, 0x1D, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(1DH_04H, 0x1D, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(1EH_01H, 0x1E, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_01H, 0x24, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_02H, 0x24, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_03H, 0x24, 0x03, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_04H, 0x24, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_08H, 0x24, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_0CH, 0x24, 0x0C, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_10H, 0x24, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_20H, 0x24, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_30H, 0x24, 0x30, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_40H, 0x24, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_80H, 0x24, 0x80, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_AAH, 0x24, 0xAA, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_C0H, 0x24, 0xC0, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(24H_FFH, 0x24, 0xFF, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(26H_01H, 0x26, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(26H_02H, 0x26, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(26H_04H, 0x26, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(26H_08H, 0x26, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(26H_0FH, 0x26, 0x0F, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(26H_10H, 0x26, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(26H_20H, 0x26, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(26H_40H, 0x26, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(26H_80H, 0x26, 0x80, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(26H_F0H, 0x26, 0xF0, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(26H_FFH, 0x26, 0xFF, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(27H_01H, 0x27, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(27H_02H, 0x27, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(27H_04H, 0x27, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(27H_08H, 0x27, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(27H_0EH, 0x27, 0x0E, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(27H_0FH, 0x27, 0x0F, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(27H_10H, 0x27, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(27H_20H, 0x27, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(27H_40H, 0x27, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(27H_80H, 0x27, 0x80, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(27H_E0H, 0x27, 0xE0, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(27H_F0H, 0x27, 0xF0, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(28H_01H, 0x28, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(28H_02H, 0x28, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(28H_04H, 0x28, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(28H_08H, 0x28, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(28H_0FH, 0x28, 0x0F, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(3DH_01H, 0x3D, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(40H_01H, 0x40, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(40H_02H, 0x40, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(40H_04H, 0x40, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(40H_08H, 0x40, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(40H_0FH, 0x40, 0x0F, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(41H_01H, 0x41, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(41H_02H, 0x41, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(41H_04H, 0x41, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(41H_08H, 0x41, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(41H_0FH, 0x41, 0x0F, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(42H_01H, 0x42, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(42H_02H, 0x42, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(42H_04H, 0x42, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(42H_08H, 0x42, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(48H_02H, 0x48, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(49H_10H, 0x49, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(49H_20H, 0x49, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(49H_40H, 0x49, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(49H_80H, 0x49, 0x80, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(4BH_08H, 0x4B, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(4CH_01H, 0x4C, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(4DH_01H, 0x4D, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(4EH_01H, 0x4E, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(4EH_02H, 0x4E, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(4EH_04H, 0x4E, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(4FH_02H, 0x4F, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(4FH_04H, 0x4F, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(4FH_08H, 0x4F, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(51H_01H, 0x51, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(51H_02H, 0x51, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(51H_04H, 0x51, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(51H_08H, 0x51, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(52H_01H, 0x52, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(53H_01H, 0x53, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(60H_01H, 0x60, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(60H_02H, 0x60, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(60H_04H, 0x60, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(60H_08H, 0x60, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(63H_01H, 0x63, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(63H_02H, 0x63, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(6CH_01H, 0x6C, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(80H_01H, 0x80, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(80H_04H, 0x80, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(80H_10H, 0x80, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(81H_01H, 0x81, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(81H_02H, 0x81, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(82H_01H, 0x82, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(83H_01H, 0x83, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(85H_01H, 0x85, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(85H_02H, 0x85, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(85H_04H, 0x85, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(85H_10H, 0x85, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(85H_20H, 0x85, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(85H_40H, 0x85, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(85H_80H, 0x85, 0x80, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(87H_01H, 0x87, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(87H_02H, 0x87, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(87H_04H, 0x87, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(87H_08H, 0x87, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(87H_0FH, 0x87, 0x0F, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(88H_01H, 0x88, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(88H_02H, 0x88, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(88H_04H, 0x88, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(88H_07H, 0x88, 0x07, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(88H_08H, 0x88, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(88H_10H, 0x88, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(88H_20H, 0x88, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(88H_30H, 0x88, 0x30, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(88H_40H, 0x88, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(89H_01H, 0x89, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(89H_02H, 0x89, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(89H_04H, 0x89, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(89H_07H, 0x89, 0x07, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(89H_08H, 0x89, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(89H_10H, 0x89, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(89H_20H, 0x89, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(89H_30H, 0x89, 0x30, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(89H_40H, 0x89, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(89H_7FH, 0x89, 0x7F, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(A2H_01H, 0xA2, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(A2H_02H, 0xA2, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(A2H_04H, 0xA2, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(A2H_08H, 0xA2, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(A2H_10H, 0xA2, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(A2H_20H, 0xA2, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(A2H_40H, 0xA2, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(A2H_80H, 0xA2, 0x80, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(A6H_01H, 0xA6, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(A7H_01H, 0xA7, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(A8H_01H, 0xA8, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B0H_01H, 0xB0, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B0H_02H, 0xB0, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B0H_04H, 0xB0, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B0H_08H, 0xB0, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B0H_20H, 0xB0, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B0H_40H, 0xB0, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B1H_01H, 0xB1, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B1H_02H, 0xB1, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B1H_04H, 0xB1, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B1H_08H, 0xB1, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B1H_10H, 0xB1, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B1H_20H, 0xB1, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B1H_40H, 0xB1, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B2H_01H, 0xB2, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B7H_01H, 0xB7, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B8H_01H, 0xB8, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B8H_02H, 0xB8, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(B8H_04H, 0xB8, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(BAH_01H, 0xBA, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(BAH_02H, 0xBA, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(C3H_02H, 0xC3, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(C3H_10H, 0xC3, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(C5H_02H, 0xC5, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(C8H_20H, 0xC8, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(CBH_40H, 0xCB, 0x40, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(CBH_80H, 0xCB, 0x80, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(CCH_03H, 0xCC, 0x03, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(D0H_01H, 0xD0, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(D1H_02H, 0xD1, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(D1H_04H, 0xD1, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(D1H_08H, 0xD1, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(DBH_01H, 0xDB, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(E4H_01H, 0xE4, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(E5H_01H, 0xE5, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F3H_04H, 0xF3, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F3H_08H, 0xF3, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F3H_10H, 0xF3, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F3H_20H, 0xF3, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F4H_01H, 0xF4, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F4H_02H, 0xF4, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F4H_04H, 0xF4, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F4H_08H, 0xF4, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F4H_10H, 0xF4, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F6H_01H, 0xF6, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F7H_01H, 0xF7, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F7H_02H, 0xF7, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F7H_04H, 0xF7, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(F8H_01H, 0xF8, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(FDH_01H, 0xFD, 0x01, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(FDH_02H, 0xFD, 0x02, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(FDH_04H, 0xFD, 0x04, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(FDH_08H, 0xFD, 0x08, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(FDH_10H, 0xFD, 0x10, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(FDH_20H, 0xFD, 0x20, IAP_F_FM | IAP_F_I7),
+ IAPDESCR(FDH_40H, 0xFD, 0x40, IAP_F_FM | IAP_F_I7),
+};
+
+static const int niap_events = sizeof(iap_events) / sizeof(iap_events[0]);
+
+static pmc_value_t
+iap_perfctr_value_to_reload_count(pmc_value_t v)
+{
+ v &= (1ULL << core_iap_width) - 1;
+ return (1ULL << core_iap_width) - v;
+}
+
+static pmc_value_t
+iap_reload_count_to_perfctr_value(pmc_value_t rlc)
+{
+ return (1ULL << core_iap_width) - rlc;
+}
+
+static int
+iap_pmc_has_overflowed(int ri)
+{
+ uint64_t v;
+
+ /*
+ * We treat a Core (i.e., Intel architecture v1) PMC as has
+ * having overflowed if its MSB is zero.
+ */
+ v = rdpmc(ri);
+ return ((v & (1ULL << (core_iap_width - 1))) == 0);
+}
+
+/*
+ * Check an event against the set of supported architectural events.
+ *
+ * Returns 1 if the event is architectural and unsupported on this
+ * CPU. Returns 0 otherwise.
+ */
+
+static int
+iap_architectural_event_is_unsupported(enum pmc_event pe)
+{
+ enum core_arch_events ae;
+
+ switch (pe) {
+ case PMC_EV_IAP_EVENT_3CH_00H:
+ ae = CORE_AE_UNHALTED_CORE_CYCLES;
+ break;
+ case PMC_EV_IAP_EVENT_C0H_00H:
+ ae = CORE_AE_INSTRUCTION_RETIRED;
+ break;
+ case PMC_EV_IAP_EVENT_3CH_01H:
+ ae = CORE_AE_UNHALTED_REFERENCE_CYCLES;
+ break;
+ case PMC_EV_IAP_EVENT_2EH_4FH:
+ ae = CORE_AE_LLC_REFERENCE;
+ break;
+ case PMC_EV_IAP_EVENT_2EH_41H:
+ ae = CORE_AE_LLC_MISSES;
+ break;
+ case PMC_EV_IAP_EVENT_C4H_00H:
+ ae = CORE_AE_BRANCH_INSTRUCTION_RETIRED;
+ break;
+ case PMC_EV_IAP_EVENT_C5H_00H:
+ ae = CORE_AE_BRANCH_MISSES_RETIRED;
+ break;
+
+ default: /* Non architectural event. */
+ return (0);
+ }
+
+ return ((core_architectural_events & (1 << ae)) == 0);
+}
+
+static int
+iap_event_ok_on_counter(enum pmc_event pe, int ri)
+{
+ uint32_t mask;
+
+ switch (pe) {
+ /*
+ * Events valid only on counter 0.
+ */
+ case PMC_EV_IAP_EVENT_10H_00H:
+ case PMC_EV_IAP_EVENT_14H_00H:
+ case PMC_EV_IAP_EVENT_18H_00H:
+ case PMC_EV_IAP_EVENT_C1H_00H:
+ case PMC_EV_IAP_EVENT_CBH_01H:
+ case PMC_EV_IAP_EVENT_CBH_02H:
+ mask = (1 << 0);
+ break;
+
+ /*
+ * Events valid only on counter 1.
+ */
+ case PMC_EV_IAP_EVENT_11H_00H:
+ case PMC_EV_IAP_EVENT_12H_00H:
+ case PMC_EV_IAP_EVENT_13H_00H:
+ mask = (1 << 1);
+ break;
+
+ default:
+ mask = ~0; /* Any row index is ok. */
+ }
+
+ return (mask & (1 << ri));
+}
+
+static int
+iap_allocate_pmc(int cpu, int ri, struct pmc *pm,
+ const struct pmc_op_pmcallocate *a)
+{
+ int n;
+ enum pmc_event ev;
+ struct iap_event_descr *ie;
+ uint32_t c, caps, config, cpuflag, evsel, mask;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal CPU %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < core_iap_npmc,
+ ("[core,%d] illegal row-index value %d", __LINE__, ri));
+
+ /* check requested capabilities */
+ caps = a->pm_caps;
+ if ((IAP_PMC_CAPS & caps) != caps)
+ return (EPERM);
+
+ ev = pm->pm_event;
+
+ if (iap_architectural_event_is_unsupported(ev))
+ return (EOPNOTSUPP);
+
+ if (iap_event_ok_on_counter(ev, ri) == 0)
+ return (EINVAL);
+
+ /*
+ * Look for an event descriptor with matching CPU and event id
+ * fields.
+ */
+
+ switch (core_cputype) {
+ default:
+ case PMC_CPU_INTEL_ATOM:
+ cpuflag = IAP_F_CA;
+ break;
+ case PMC_CPU_INTEL_CORE:
+ cpuflag = IAP_F_CC;
+ break;
+ case PMC_CPU_INTEL_CORE2:
+ cpuflag = IAP_F_CC2;
+ break;
+ case PMC_CPU_INTEL_CORE2EXTREME:
+ cpuflag = IAP_F_CC2 | IAP_F_CC2E;
+ break;
+ case PMC_CPU_INTEL_COREI7:
+ cpuflag = IAP_F_I7;
+ break;
+ }
+
+ for (n = 0, ie = iap_events; n < niap_events; n++, ie++)
+ if (ie->iap_ev == ev && ie->iap_flags & cpuflag)
+ break;
+
+ if (n == niap_events)
+ return (EINVAL);
+
+ /*
+ * A matching event descriptor has been found, so start
+ * assembling the contents of the event select register.
+ */
+ evsel = ie->iap_evcode;
+
+ config = a->pm_md.pm_iap.pm_iap_config & ~IAP_F_CMASK;
+
+ /*
+ * If the event uses a fixed umask value, reject any umask
+ * bits set by the user.
+ */
+ if (ie->iap_flags & IAP_F_FM) {
+
+ if (IAP_UMASK(config) != 0)
+ return (EINVAL);
+
+ evsel |= (ie->iap_umask << 8);
+
+ } else {
+
+ /*
+ * Otherwise, the UMASK value needs to be taken from
+ * the MD fields of the allocation request. Reject
+ * requests that specify reserved bits.
+ */
+
+ mask = 0;
+
+ if (ie->iap_flags & IAP_M_CORE) {
+ if ((c = (config & IAP_F_CORE)) != IAP_CORE_ALL &&
+ c != IAP_CORE_THIS)
+ return (EINVAL);
+ mask |= IAP_F_CORE;
+ }
+
+ if (ie->iap_flags & IAP_M_AGENT)
+ mask |= IAP_F_AGENT;
+
+ if (ie->iap_flags & IAP_M_PREFETCH) {
+
+ if ((c = (config & IAP_F_PREFETCH)) ==
+ IAP_PREFETCH_RESERVED)
+ return (EINVAL);
+
+ mask |= IAP_F_PREFETCH;
+ }
+
+ if (ie->iap_flags & IAP_M_MESI)
+ mask |= IAP_F_MESI;
+
+ if (ie->iap_flags & IAP_M_SNOOPRESPONSE)
+ mask |= IAP_F_SNOOPRESPONSE;
+
+ if (ie->iap_flags & IAP_M_SNOOPTYPE)
+ mask |= IAP_F_SNOOPTYPE;
+
+ if (ie->iap_flags & IAP_M_TRANSITION)
+ mask |= IAP_F_TRANSITION;
+
+ /*
+ * If bits outside of the allowed set of umask bits
+ * are set, reject the request.
+ */
+ if (config & ~mask)
+ return (EINVAL);
+
+ evsel |= (config & mask);
+
+ }
+
+ /*
+ * Only Atom CPUs support the 'ANY' qualifier.
+ */
+ if (core_cputype == PMC_CPU_INTEL_ATOM)
+ evsel |= (config & IAP_ANY);
+ else if (config & IAP_ANY)
+ return (EINVAL);
+
+ if (caps & PMC_CAP_THRESHOLD)
+ evsel |= (a->pm_md.pm_iap.pm_iap_config & IAP_F_CMASK);
+ if (caps & PMC_CAP_USER)
+ evsel |= IAP_USR;
+ if (caps & PMC_CAP_SYSTEM)
+ evsel |= IAP_OS;
+ if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
+ evsel |= (IAP_OS | IAP_USR);
+ if (caps & PMC_CAP_EDGE)
+ evsel |= IAP_EDGE;
+ if (caps & PMC_CAP_INVERT)
+ evsel |= IAP_INV;
+ if (caps & PMC_CAP_INTERRUPT)
+ evsel |= IAP_INT;
+
+ pm->pm_md.pm_iap.pm_iap_evsel = evsel;
+
+ return (0);
+}
+
+static int
+iap_config_pmc(int cpu, int ri, struct pmc *pm)
+{
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal CPU %d", __LINE__, cpu));
+
+ KASSERT(ri >= 0 && ri < core_iap_npmc,
+ ("[core,%d] illegal row-index %d", __LINE__, ri));
+
+ PMCDBG(MDP,CFG,1, "iap-config cpu=%d ri=%d pm=%p", cpu, ri, pm);
+
+ KASSERT(core_pcpu[cpu] != NULL, ("[core,%d] null per-cpu %d", __LINE__,
+ cpu));
+
+ core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc = pm;
+
+ return (0);
+}
+
+static int
+iap_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
+{
+ int error;
+ struct pmc_hw *phw;
+ char iap_name[PMC_NAME_MAX];
+
+ phw = &core_pcpu[cpu]->pc_corepmcs[ri];
+
+ (void) snprintf(iap_name, sizeof(iap_name), "IAP-%d", ri);
+ if ((error = copystr(iap_name, pi->pm_name, PMC_NAME_MAX,
+ NULL)) != 0)
+ return (error);
+
+ pi->pm_class = PMC_CLASS_IAP;
+
+ if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
+ pi->pm_enabled = TRUE;
+ *ppmc = phw->phw_pmc;
+ } else {
+ pi->pm_enabled = FALSE;
+ *ppmc = NULL;
+ }
+
+ return (0);
+}
+
+static int
+iap_get_config(int cpu, int ri, struct pmc **ppm)
+{
+ *ppm = core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc;
+
+ return (0);
+}
+
+static int
+iap_get_msr(int ri, uint32_t *msr)
+{
+ KASSERT(ri >= 0 && ri < core_iap_npmc,
+ ("[iap,%d] ri %d out of range", __LINE__, ri));
+
+ *msr = ri;
+
+ return (0);
+}
+
+static int
+iap_read_pmc(int cpu, int ri, pmc_value_t *v)
+{
+ struct pmc *pm;
+ pmc_value_t tmp;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal cpu value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < core_iap_npmc,
+ ("[core,%d] illegal row-index %d", __LINE__, ri));
+
+ pm = core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc;
+
+ KASSERT(pm,
+ ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu,
+ ri));
+
+ tmp = rdpmc(ri);
+ if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+ *v = iap_perfctr_value_to_reload_count(tmp);
+ else
+ *v = tmp;
+
+ PMCDBG(MDP,REA,1, "iap-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
+ ri, *v);
+
+ return (0);
+}
+
+static int
+iap_release_pmc(int cpu, int ri, struct pmc *pm)
+{
+ (void) pm;
+
+ PMCDBG(MDP,REL,1, "iap-release cpu=%d ri=%d pm=%p", cpu, ri,
+ pm);
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal CPU value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < core_iap_npmc,
+ ("[core,%d] illegal row-index %d", __LINE__, ri));
+
+ KASSERT(core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc
+ == NULL, ("[core,%d] PHW pmc non-NULL", __LINE__));
+
+ return (0);
+}
+
+static int
+iap_start_pmc(int cpu, int ri)
+{
+ struct pmc *pm;
+ uint32_t evsel;
+ struct core_cpu *cc;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal CPU value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < core_iap_npmc,
+ ("[core,%d] illegal row-index %d", __LINE__, ri));
+
+ cc = core_pcpu[cpu];
+ pm = cc->pc_corepmcs[ri].phw_pmc;
+
+ KASSERT(pm,
+ ("[core,%d] starting cpu%d,ri%d with no pmc configured",
+ __LINE__, cpu, ri));
+
+ PMCDBG(MDP,STA,1, "iap-start cpu=%d ri=%d", cpu, ri);
+
+ evsel = pm->pm_md.pm_iap.pm_iap_evsel;
+
+ PMCDBG(MDP,STA,2, "iap-start/2 cpu=%d ri=%d evselmsr=0x%x evsel=0x%x",
+ cpu, ri, IAP_EVSEL0 + ri, evsel);
+
+ wrmsr(IAP_EVSEL0 + ri, evsel | IAP_EN);
+
+ if (core_cputype == PMC_CPU_INTEL_CORE)
+ return (0);
+
+ do {
+ cc->pc_resync = 0;
+ cc->pc_globalctrl |= (1ULL << ri);
+ wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
+ } while (cc->pc_resync != 0);
+
+ return (0);
+}
+
+static int
+iap_stop_pmc(int cpu, int ri)
+{
+ struct pmc *pm;
+ struct core_cpu *cc;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal cpu value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < core_iap_npmc,
+ ("[core,%d] illegal row index %d", __LINE__, ri));
+
+ cc = core_pcpu[cpu];
+ pm = cc->pc_corepmcs[ri].phw_pmc;
+
+ KASSERT(pm,
+ ("[core,%d] cpu%d ri%d no configured PMC to stop", __LINE__,
+ cpu, ri));
+
+ PMCDBG(MDP,STO,1, "iap-stop cpu=%d ri=%d", cpu, ri);
+
+ wrmsr(IAP_EVSEL0 + ri, 0); /* stop hw */
+
+ if (core_cputype == PMC_CPU_INTEL_CORE)
+ return (0);
+
+ do {
+ cc->pc_resync = 0;
+ cc->pc_globalctrl &= ~(1ULL << ri);
+ wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
+ } while (cc->pc_resync != 0);
+
+ return (0);
+}
+
+static int
+iap_write_pmc(int cpu, int ri, pmc_value_t v)
+{
+ struct pmc *pm;
+ struct core_cpu *cc;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[core,%d] illegal cpu value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < core_iap_npmc,
+ ("[core,%d] illegal row index %d", __LINE__, ri));
+
+ cc = core_pcpu[cpu];
+ pm = cc->pc_corepmcs[ri].phw_pmc;
+
+ KASSERT(pm,
+ ("[core,%d] cpu%d ri%d no configured PMC to stop", __LINE__,
+ cpu, ri));
+
+ PMCDBG(MDP,WRI,1, "iap-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri,
+ IAP_PMC0 + ri, v);
+
+ if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+ v = iap_reload_count_to_perfctr_value(v);
+
+ /*
+ * Write the new value to the counter. The counter will be in
+ * a stopped state when the pcd_write() entry point is called.
+ */
+
+ wrmsr(IAP_PMC0 + ri, v);
+
+ return (0);
+}
+
+
+static void
+iap_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth,
+ int flags)
+{
+ struct pmc_classdep *pcd;
+
+ KASSERT(md != NULL, ("[iap,%d] md is NULL", __LINE__));
+
+ PMCDBG(MDP,INI,1, "%s", "iap-initialize");
+
+ /* Remember the set of architectural events supported. */
+ core_architectural_events = ~flags;
+
+ pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP];
+
+ pcd->pcd_caps = IAP_PMC_CAPS;
+ pcd->pcd_class = PMC_CLASS_IAP;
+ pcd->pcd_num = npmc;
+ pcd->pcd_ri = md->pmd_npmc;
+ pcd->pcd_width = pmcwidth;
+
+ pcd->pcd_allocate_pmc = iap_allocate_pmc;
+ pcd->pcd_config_pmc = iap_config_pmc;
+ pcd->pcd_describe = iap_describe;
+ pcd->pcd_get_config = iap_get_config;
+ pcd->pcd_get_msr = iap_get_msr;
+ pcd->pcd_pcpu_fini = core_pcpu_fini;
+ pcd->pcd_pcpu_init = core_pcpu_init;
+ pcd->pcd_read_pmc = iap_read_pmc;
+ pcd->pcd_release_pmc = iap_release_pmc;
+ pcd->pcd_start_pmc = iap_start_pmc;
+ pcd->pcd_stop_pmc = iap_stop_pmc;
+ pcd->pcd_write_pmc = iap_write_pmc;
+
+ md->pmd_npmc += npmc;
+}
+
+static int
+core_intr(int cpu, struct trapframe *tf)
+{
+ pmc_value_t v;
+ struct pmc *pm;
+ struct core_cpu *cc;
+ int error, found_interrupt, ri;
+
+ PMCDBG(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf,
+ TRAPF_USERMODE(tf));
+
+ found_interrupt = 0;
+ cc = core_pcpu[cpu];
+
+ for (ri = 0; ri < core_iap_npmc; ri++) {
+
+ if ((pm = cc->pc_corepmcs[ri].phw_pmc) == NULL ||
+ !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+ continue;
+
+ if (!iap_pmc_has_overflowed(ri))
+ continue;
+
+ found_interrupt = 1;
+
+ if (pm->pm_state != PMC_STATE_RUNNING)
+ continue;
+
+ error = pmc_process_interrupt(cpu, pm, tf,
+ TRAPF_USERMODE(tf));
+
+ v = pm->pm_sc.pm_reloadcount;
+ v = iaf_reload_count_to_perfctr_value(v);
+
+ /*
+ * Stop the counter, reload it but only restart it if
+ * the PMC is not stalled.
+ */
+ wrmsr(IAP_EVSEL0 + ri, 0);
+ wrmsr(IAP_PMC0 + ri, v);
+
+ if (error)
+ continue;
+
+ wrmsr(IAP_EVSEL0 + ri,
+ pm->pm_md.pm_iap.pm_iap_evsel | IAP_EN);
+ }
+
+ if (found_interrupt)
+ pmc_x86_lapic_enable_pmc_interrupt();
+
+ atomic_add_int(found_interrupt ? &pmc_stats.pm_intr_processed :
+ &pmc_stats.pm_intr_ignored, 1);
+
+ return (found_interrupt);
+}
+
+static int
+core2_intr(int cpu, struct trapframe *tf)
+{
+ int error, found_interrupt, n;
+ uint64_t flag, intrstatus, intrenable;
+ struct pmc *pm;
+ struct core_cpu *cc;
+ pmc_value_t v;
+
+ PMCDBG(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf,
+ TRAPF_USERMODE(tf));
+
+ /*
+ * The IA_GLOBAL_STATUS (MSR 0x38E) register indicates which
+ * PMCs have a pending PMI interrupt. We take a 'snapshot' of
+ * the current set of interrupting PMCs and process these
+ * after stopping them.
+ */
+ intrstatus = rdmsr(IA_GLOBAL_STATUS);
+ intrenable = intrstatus & core_pmcmask;
+
+ PMCDBG(MDP,INT, 1, "cpu=%d intrstatus=%jx", cpu,
+ (uintmax_t) intrstatus);
+
+ found_interrupt = 0;
+ cc = core_pcpu[cpu];
+
+ KASSERT(cc != NULL, ("[core,%d] null pcpu", __LINE__));
+
+ cc->pc_globalctrl &= ~intrenable;
+ cc->pc_resync = 1; /* MSRs now potentially out of sync. */
+
+ /*
+ * Stop PMCs and clear overflow status bits.
+ */
+ wrmsr(IA_GLOBAL_CTRL, 0);
+ wrmsr(IA_GLOBAL_OVF_CTRL, intrenable |
+ IA_GLOBAL_STATUS_FLAG_OVFBUF |
+ IA_GLOBAL_STATUS_FLAG_CONDCHG);
+
+ /*
+ * Look for interrupts from fixed function PMCs.
+ */
+ for (n = 0, flag = (1ULL << IAF_OFFSET); n < core_iaf_npmc;
+ n++, flag <<= 1) {
+
+ if ((intrstatus & flag) == 0)
+ continue;
+
+ found_interrupt = 1;
+
+ pm = cc->pc_corepmcs[n + core_iaf_ri].phw_pmc;
+ if (pm == NULL || pm->pm_state != PMC_STATE_RUNNING ||
+ !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+ continue;
+
+ error = pmc_process_interrupt(cpu, pm, tf,
+ TRAPF_USERMODE(tf));
+
+ v = iaf_reload_count_to_perfctr_value(pm->pm_sc.pm_reloadcount);
+
+ /* Reload sampling count. */
+ wrmsr(IAF_CTR0 + n, v);
+
+ PMCDBG(MDP,INT, 1, "iaf-intr cpu=%d error=%d v=%jx(%jx)", cpu, error,
+ (uintmax_t) v, (uintmax_t) rdpmc(IAF_RI_TO_MSR(n)));
+
+ if (error)
+ intrenable &= ~flag;
+ }
+
+ /*
+ * Process interrupts from the programmable counters.
+ */
+ for (n = 0, flag = 1; n < core_iap_npmc; n++, flag <<= 1) {
+ if ((intrstatus & flag) == 0)
+ continue;
+
+ found_interrupt = 1;
+
+ pm = cc->pc_corepmcs[n].phw_pmc;
+ if (pm == NULL || pm->pm_state != PMC_STATE_RUNNING ||
+ !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+ continue;
+
+ error = pmc_process_interrupt(cpu, pm, tf,
+ TRAPF_USERMODE(tf));
+ if (error)
+ intrenable &= ~flag;
+
+ v = iap_reload_count_to_perfctr_value(pm->pm_sc.pm_reloadcount);
+
+ PMCDBG(MDP,INT, 1, "iap-intr cpu=%d error=%d v=%jx", cpu, error,
+ (uintmax_t) v);
+
+ /* Reload sampling count. */
+ wrmsr(IAP_PMC0 + n, v);
+ }
+
+ /*
+ * Reenable all non-stalled PMCs.
+ */
+ PMCDBG(MDP,INT, 1, "cpu=%d intrenable=%jx", cpu,
+ (uintmax_t) intrenable);
+
+ cc->pc_globalctrl |= intrenable;
+
+ wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
+
+ PMCDBG(MDP,INT, 1, "cpu=%d fixedctrl=%jx globalctrl=%jx status=%jx "
+ "ovf=%jx", cpu, (uintmax_t) rdmsr(IAF_CTRL),
+ (uintmax_t) rdmsr(IA_GLOBAL_CTRL),
+ (uintmax_t) rdmsr(IA_GLOBAL_STATUS),
+ (uintmax_t) rdmsr(IA_GLOBAL_OVF_CTRL));
+
+ if (found_interrupt)
+ pmc_x86_lapic_enable_pmc_interrupt();
+
+ atomic_add_int(found_interrupt ? &pmc_stats.pm_intr_processed :
+ &pmc_stats.pm_intr_ignored, 1);
+
+ return (found_interrupt);
+}
+
+int
+pmc_core_initialize(struct pmc_mdep *md, int maxcpu)
+{
+ int cpuid[CORE_CPUID_REQUEST_SIZE];
+ int ipa_version, flags, nflags;
+
+ do_cpuid(CORE_CPUID_REQUEST, cpuid);
+
+ ipa_version = cpuid[CORE_CPUID_EAX] & 0xFF;
+
+ PMCDBG(MDP,INI,1,"core-init cputype=%d ncpu=%d ipa-version=%d",
+ md->pmd_cputype, maxcpu, ipa_version);
+
+ if (ipa_version < 1 || ipa_version > 3) /* Unknown PMC architecture. */
+ return (EPROGMISMATCH);
+
+ core_cputype = md->pmd_cputype;
+
+ core_pmcmask = 0;
+
+ /*
+ * Initialize programmable counters.
+ */
+ KASSERT(ipa_version >= 1,
+ ("[core,%d] ipa_version %d too small", __LINE__, ipa_version));
+
+ core_iap_npmc = (cpuid[CORE_CPUID_EAX] >> 8) & 0xFF;
+ core_iap_width = (cpuid[CORE_CPUID_EAX] >> 16) & 0xFF;
+
+ core_pmcmask |= ((1ULL << core_iap_npmc) - 1);
+
+ nflags = (cpuid[CORE_CPUID_EAX] >> 24) & 0xFF;
+ flags = cpuid[CORE_CPUID_EBX] & ((1 << nflags) - 1);
+
+ iap_initialize(md, maxcpu, core_iap_npmc, core_iap_width, flags);
+
+ /*
+ * Initialize fixed function counters, if present.
+ */
+ if (core_cputype != PMC_CPU_INTEL_CORE) {
+ KASSERT(ipa_version >= 2,
+ ("[core,%d] ipa_version %d too small", __LINE__,
+ ipa_version));
+
+ core_iaf_ri = core_iap_npmc;
+ core_iaf_npmc = cpuid[CORE_CPUID_EDX] & 0x1F;
+ core_iaf_width = (cpuid[CORE_CPUID_EDX] >> 5) & 0xFF;
+
+ iaf_initialize(md, maxcpu, core_iaf_npmc, core_iaf_width);
+
+ core_pmcmask |= ((1ULL << core_iaf_npmc) - 1) <<
+ IAF_OFFSET;
+
+ }
+
+ PMCDBG(MDP,INI,1,"core-init pmcmask=0x%jx iafri=%d", core_pmcmask,
+ core_iaf_ri);
+
+ core_pcpu = malloc(sizeof(struct core_cpu **) * maxcpu, M_PMC,
+ M_ZERO | M_WAITOK);
+
+ /*
+ * Choose the appropriate interrupt handler.
+ */
+ if (ipa_version == 1)
+ md->pmd_intr = core_intr;
+ else
+ md->pmd_intr = core2_intr;
+
+ md->pmd_pcpu_fini = NULL;
+ md->pmd_pcpu_init = NULL;
+
+ return (0);
+}
+
+void
+pmc_core_finalize(struct pmc_mdep *md)
+{
+ PMCDBG(MDP,INI,1, "%s", "core-finalize");
+
+ free(core_pcpu, M_PMC);
+ core_pcpu = NULL;
+}
diff --git a/sys/dev/hwpmc/hwpmc_core.h b/sys/dev/hwpmc/hwpmc_core.h
new file mode 100644
index 000000000000..0c4ee5b38895
--- /dev/null
+++ b/sys/dev/hwpmc/hwpmc_core.h
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_HWPMC_CORE_H_
+#define _DEV_HWPMC_CORE_H_ 1
+
+/*
+ * Fixed-function PMCs.
+ */
+struct pmc_md_iaf_op_pmcallocate {
+ uint16_t pm_iaf_flags; /* additional flags */
+};
+
+#define IAF_OS 0x1
+#define IAF_USR 0x2
+#define IAF_ANY 0x4
+#define IAF_PMI 0x8
+
+/*
+ * Programmable PMCs.
+ */
+struct pmc_md_iap_op_pmcallocate {
+ uint32_t pm_iap_config;
+};
+
+#define IAP_EVSEL(C) ((C) & 0xFF)
+#define IAP_UMASK(C) ((C) & 0xFF00)
+#define IAP_USR (1 << 16)
+#define IAP_OS (1 << 17)
+#define IAP_EDGE (1 << 18)
+#define IAP_INT (1 << 20)
+#define IAP_ANY (1 << 21)
+#define IAP_EN (1 << 22)
+#define IAP_INV (1 << 23)
+#define IAP_CMASK(C) (((C) & 0xFF) << 24)
+
+#ifdef _KERNEL
+
+/*
+ * Fixed-function counters.
+ */
+#define IAF_MASK 0xF
+
+#define IAF_CTR0 0x309
+#define IAF_CTR1 0x30A
+#define IAF_CTR2 0x30B
+
+#define IAF_OFFSET 32
+#define IAF_CTRL 0x38D
+
+/*
+ * Programmable counters.
+ */
+#define IAP_PMC0 0x0C1
+#define IAP_PMC1 0x0C2
+
+#define IAP_EVSEL0 0x186
+#define IAP_EVSEL1 0x187
+
+/*
+ * Simplified programming interface in Intel Performance Architecture
+ * v2 and later.
+ */
+#define IA_GLOBAL_STATUS 0x38E
+#define IA_GLOBAL_CTRL 0x38F
+#define IA_GLOBAL_OVF_CTRL 0x390
+
+#define IA_GLOBAL_STATUS_FLAG_CONDCHG (1ULL << 63)
+#define IA_GLOBAL_STATUS_FLAG_OVFBUF (1ULL << 62)
+
+struct pmc_md_iaf_pmc {
+ uint64_t pm_iaf_ctrl;
+};
+
+struct pmc_md_iap_pmc {
+ uint32_t pm_iap_evsel;
+};
+
+/*
+ * Prototypes.
+ */
+
+int pmc_core_initialize(struct pmc_mdep *_md, int _maxcpu);
+void pmc_core_finalize(struct pmc_mdep *_md);
+
+void pmc_core_mark_started(int _cpu, int _pmc);
+
+int pmc_iaf_initialize(struct pmc_mdep *_md, int _maxcpu, int _npmc, int _width);
+void pmc_iaf_finalize(struct pmc_mdep *_md);
+
+int pmc_iap_initialize(struct pmc_mdep *_md, int _maxcpu, int _npmc, int _width,
+ int _flags);
+void pmc_iap_finalize(struct pmc_mdep *_md);
+
+#endif /* _KERNEL */
+#endif /* _DEV_HWPMC_CORE_H */
diff --git a/sys/dev/hwpmc/hwpmc_ia64.c b/sys/dev/hwpmc/hwpmc_ia64.c
index af905b66924e..ce1caf69e108 100644
--- a/sys/dev/hwpmc/hwpmc_ia64.c
+++ b/sys/dev/hwpmc/hwpmc_ia64.c
@@ -38,3 +38,29 @@ pmc_md_initialize()
{
return NULL;
}
+
+void
+pmc_md_finalize(struct pmc_mdep *md)
+{
+ (void) md;
+}
+
+int
+pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
+ struct trapframe *tf)
+{
+ (void) cc;
+ (void) maxsamples;
+ (void) tf;
+ return (0);
+}
+
+int
+pmc_save_user_callchain(uintptr_t *cc, int maxsamples,
+ struct trapframe *tf)
+{
+ (void) cc;
+ (void) maxsamples;
+ (void) tf;
+ return (0);
+}
diff --git a/sys/dev/hwpmc/hwpmc_intel.c b/sys/dev/hwpmc/hwpmc_intel.c
new file mode 100644
index 000000000000..e7998e821e2d
--- /dev/null
+++ b/sys/dev/hwpmc/hwpmc_intel.c
@@ -0,0 +1,269 @@
+/*-
+ * Copyright (c) 2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Common code for handling Intel CPUs.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/pmc.h>
+#include <sys/pmckern.h>
+#include <sys/systm.h>
+
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+#include <machine/specialreg.h>
+
+static int
+intel_switch_in(struct pmc_cpu *pc, struct pmc_process *pp)
+{
+ (void) pc;
+
+ PMCDBG(MDP,SWI,1, "pc=%p pp=%p enable-msr=%d", pc, pp,
+ pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS);
+
+ /* allow the RDPMC instruction if needed */
+ if (pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS)
+ load_cr4(rcr4() | CR4_PCE);
+
+ PMCDBG(MDP,SWI,1, "cr4=0x%jx", (uintmax_t) rcr4());
+
+ return 0;
+}
+
+static int
+intel_switch_out(struct pmc_cpu *pc, struct pmc_process *pp)
+{
+ (void) pc;
+ (void) pp; /* can be NULL */
+
+ PMCDBG(MDP,SWO,1, "pc=%p pp=%p cr4=0x%jx", pc, pp,
+ (uintmax_t) rcr4());
+
+ /* always turn off the RDPMC instruction */
+ load_cr4(rcr4() & ~CR4_PCE);
+
+ return 0;
+}
+
+struct pmc_mdep *
+pmc_intel_initialize(void)
+{
+ struct pmc_mdep *pmc_mdep;
+ enum pmc_cputype cputype;
+ int error, model, nclasses, ncpus;
+
+ KASSERT(strcmp(cpu_vendor, "GenuineIntel") == 0,
+ ("[intel,%d] Initializing non-intel processor", __LINE__));
+
+ PMCDBG(MDP,INI,0, "intel-initialize cpuid=0x%x", cpu_id);
+
+ cputype = -1;
+ nclasses = 2;
+
+ model = ((cpu_id & 0xF0000) >> 12) | ((cpu_id & 0xF0) >> 4);
+
+ switch (cpu_id & 0xF00) {
+#if defined(__i386__)
+ case 0x500: /* Pentium family processors */
+ cputype = PMC_CPU_INTEL_P5;
+ break;
+#endif
+ case 0x600: /* Pentium Pro, Celeron, Pentium II & III */
+ switch (model) {
+#if defined(__i386__)
+ case 0x1:
+ cputype = PMC_CPU_INTEL_P6;
+ break;
+ case 0x3: case 0x5:
+ cputype = PMC_CPU_INTEL_PII;
+ break;
+ case 0x6: case 0x16:
+ cputype = PMC_CPU_INTEL_CL;
+ break;
+ case 0x7: case 0x8: case 0xA: case 0xB:
+ cputype = PMC_CPU_INTEL_PIII;
+ break;
+ case 0x9: case 0xD:
+ cputype = PMC_CPU_INTEL_PM;
+ break;
+#endif
+ case 0xE:
+ cputype = PMC_CPU_INTEL_CORE;
+ break;
+ case 0xF:
+ cputype = PMC_CPU_INTEL_CORE2;
+ nclasses = 3;
+ break;
+ case 0x17:
+ cputype = PMC_CPU_INTEL_CORE2EXTREME;
+ nclasses = 3;
+ break;
+ case 0x1C: /* Per Intel document 320047-002. */
+ cputype = PMC_CPU_INTEL_ATOM;
+ nclasses = 3;
+ break;
+ case 0x1A:
+ cputype = PMC_CPU_INTEL_COREI7;
+ nclasses = 3;
+ break;
+ }
+ break;
+#if defined(__i386__) || defined(__amd64__)
+ case 0xF00: /* P4 */
+ if (model >= 0 && model <= 6) /* known models */
+ cputype = PMC_CPU_INTEL_PIV;
+ break;
+ }
+#endif
+
+ if ((int) cputype == -1) {
+ printf("pmc: Unknown Intel CPU.\n");
+ return (NULL);
+ }
+
+ pmc_mdep = malloc(sizeof(struct pmc_mdep) + nclasses *
+ sizeof(struct pmc_classdep), M_PMC, M_WAITOK|M_ZERO);
+
+ pmc_mdep->pmd_cputype = cputype;
+ pmc_mdep->pmd_nclass = nclasses;
+
+ pmc_mdep->pmd_switch_in = intel_switch_in;
+ pmc_mdep->pmd_switch_out = intel_switch_out;
+
+ ncpus = pmc_cpu_max();
+
+ error = pmc_tsc_initialize(pmc_mdep, ncpus);
+ if (error)
+ goto error;
+
+ switch (cputype) {
+#if defined(__i386__) || defined(__amd64__)
+ /*
+ * Intel Core, Core 2 and Atom processors.
+ */
+ case PMC_CPU_INTEL_ATOM:
+ case PMC_CPU_INTEL_CORE:
+ case PMC_CPU_INTEL_CORE2:
+ case PMC_CPU_INTEL_CORE2EXTREME:
+ case PMC_CPU_INTEL_COREI7:
+ error = pmc_core_initialize(pmc_mdep, ncpus);
+ break;
+
+ /*
+ * Intel Pentium 4 Processors, and P4/EMT64 processors.
+ */
+
+ case PMC_CPU_INTEL_PIV:
+ error = pmc_p4_initialize(pmc_mdep, ncpus);
+
+ KASSERT(pmc_mdep->pmd_npmc == TSC_NPMCS + P4_NPMCS,
+ ("[intel,%d] incorrect npmc count %d", __LINE__,
+ pmc_mdep->pmd_npmc));
+ break;
+#endif
+
+#if defined(__i386__)
+ /*
+ * P6 Family Processors
+ */
+
+ case PMC_CPU_INTEL_P6:
+ case PMC_CPU_INTEL_CL:
+ case PMC_CPU_INTEL_PII:
+ case PMC_CPU_INTEL_PIII:
+ case PMC_CPU_INTEL_PM:
+ error = pmc_p6_initialize(pmc_mdep, ncpus);
+
+ KASSERT(pmc_mdep->pmd_npmc == TSC_NPMCS + P6_NPMCS,
+ ("[intel,%d] incorrect npmc count %d", __LINE__,
+ pmc_mdep->pmd_npmc));
+ break;
+
+ /*
+ * Intel Pentium PMCs.
+ */
+
+ case PMC_CPU_INTEL_P5:
+ error = pmc_p5_initialize(pmc_mdep, ncpus);
+
+ KASSERT(pmc_mdep->pmd_npmc == TSC_NPMCS + PENTIUM_NPMCS,
+ ("[intel,%d] incorrect npmc count %d", __LINE__,
+ pmc_mdep->pmd_npmc));
+ break;
+#endif
+
+ default:
+ KASSERT(0, ("[intel,%d] Unknown CPU type", __LINE__));
+ }
+
+
+ error:
+ if (error) {
+ free(pmc_mdep, M_PMC);
+ pmc_mdep = NULL;
+ }
+
+ return (pmc_mdep);
+}
+
+void
+pmc_intel_finalize(struct pmc_mdep *md)
+{
+ pmc_tsc_finalize(md);
+
+ switch (md->pmd_cputype) {
+#if defined(__i386__) || defined(__amd64__)
+ case PMC_CPU_INTEL_ATOM:
+ case PMC_CPU_INTEL_CORE:
+ case PMC_CPU_INTEL_CORE2:
+ case PMC_CPU_INTEL_CORE2EXTREME:
+ pmc_core_finalize(md);
+ break;
+
+ case PMC_CPU_INTEL_PIV:
+ pmc_p4_finalize(md);
+ break;
+#endif
+#if defined(__i386__)
+ case PMC_CPU_INTEL_P6:
+ case PMC_CPU_INTEL_CL:
+ case PMC_CPU_INTEL_PII:
+ case PMC_CPU_INTEL_PIII:
+ case PMC_CPU_INTEL_PM:
+ pmc_p6_finalize(md);
+ break;
+ case PMC_CPU_INTEL_P5:
+ pmc_p5_finalize(md);
+ break;
+#endif
+ default:
+ KASSERT(0, ("[intel,%d] unknown CPU type", __LINE__));
+ }
+}
diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c
index 5af555c46df8..bed47366da05 100644
--- a/sys/dev/hwpmc/hwpmc_logging.c
+++ b/sys/dev/hwpmc/hwpmc_logging.c
@@ -1,7 +1,11 @@
/*-
- * Copyright (c) 2005 Joseph Koshy
+ * Copyright (c) 2005-2007 Joseph Koshy
+ * Copyright (c) 2007 The FreeBSD Foundation
* All rights reserved.
*
+ * Portions of this software were developed by A. Joseph Koshy under
+ * sponsorship from the FreeBSD Foundation and Google, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -64,7 +68,6 @@ TUNABLE_INT(PMC_SYSCTL_NAME_PREFIX "logbuffersize", &pmclog_buffer_size);
SYSCTL_INT(_kern_hwpmc, OID_AUTO, logbuffersize, CTLFLAG_TUN|CTLFLAG_RD,
&pmclog_buffer_size, 0, "size of log buffers in kilobytes");
-
/*
* kern.hwpmc.nbuffer -- number of global log buffers
*/
@@ -96,7 +99,6 @@ static struct mtx pmc_kthread_mtx; /* sleep lock */
/*
* Log file record constructors.
*/
-
#define _PMCLOG_TO_HEADER(T,L) \
((PMCLOG_HEADER_MAGIC << 24) | \
(PMCLOG_TYPE_ ## T << 16) | \
@@ -135,6 +137,8 @@ static struct mtx pmc_kthread_mtx; /* sleep lock */
* Assertions about the log file format.
*/
+CTASSERT(sizeof(struct pmclog_callchain) == 6*4 +
+ PMC_CALLCHAIN_DEPTH_MAX*sizeof(uintfptr_t));
CTASSERT(sizeof(struct pmclog_closelog) == 3*4);
CTASSERT(sizeof(struct pmclog_dropnotify) == 3*4);
CTASSERT(sizeof(struct pmclog_map_in) == PATH_MAX +
@@ -195,7 +199,7 @@ pmclog_get_buffer(struct pmc_owner *po)
mtx_assert(&po->po_mtx, MA_OWNED);
KASSERT(po->po_curbuf == NULL,
- ("[pmc,%d] po=%p current buffer still valid", __LINE__, po));
+ ("[pmclog,%d] po=%p current buffer still valid", __LINE__, po));
mtx_lock_spin(&pmc_bufferlist_mtx);
if ((plb = TAILQ_FIRST(&pmc_bufferlist)) != NULL)
@@ -208,7 +212,7 @@ pmclog_get_buffer(struct pmc_owner *po)
if (plb)
KASSERT(plb->plb_ptr == plb->plb_base &&
plb->plb_base < plb->plb_fence,
- ("[pmc,%d] po=%p buffer invariants: ptr=%p "
+ ("[pmclog,%d] po=%p buffer invariants: ptr=%p "
"base=%p fence=%p", __LINE__, po, plb->plb_ptr,
plb->plb_base, plb->plb_fence));
#endif
@@ -220,7 +224,7 @@ pmclog_get_buffer(struct pmc_owner *po)
if (plb == NULL)
atomic_add_int(&pmc_stats.pm_buffer_requests_failed, 1);
- return plb ? 0 : ENOMEM;
+ return (plb ? 0 : ENOMEM);
}
/*
@@ -252,7 +256,7 @@ pmclog_loop(void *arg)
PMCDBG(LOG,INI,1, "po=%p kt=%p", po, po->po_kthread);
KASSERT(po->po_kthread == curthread->td_proc,
- ("[pmc,%d] proc mismatch po=%p po/kt=%p curproc=%p", __LINE__,
+ ("[pmclog,%d] proc mismatch po=%p po/kt=%p curproc=%p", __LINE__,
po, po->po_kthread, curthread->td_proc));
lb = NULL;
@@ -277,7 +281,11 @@ pmclog_loop(void *arg)
if ((lb = TAILQ_FIRST(&po->po_logbuffers)) == NULL) {
mtx_unlock_spin(&po->po_mtx);
- /* wakeup any processes waiting for a FLUSH */
+ /*
+ * Wakeup the thread waiting for the
+ * PMC_OP_FLUSHLOG request to
+ * complete.
+ */
if (po->po_flags & PMC_PO_IN_FLUSH) {
po->po_flags &= ~PMC_PO_IN_FLUSH;
wakeup_one(po->po_kthread);
@@ -373,10 +381,10 @@ static void
pmclog_release(struct pmc_owner *po)
{
KASSERT(po->po_curbuf->plb_ptr >= po->po_curbuf->plb_base,
- ("[pmc,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
+ ("[pmclog,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base));
KASSERT(po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence,
- ("[pmc,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
+ ("[pmclog,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_fence));
/* schedule an I/O if we've filled a buffer */
@@ -415,15 +423,15 @@ pmclog_reserve(struct pmc_owner *po, int length)
if (po->po_curbuf == NULL)
if (pmclog_get_buffer(po) != 0) {
mtx_unlock_spin(&po->po_mtx);
- return NULL;
+ return (NULL);
}
KASSERT(po->po_curbuf != NULL,
- ("[pmc,%d] po=%p no current buffer", __LINE__, po));
+ ("[pmclog,%d] po=%p no current buffer", __LINE__, po));
KASSERT(po->po_curbuf->plb_ptr >= po->po_curbuf->plb_base &&
po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence,
- ("[pmc,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
+ ("[pmclog,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
__LINE__, po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base,
po->po_curbuf->plb_fence));
@@ -431,7 +439,7 @@ pmclog_reserve(struct pmc_owner *po, int length)
newptr = oldptr + length;
KASSERT(oldptr != (uintptr_t) NULL,
- ("[pmc,%d] po=%p Null log buffer pointer", __LINE__, po));
+ ("[pmclog,%d] po=%p Null log buffer pointer", __LINE__, po));
/*
* If we have space in the current buffer, return a pointer to
@@ -450,18 +458,18 @@ pmclog_reserve(struct pmc_owner *po, int length)
if (pmclog_get_buffer(po) != 0) {
mtx_unlock_spin(&po->po_mtx);
- return NULL;
+ return (NULL);
}
KASSERT(po->po_curbuf != NULL,
- ("[pmc,%d] po=%p no current buffer", __LINE__, po));
+ ("[pmclog,%d] po=%p no current buffer", __LINE__, po));
KASSERT(po->po_curbuf->plb_ptr != NULL,
- ("[pmc,%d] null return from pmc_get_log_buffer", __LINE__));
+ ("[pmclog,%d] null return from pmc_get_log_buffer", __LINE__));
KASSERT(po->po_curbuf->plb_ptr == po->po_curbuf->plb_base &&
po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence,
- ("[pmc,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
+ ("[pmclog,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
__LINE__, po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base,
po->po_curbuf->plb_fence));
@@ -473,7 +481,7 @@ pmclog_reserve(struct pmc_owner *po, int length)
getnanotime(&ts); /* fill in the timestamp */
*lh++ = ts.tv_sec & 0xFFFFFFFF;
*lh++ = ts.tv_nsec & 0xFFFFFFF;
- return (uint32_t *) oldptr;
+ return ((uint32_t *) oldptr);
}
/*
@@ -486,13 +494,13 @@ static void
pmclog_schedule_io(struct pmc_owner *po)
{
KASSERT(po->po_curbuf != NULL,
- ("[pmc,%d] schedule_io with null buffer po=%p", __LINE__, po));
+ ("[pmclog,%d] schedule_io with null buffer po=%p", __LINE__, po));
KASSERT(po->po_curbuf->plb_ptr >= po->po_curbuf->plb_base,
- ("[pmc,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
+ ("[pmclog,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base));
KASSERT(po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence,
- ("[pmc,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
+ ("[pmclog,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_fence));
PMCDBG(LOG,SIO, 1, "po=%p", po);
@@ -539,7 +547,7 @@ pmclog_stop_kthread(struct pmc_owner *po)
*/
int
-pmclog_configure_log(struct pmc_owner *po, int logfd)
+pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
{
int error;
struct proc *p;
@@ -550,13 +558,13 @@ pmclog_configure_log(struct pmc_owner *po, int logfd)
/* return EBUSY if a log file was already present */
if (po->po_flags & PMC_PO_OWNS_LOGFILE)
- return EBUSY;
+ return (EBUSY);
KASSERT(po->po_kthread == NULL,
- ("[pmc,%d] po=%p kthread (%p) already present", __LINE__, po,
+ ("[pmclog,%d] po=%p kthread (%p) already present", __LINE__, po,
po->po_kthread));
KASSERT(po->po_file == NULL,
- ("[pmc,%d] po=%p file (%p) already present", __LINE__, po,
+ ("[pmclog,%d] po=%p file (%p) already present", __LINE__, po,
po->po_file));
/* get a reference to the file state */
@@ -583,7 +591,7 @@ pmclog_configure_log(struct pmc_owner *po, int logfd)
PMCLOG_EMIT32(md->pmd_cputype);
PMCLOG_DESPATCH(po);
- return 0;
+ return (0);
error:
/* shutdown the thread */
@@ -592,15 +600,15 @@ pmclog_configure_log(struct pmc_owner *po, int logfd)
pmclog_stop_kthread(po);
mtx_unlock(&pmc_kthread_mtx);
- KASSERT(po->po_kthread == NULL, ("[pmc,%d] po=%p kthread not stopped",
- __LINE__, po));
+ KASSERT(po->po_kthread == NULL, ("[pmclog,%d] po=%p kthread not "
+ "stopped", __LINE__, po));
if (po->po_file)
(void) fdrop(po->po_file, curthread);
po->po_file = NULL; /* clear file and error state */
po->po_error = 0;
- return error;
+ return (error);
}
@@ -618,12 +626,12 @@ pmclog_deconfigure_log(struct pmc_owner *po)
PMCDBG(LOG,CFG,1, "de-config po=%p", po);
if ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0)
- return EINVAL;
+ return (EINVAL);
KASSERT(po->po_sscount == 0,
- ("[pmc,%d] po=%p still owning SS PMCs", __LINE__, po));
+ ("[pmclog,%d] po=%p still owning SS PMCs", __LINE__, po));
KASSERT(po->po_file != NULL,
- ("[pmc,%d] po=%p no log file", __LINE__, po));
+ ("[pmclog,%d] po=%p no log file", __LINE__, po));
/* stop the kthread, this will reset the 'OWNS_LOGFILE' flag */
mtx_lock(&pmc_kthread_mtx);
@@ -632,7 +640,7 @@ pmclog_deconfigure_log(struct pmc_owner *po)
mtx_unlock(&pmc_kthread_mtx);
KASSERT(po->po_kthread == NULL,
- ("[pmc,%d] po=%p kthread not stopped", __LINE__, po));
+ ("[pmclog,%d] po=%p kthread not stopped", __LINE__, po));
/* return all queued log buffers to the global pool */
while ((lb = TAILQ_FIRST(&po->po_logbuffers)) != NULL) {
@@ -656,7 +664,7 @@ pmclog_deconfigure_log(struct pmc_owner *po)
po->po_file = NULL;
po->po_error = 0;
- return error;
+ return (error);
}
/*
@@ -675,7 +683,7 @@ pmclog_flush(struct pmc_owner *po)
* return that.
*/
if (po->po_error)
- return po->po_error;
+ return (po->po_error);
error = 0;
@@ -701,18 +709,39 @@ pmclog_flush(struct pmc_owner *po)
po->po_flags |= PMC_PO_IN_FLUSH; /* ask for a wakeup */
error = msleep(po->po_kthread, &pmc_kthread_mtx, PWAIT,
"pmcflush", 0);
+ if (error == 0)
+ error = po->po_error;
}
error:
mtx_unlock(&pmc_kthread_mtx);
- return error;
+ return (error);
}
-/*
- * Send a 'close log' event to the log file.
- */
+void
+pmclog_process_callchain(struct pmc *pm, struct pmc_sample *ps)
+{
+ int n, recordlen;
+ uint32_t flags;
+ struct pmc_owner *po;
+
+ PMCDBG(LOG,SAM,1,"pm=%p pid=%d n=%d", pm, ps->ps_pid,
+ ps->ps_nsamples);
+
+ recordlen = offsetof(struct pmclog_callchain, pl_pc) +
+ ps->ps_nsamples * sizeof(uintfptr_t);
+ po = pm->pm_owner;
+ flags = PMC_CALLCHAIN_TO_CPUFLAGS(ps->ps_cpu,ps->ps_flags);
+ PMCLOG_RESERVE(po, CALLCHAIN, recordlen);
+ PMCLOG_EMIT32(ps->ps_pid);
+ PMCLOG_EMIT32(pm->pm_id);
+ PMCLOG_EMIT32(flags);
+ for (n = 0; n < ps->ps_nsamples; n++)
+ PMCLOG_EMITADDR(ps->ps_pc[n]);
+ PMCLOG_DESPATCH(po);
+}
void
pmclog_process_closelog(struct pmc_owner *po)
@@ -761,24 +790,6 @@ pmclog_process_map_out(struct pmc_owner *po, pid_t pid, uintfptr_t start,
}
void
-pmclog_process_pcsample(struct pmc *pm, struct pmc_sample *ps)
-{
- struct pmc_owner *po;
-
- PMCDBG(LOG,SAM,1,"pm=%p pid=%d pc=%p", pm, ps->ps_pid,
- (void *) ps->ps_pc);
-
- po = pm->pm_owner;
-
- PMCLOG_RESERVE(po, PCSAMPLE, sizeof(struct pmclog_pcsample));
- PMCLOG_EMIT32(ps->ps_pid);
- PMCLOG_EMITADDR(ps->ps_pc);
- PMCLOG_EMIT32(pm->pm_id);
- PMCLOG_EMIT32(ps->ps_usermode);
- PMCLOG_DESPATCH(po);
-}
-
-void
pmclog_process_pmcallocate(struct pmc *pm)
{
struct pmc_owner *po;
@@ -939,7 +950,7 @@ pmclog_process_userlog(struct pmc_owner *po, struct pmc_op_writelog *wl)
PMCLOG_DESPATCH(po);
error:
- return error;
+ return (error);
}
/*
@@ -955,8 +966,8 @@ pmclog_initialize()
struct pmclog_buffer *plb;
if (pmclog_buffer_size <= 0) {
- (void) printf("hwpmc: tunable logbuffersize=%d must be greater "
- "than zero.\n", pmclog_buffer_size);
+ (void) printf("hwpmc: tunable logbuffersize=%d must be "
+ "greater than zero.\n", pmclog_buffer_size);
pmclog_buffer_size = PMC_LOG_BUFFER_SIZE;
}
@@ -968,8 +979,8 @@ pmclog_initialize()
/* create global pool of log buffers */
for (n = 0; n < pmc_nlogbuffers; n++) {
- MALLOC(plb, struct pmclog_buffer *, 1024 * pmclog_buffer_size,
- M_PMC, M_ZERO|M_WAITOK);
+ plb = malloc(1024 * pmclog_buffer_size, M_PMC,
+ M_WAITOK|M_ZERO);
PMCLOG_INIT_BUFFER_DESCRIPTOR(plb);
TAILQ_INSERT_HEAD(&pmc_bufferlist, plb, plb_next);
}
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index ee42521d63d8..044163d6be68 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -1,7 +1,11 @@
/*-
- * Copyright (c) 2003-2006 Joseph Koshy
+ * Copyright (c) 2003-2008 Joseph Koshy
+ * Copyright (c) 2007 The FreeBSD Foundation
* All rights reserved.
*
+ * Portions of this software were developed by A. Joseph Koshy under
+ * sponsorship from the FreeBSD Foundation and Google, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -94,8 +98,8 @@ static int *pmc_pmcdisp; /* PMC row dispositions */
KASSERT(pmc_pmcdisp[(R)] <= 0, ("[pmc,%d] row disposition error", \
__LINE__)); \
atomic_add_int(&pmc_pmcdisp[(R)], -1); \
- KASSERT(pmc_pmcdisp[(R)] >= (-mp_ncpus), ("[pmc,%d] row " \
- "disposition error", __LINE__)); \
+ KASSERT(pmc_pmcdisp[(R)] >= (-pmc_cpu_max_active()), \
+ ("[pmc,%d] row disposition error", __LINE__)); \
} while (0)
#define PMC_UNMARK_ROW_STANDALONE(R) do { \
@@ -124,7 +128,7 @@ static eventhandler_tag pmc_exit_tag, pmc_fork_tag;
struct pmc_op_getdriverstats pmc_stats;
/* Machine/processor dependent operations */
-struct pmc_mdep *md;
+static struct pmc_mdep *md;
/*
* Hash tables mapping owner processes and target threads to PMCs.
@@ -150,6 +154,11 @@ static LIST_HEAD(, pmc_owner) pmc_ss_owners;
/*
+ * A map of row indices to classdep structures.
+ */
+static struct pmc_classdep **pmc_rowindex_to_classdep;
+
+/*
* Prototypes
*/
@@ -166,6 +175,7 @@ static int pmc_attach_one_process(struct proc *p, struct pmc *pm);
static int pmc_can_allocate_rowindex(struct proc *p, unsigned int ri,
int cpu);
static int pmc_can_attach(struct pmc *pm, struct proc *p);
+static void pmc_capture_user_callchain(int cpu, struct trapframe *tf);
static void pmc_cleanup(void);
static int pmc_detach_process(struct proc *p, struct pmc *pm);
static int pmc_detach_one_process(struct proc *p, struct pmc *pm,
@@ -180,6 +190,9 @@ static struct pmc_process *pmc_find_process_descriptor(struct proc *p,
static void pmc_force_context_switch(void);
static void pmc_link_target_process(struct pmc *pm,
struct pmc_process *pp);
+static void pmc_log_all_process_mappings(struct pmc_owner *po);
+static void pmc_log_kernel_mappings(struct pmc *pm);
+static void pmc_log_process_mappings(struct pmc_owner *po, struct proc *p);
static void pmc_maybe_remove_owner(struct pmc_owner *po);
static void pmc_process_csw_in(struct thread *td);
static void pmc_process_csw_out(struct thread *td);
@@ -205,6 +218,11 @@ static void pmc_unlink_target_process(struct pmc *pmc,
SYSCTL_NODE(_kern, OID_AUTO, hwpmc, CTLFLAG_RW, 0, "HWPMC parameters");
+static int pmc_callchaindepth = PMC_CALLCHAIN_DEPTH;
+TUNABLE_INT(PMC_SYSCTL_NAME_PREFIX "callchaindepth", &pmc_callchaindepth);
+SYSCTL_INT(_kern_hwpmc, OID_AUTO, callchaindepth, CTLFLAG_TUN|CTLFLAG_RD,
+ &pmc_callchaindepth, 0, "depth of call chain records");
+
#ifdef DEBUG
struct pmc_debugflags pmc_debugflags = PMC_DEBUG_DEFAULT_FLAGS;
char pmc_debugstr[PMC_DEBUG_STRSIZE];
@@ -226,7 +244,7 @@ SYSCTL_INT(_kern_hwpmc, OID_AUTO, hashsize, CTLFLAG_TUN|CTLFLAG_RD,
&pmc_hashsize, 0, "rows in hash tables");
/*
- * kern.hwpmc.nsamples --- number of PC samples per CPU
+ * kern.hwpmc.nsamples --- number of PC samples/callchain stacks per CPU
*/
static int pmc_nsamples = PMC_NSAMPLES;
@@ -234,6 +252,7 @@ TUNABLE_INT(PMC_SYSCTL_NAME_PREFIX "nsamples", &pmc_nsamples);
SYSCTL_INT(_kern_hwpmc, OID_AUTO, nsamples, CTLFLAG_TUN|CTLFLAG_RD,
&pmc_nsamples, 0, "number of PC samples per CPU");
+
/*
* kern.hwpmc.mtxpoolsize -- number of mutexes in the mutex pool.
*/
@@ -450,7 +469,7 @@ pmc_debugflags_sysctl_handler(SYSCTL_HANDLER_ARGS)
(void) arg1; (void) arg2; /* unused parameters */
n = sizeof(pmc_debugstr);
- MALLOC(newstr, char *, n, M_PMC, M_ZERO|M_WAITOK);
+ newstr = malloc(n, M_PMC, M_WAITOK|M_ZERO);
(void) strlcpy(newstr, pmc_debugstr, n);
error = sysctl_handle_string(oidp, newstr, n, req);
@@ -470,6 +489,33 @@ pmc_debugflags_sysctl_handler(SYSCTL_HANDLER_ARGS)
#endif
/*
+ * Map a row index to a classdep structure and return the adjusted row
+ * index for the PMC class index.
+ */
+static struct pmc_classdep *
+pmc_ri_to_classdep(struct pmc_mdep *md, int ri, int *adjri)
+{
+ struct pmc_classdep *pcd;
+
+ (void) md;
+
+ KASSERT(ri >= 0 && ri < md->pmd_npmc,
+ ("[pmc,%d] illegal row-index %d", __LINE__, ri));
+
+ pcd = pmc_rowindex_to_classdep[ri];
+
+ KASSERT(pcd != NULL,
+ ("[amd,%d] ri %d null pcd", __LINE__, ri));
+
+ *adjri = ri - pcd->pcd_ri;
+
+ KASSERT(*adjri >= 0 && *adjri < pcd->pcd_num,
+ ("[pmc,%d] adjusted row-index %d", __LINE__, *adjri));
+
+ return (pcd);
+}
+
+/*
* Concurrency Control
*
* The driver manages the following data structures:
@@ -623,12 +669,12 @@ pmc_restore_cpu_binding(struct pmc_binding *pb)
static void
pmc_select_cpu(int cpu)
{
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[pmc,%d] bad cpu number %d", __LINE__, cpu));
- /* never move to a disabled CPU */
- KASSERT(pmc_cpu_is_disabled(cpu) == 0, ("[pmc,%d] selecting "
- "disabled CPU %d", __LINE__, cpu));
+ /* Never move to an inactive CPU. */
+ KASSERT(pmc_cpu_is_active(cpu), ("[pmc,%d] selecting inactive "
+ "CPU %d", __LINE__, cpu));
PMCDBG(CPU,SEL,2, "select-cpu cpu=%d", cpu);
thread_lock(curthread);
@@ -763,9 +809,7 @@ pmc_link_target_process(struct pmc *pm, struct pmc_process *pp)
__LINE__, pp, pm));
#endif
- MALLOC(pt, struct pmc_target *, sizeof(struct pmc_target),
- M_PMC, M_ZERO|M_WAITOK);
-
+ pt = malloc(sizeof(struct pmc_target), M_PMC, M_WAITOK|M_ZERO);
pt->pt_process = pp;
LIST_INSERT_HEAD(&pm->pm_targets, pt, pt_next);
@@ -952,9 +996,15 @@ pmc_attach_one_process(struct proc *p, struct pmc *pm)
/* issue an attach event to a configured log file */
if (pm->pm_owner->po_flags & PMC_PO_OWNS_LOGFILE) {
pmc_getfilename(p->p_textvp, &fullpath, &freepath);
- pmclog_process_pmcattach(pm, p->p_pid, fullpath);
+ if (p->p_flag & P_KTHREAD) {
+ fullpath = kernelname;
+ freepath = NULL;
+ } else
+ pmclog_process_pmcattach(pm, p->p_pid, fullpath);
if (freepath)
FREE(freepath, M_TEMP);
+ if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+ pmc_log_process_mappings(pm->pm_owner, p);
}
/* mark process as using HWPMCs */
PROC_LOCK(p);
@@ -1143,13 +1193,14 @@ static void
pmc_process_csw_in(struct thread *td)
{
int cpu;
- unsigned int ri;
+ unsigned int adjri, ri;
struct pmc *pm;
struct proc *p;
struct pmc_cpu *pc;
struct pmc_hw *phw;
- struct pmc_process *pp;
pmc_value_t newvalue;
+ struct pmc_process *pp;
+ struct pmc_classdep *pcd;
p = td->td_proc;
@@ -1166,7 +1217,7 @@ pmc_process_csw_in(struct thread *td)
PMCDBG(CSW,SWI,1, "cpu=%d proc=%p (%d, %s) pp=%p", cpu, p,
p->p_pid, p->p_comm, pp);
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[pmc,%d] wierd CPU id %d", __LINE__, cpu));
pc = pmc_pcpu[cpu];
@@ -1196,7 +1247,8 @@ pmc_process_csw_in(struct thread *td)
atomic_add_rel_32(&pm->pm_runcount, 1);
/* configure the HWPMC we are going to use. */
- md->pmd_config_pmc(cpu, ri, pm);
+ pcd = pmc_ri_to_classdep(md, ri, &adjri);
+ pcd->pcd_config_pmc(cpu, adjri, pm);
phw = pc->pc_hwpmcs[ri];
@@ -1231,8 +1283,8 @@ pmc_process_csw_in(struct thread *td)
PMCDBG(CSW,SWI,1,"cpu=%d ri=%d new=%jd", cpu, ri, newvalue);
- md->pmd_write_pmc(cpu, ri, newvalue);
- md->pmd_start_pmc(cpu, ri);
+ pcd->pcd_write_pmc(cpu, adjri, newvalue);
+ pcd->pcd_start_pmc(cpu, adjri);
}
/*
@@ -1254,14 +1306,16 @@ static void
pmc_process_csw_out(struct thread *td)
{
int cpu;
- enum pmc_mode mode;
- unsigned int ri;
+ int64_t tmp;
struct pmc *pm;
struct proc *p;
+ enum pmc_mode mode;
struct pmc_cpu *pc;
- struct pmc_process *pp;
- int64_t tmp;
pmc_value_t newvalue;
+ unsigned int adjri, ri;
+ struct pmc_process *pp;
+ struct pmc_classdep *pcd;
+
/*
* Locate our process descriptor; this may be NULL if
@@ -1291,7 +1345,7 @@ pmc_process_csw_out(struct thread *td)
PMCDBG(CSW,SWO,1, "cpu=%d proc=%p (%d, %s) pp=%p", cpu, p,
p->p_pid, p->p_comm, pp);
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[pmc,%d wierd CPU id %d", __LINE__, cpu));
pc = pmc_pcpu[cpu];
@@ -1309,8 +1363,9 @@ pmc_process_csw_out(struct thread *td)
for (ri = 0; ri < md->pmd_npmc; ri++) {
- pm = NULL;
- (void) (*md->pmd_get_config)(cpu, ri, &pm);
+ pcd = pmc_ri_to_classdep(md, ri, &adjri);
+ pm = NULL;
+ (void) (*pcd->pcd_get_config)(cpu, adjri, &pm);
if (pm == NULL) /* nothing at this row index */
continue;
@@ -1325,7 +1380,7 @@ pmc_process_csw_out(struct thread *td)
/* Stop hardware if not already stopped */
if (pm->pm_stalled == 0)
- md->pmd_stop_pmc(cpu, ri);
+ pcd->pcd_stop_pmc(cpu, adjri);
/* reduce this PMC's runcount */
atomic_subtract_rel_32(&pm->pm_runcount, 1);
@@ -1345,7 +1400,7 @@ pmc_process_csw_out(struct thread *td)
("[pmc,%d] pp refcnt = %d", __LINE__,
pp->pp_refcnt));
- md->pmd_read_pmc(cpu, ri, &newvalue);
+ pcd->pcd_read_pmc(cpu, adjri, &newvalue);
tmp = newvalue - PMC_PCPU_SAVED(cpu,ri);
@@ -1396,7 +1451,7 @@ pmc_process_csw_out(struct thread *td)
}
/* mark hardware as free */
- md->pmd_config_pmc(cpu, ri, NULL);
+ pcd->pcd_config_pmc(cpu, adjri, NULL);
}
/*
@@ -1447,7 +1502,7 @@ pmc_process_kld_unload(struct pmckern_map_out *pkm)
if (po->po_flags & PMC_PO_OWNS_LOGFILE)
pmclog_process_map_out(po, (pid_t) -1,
pkm->pm_address, pkm->pm_address + pkm->pm_size);
-
+
/*
* TODO: Notify owners of process-sampling PMCs.
*/
@@ -1526,6 +1581,88 @@ pmc_process_munmap(struct thread *td, struct pmckern_map_out *pkm)
}
/*
+ * Log mapping information about the kernel.
+ */
+
+static void
+pmc_log_kernel_mappings(struct pmc *pm)
+{
+ struct pmc_owner *po;
+ struct pmckern_map_in *km, *kmbase;
+
+ sx_assert(&pmc_sx, SX_LOCKED);
+ KASSERT(PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)),
+ ("[pmc,%d] non-sampling PMC (%p) desires mapping information",
+ __LINE__, (void *) pm));
+
+ po = pm->pm_owner;
+
+ if (po->po_flags & PMC_PO_INITIAL_MAPPINGS_DONE)
+ return;
+
+ /*
+ * Log the current set of kernel modules.
+ */
+ kmbase = linker_hwpmc_list_objects();
+ for (km = kmbase; km->pm_file != NULL; km++) {
+ PMCDBG(LOG,REG,1,"%s %p", (char *) km->pm_file,
+ (void *) km->pm_address);
+ pmclog_process_map_in(po, (pid_t) -1, km->pm_address,
+ km->pm_file);
+ }
+ FREE(kmbase, M_LINKER);
+
+ po->po_flags |= PMC_PO_INITIAL_MAPPINGS_DONE;
+}
+
+/*
+ * Log the mappings for a single process.
+ */
+
+static void
+pmc_log_process_mappings(struct pmc_owner *po, struct proc *p)
+{
+}
+
+/*
+ * Log mappings for all processes in the system.
+ */
+
+static void
+pmc_log_all_process_mappings(struct pmc_owner *po)
+{
+ struct proc *p, *top;
+
+ sx_assert(&pmc_sx, SX_XLOCKED);
+
+ if ((p = pfind(1)) == NULL)
+ panic("[pmc,%d] Cannot find init", __LINE__);
+
+ PROC_UNLOCK(p);
+
+ sx_slock(&proctree_lock);
+
+ top = p;
+
+ for (;;) {
+ pmc_log_process_mappings(po, p);
+ if (!LIST_EMPTY(&p->p_children))
+ p = LIST_FIRST(&p->p_children);
+ else for (;;) {
+ if (p == top)
+ goto done;
+ if (LIST_NEXT(p, p_sibling)) {
+ p = LIST_NEXT(p, p_sibling);
+ break;
+ }
+ p = p->p_pptr;
+ }
+ }
+ done:
+ sx_sunlock(&proctree_lock);
+}
+
+/*
* The 'hook' invoked from the kernel proper
*/
@@ -1541,7 +1678,8 @@ const char *pmc_hooknames[] = {
"KLDLOAD",
"KLDUNLOAD",
"MMAP",
- "MUNMAP"
+ "MUNMAP",
+ "CALLCHAIN"
};
#endif
@@ -1724,6 +1862,17 @@ pmc_hook_handler(struct thread *td, int function, void *arg)
pmc_process_munmap(td, (struct pmckern_map_out *) arg);
break;
+ case PMC_FN_USER_CALLCHAIN:
+ /*
+ * Record a call chain.
+ */
+ KASSERT(td == curthread, ("[pmc,%d] td != curthread",
+ __LINE__));
+ pmc_capture_user_callchain(PCPU_GET(cpuid),
+ (struct trapframe *) arg);
+ td->td_pflags &= ~TDP_CALLCHAIN;
+ break;
+
default:
#ifdef DEBUG
KASSERT(0, ("[pmc,%d] unknown hook %d\n", __LINE__, function));
@@ -1750,9 +1899,7 @@ pmc_allocate_owner_descriptor(struct proc *p)
poh = &pmc_ownerhash[hindex];
/* allocate space for N pointers and one descriptor struct */
- MALLOC(po, struct pmc_owner *, sizeof(struct pmc_owner),
- M_PMC, M_ZERO|M_WAITOK);
-
+ po = malloc(sizeof(struct pmc_owner), M_PMC, M_WAITOK|M_ZERO);
po->po_sscount = po->po_error = po->po_flags = 0;
po->po_file = NULL;
po->po_owner = p;
@@ -1801,13 +1948,9 @@ pmc_find_process_descriptor(struct proc *p, uint32_t mode)
* Pre-allocate memory in the FIND_ALLOCATE case since we
* cannot call malloc(9) once we hold a spin lock.
*/
-
- if (mode & PMC_FLAG_ALLOCATE) {
- /* allocate additional space for 'n' pmc pointers */
- MALLOC(ppnew, struct pmc_process *,
- sizeof(struct pmc_process) + md->pmd_npmc *
- sizeof(struct pmc_targetstate), M_PMC, M_ZERO|M_WAITOK);
- }
+ if (mode & PMC_FLAG_ALLOCATE)
+ ppnew = malloc(sizeof(struct pmc_process) + md->pmd_npmc *
+ sizeof(struct pmc_targetstate), M_PMC, M_WAITOK|M_ZERO);
mtx_lock_spin(&pmc_processhash_mtx);
LIST_FOREACH(pp, pph, pp_next)
@@ -1886,7 +2029,7 @@ pmc_allocate_pmc_descriptor(void)
{
struct pmc *pmc;
- MALLOC(pmc, struct pmc *, sizeof(struct pmc), M_PMC, M_ZERO|M_WAITOK);
+ pmc = malloc(sizeof(struct pmc), M_PMC, M_WAITOK|M_ZERO);
if (pmc != NULL) {
pmc->pm_owner = NULL;
@@ -1927,7 +2070,7 @@ pmc_wait_for_pmc_idle(struct pmc *pm)
#ifdef DEBUG
volatile int maxloop;
- maxloop = 100 * mp_ncpus;
+ maxloop = 100 * pmc_cpu_max();
#endif
/*
@@ -1961,19 +2104,21 @@ pmc_wait_for_pmc_idle(struct pmc *pm)
static void
pmc_release_pmc_descriptor(struct pmc *pm)
{
- u_int ri, cpu;
enum pmc_mode mode;
struct pmc_hw *phw;
+ u_int adjri, ri, cpu;
struct pmc_owner *po;
+ struct pmc_binding pb;
struct pmc_process *pp;
+ struct pmc_classdep *pcd;
struct pmc_target *ptgt, *tmp;
- struct pmc_binding pb;
sx_assert(&pmc_sx, SX_XLOCKED);
KASSERT(pm, ("[pmc,%d] null pmc", __LINE__));
ri = PMC_TO_ROWINDEX(pm);
+ pcd = pmc_ri_to_classdep(md, ri, &adjri);
mode = PMC_TO_MODE(pm);
PMCDBG(PMC,REL,1, "release-pmc pmc=%p ri=%d mode=%d", pm, ri,
@@ -2007,14 +2152,14 @@ pmc_release_pmc_descriptor(struct pmc *pm)
PMCDBG(PMC,REL,2, "stopping cpu=%d ri=%d", cpu, ri);
critical_enter();
- md->pmd_stop_pmc(cpu, ri);
+ pcd->pcd_stop_pmc(cpu, adjri);
critical_exit();
}
PMCDBG(PMC,REL,2, "decfg cpu=%d ri=%d", cpu, ri);
critical_enter();
- md->pmd_config_pmc(cpu, ri, NULL);
+ pcd->pcd_config_pmc(cpu, adjri, NULL);
critical_exit();
/* adjust the global and process count of SS mode PMCs */
@@ -2087,8 +2232,7 @@ pmc_release_pmc_descriptor(struct pmc *pm)
/*
* Release any MD resources
*/
-
- (void) md->pmd_release_pmc(cpu, ri, pm);
+ (void) pcd->pcd_release_pmc(cpu, adjri, pm);
/*
* Update row disposition
@@ -2303,22 +2447,40 @@ pmc_find_pmc(pmc_id_t pmcid, struct pmc **pmc)
static int
pmc_start(struct pmc *pm)
{
- int error, cpu, ri;
enum pmc_mode mode;
struct pmc_owner *po;
struct pmc_binding pb;
+ struct pmc_classdep *pcd;
+ int adjri, error, cpu, ri;
KASSERT(pm != NULL,
("[pmc,%d] null pm", __LINE__));
mode = PMC_TO_MODE(pm);
ri = PMC_TO_ROWINDEX(pm);
+ pcd = pmc_ri_to_classdep(md, ri, &adjri);
+
error = 0;
PMCDBG(PMC,OPS,1, "start pmc=%p mode=%d ri=%d", pm, mode, ri);
po = pm->pm_owner;
+ /*
+ * Disallow PMCSTART if a logfile is required but has not been
+ * configured yet.
+ */
+ if ((pm->pm_flags & PMC_F_NEEDS_LOGFILE) &&
+ (po->po_flags & PMC_PO_OWNS_LOGFILE) == 0)
+ return (EDOOFUS); /* programming error */
+
+ /*
+ * If this is a sampling mode PMC, log mapping information for
+ * the kernel modules that are currently loaded.
+ */
+ if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+ pmc_log_kernel_mappings(pm);
+
if (PMC_IS_VIRTUAL_MODE(mode)) {
/*
@@ -2331,15 +2493,6 @@ pmc_start(struct pmc *pm)
pmc_attach_process(po->po_owner, pm);
/*
- * Disallow PMCSTART if a logfile is required but has not
- * been configured yet.
- */
-
- if (error == 0 && (pm->pm_flags & PMC_F_NEEDS_LOGFILE) &&
- (po->po_flags & PMC_PO_OWNS_LOGFILE) == 0)
- error = EDOOFUS;
-
- /*
* If the PMC is attached to its owner, then force a context
* switch to ensure that the MD state gets set correctly.
*/
@@ -2350,19 +2503,13 @@ pmc_start(struct pmc *pm)
pmc_force_context_switch();
}
- return error;
+ return (error);
}
/*
* A system-wide PMC.
- */
-
- if ((pm->pm_flags & PMC_F_NEEDS_LOGFILE) &&
- (po->po_flags & PMC_PO_OWNS_LOGFILE) == 0)
- return EDOOFUS; /* programming error */
-
- /*
+ *
* Add the owner to the global list if this is a system-wide
* sampling PMC.
*/
@@ -2376,7 +2523,8 @@ pmc_start(struct pmc *pm)
po->po_sscount++;
}
- /* TODO: dump system wide process mappings to the log? */
+ /* Log mapping information for all processes in the system. */
+ pmc_log_all_process_mappings(po);
/*
* Move to the CPU associated with this
@@ -2387,8 +2535,8 @@ pmc_start(struct pmc *pm)
cpu = PMC_TO_CPU(pm);
- if (pmc_cpu_is_disabled(cpu))
- return ENXIO;
+ if (!pmc_cpu_is_active(cpu))
+ return (ENXIO);
pmc_select_cpu(cpu);
@@ -2400,16 +2548,16 @@ pmc_start(struct pmc *pm)
pm->pm_state = PMC_STATE_RUNNING;
critical_enter();
- if ((error = md->pmd_write_pmc(cpu, ri,
+ if ((error = pcd->pcd_write_pmc(cpu, adjri,
PMC_IS_SAMPLING_MODE(mode) ?
pm->pm_sc.pm_reloadcount :
pm->pm_sc.pm_initial)) == 0)
- error = md->pmd_start_pmc(cpu, ri);
+ error = pcd->pcd_start_pmc(cpu, adjri);
critical_exit();
pmc_restore_cpu_binding(&pb);
- return error;
+ return (error);
}
/*
@@ -2419,9 +2567,10 @@ pmc_start(struct pmc *pm)
static int
pmc_stop(struct pmc *pm)
{
- int cpu, error, ri;
struct pmc_owner *po;
struct pmc_binding pb;
+ struct pmc_classdep *pcd;
+ int adjri, cpu, error, ri;
KASSERT(pm != NULL, ("[pmc,%d] null pmc", __LINE__));
@@ -2454,19 +2603,20 @@ pmc_stop(struct pmc *pm)
cpu = PMC_TO_CPU(pm);
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[pmc,%d] illegal cpu=%d", __LINE__, cpu));
- if (pmc_cpu_is_disabled(cpu))
+ if (!pmc_cpu_is_active(cpu))
return ENXIO;
pmc_select_cpu(cpu);
ri = PMC_TO_ROWINDEX(pm);
+ pcd = pmc_ri_to_classdep(md, ri, &adjri);
critical_enter();
- if ((error = md->pmd_stop_pmc(cpu, ri)) == 0)
- error = md->pmd_read_pmc(cpu, ri, &pm->pm_sc.pm_initial);
+ if ((error = pcd->pcd_stop_pmc(cpu, adjri)) == 0)
+ error = pcd->pcd_read_pmc(cpu, adjri, &pm->pm_sc.pm_initial);
critical_exit();
pmc_restore_cpu_binding(&pb);
@@ -2483,7 +2633,7 @@ pmc_stop(struct pmc *pm)
}
}
- return error;
+ return (error);
}
@@ -2552,7 +2702,6 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
struct proc *p;
struct pmc *pm;
struct pmc_owner *po;
- struct pmckern_map_in *km, *kmbase;
struct pmc_op_configurelog cl;
sx_assert(&pmc_sx, SX_XLOCKED);
@@ -2575,7 +2724,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
* de-configure it.
*/
if (cl.pm_logfd >= 0)
- error = pmclog_configure_log(po, cl.pm_logfd);
+ error = pmclog_configure_log(md, po, cl.pm_logfd);
else if (po->po_flags & PMC_PO_OWNS_LOGFILE) {
pmclog_process_closelog(po);
error = pmclog_flush(po);
@@ -2591,18 +2740,6 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
if (error)
break;
-
- /*
- * Log the current set of kernel modules.
- */
- kmbase = linker_hwpmc_list_objects();
- for (km = kmbase; km->pm_file != NULL; km++) {
- PMCDBG(LOG,REG,1,"%s %p", (char *) km->pm_file,
- (void *) km->pm_address);
- pmclog_process_map_in(po, (pid_t) -1, km->pm_address,
- km->pm_file);
- }
- FREE(kmbase, M_LINKER);
}
break;
@@ -2633,13 +2770,22 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
case PMC_OP_GETCPUINFO: /* CPU information */
{
struct pmc_op_getcpuinfo gci;
+ struct pmc_classinfo *pci;
+ struct pmc_classdep *pcd;
+ int cl;
gci.pm_cputype = md->pmd_cputype;
- gci.pm_ncpu = mp_ncpus;
+ gci.pm_ncpu = pmc_cpu_max();
gci.pm_npmc = md->pmd_npmc;
gci.pm_nclass = md->pmd_nclass;
- bcopy(md->pmd_classes, &gci.pm_classes,
- sizeof(gci.pm_classes));
+ pci = gci.pm_classes;
+ pcd = md->pmd_classdep;
+ for (cl = 0; cl < md->pmd_nclass; cl++, pci++, pcd++) {
+ pci->pm_caps = pcd->pcd_caps;
+ pci->pm_class = pcd->pcd_class;
+ pci->pm_width = pcd->pcd_width;
+ pci->pm_num = pcd->pcd_num;
+ }
error = copyout(&gci, arg, sizeof(gci));
}
break;
@@ -2688,13 +2834,15 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
case PMC_OP_GETPMCINFO:
{
- uint32_t cpu, n, npmc;
- size_t pmcinfo_size;
+ int ari;
struct pmc *pm;
- struct pmc_info *p, *pmcinfo;
- struct pmc_op_getpmcinfo *gpi;
+ size_t pmcinfo_size;
+ uint32_t cpu, n, npmc;
struct pmc_owner *po;
struct pmc_binding pb;
+ struct pmc_classdep *pcd;
+ struct pmc_info *p, *pmcinfo;
+ struct pmc_op_getpmcinfo *gpi;
PMC_DOWNGRADE_SX();
@@ -2703,12 +2851,12 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
if ((error = copyin(&gpi->pm_cpu, &cpu, sizeof(cpu))) != 0)
break;
- if (cpu >= (unsigned int) mp_ncpus) {
+ if (cpu >= pmc_cpu_max()) {
error = EINVAL;
break;
}
- if (pmc_cpu_is_disabled(cpu)) {
+ if (!pmc_cpu_is_active(cpu)) {
error = ENXIO;
break;
}
@@ -2727,7 +2875,12 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
for (n = 0; n < md->pmd_npmc; n++, p++) {
- if ((error = md->pmd_describe(cpu, n, p, &pm)) != 0)
+ pcd = pmc_ri_to_classdep(md, n, &ari);
+
+ KASSERT(pcd != NULL,
+ ("[pmc,%d] null pcd ri=%d", __LINE__, n));
+
+ if ((error = pcd->pcd_describe(cpu, ari, p, &pm)) != 0)
break;
if (PMC_ROW_DISP_IS_STANDALONE(n))
@@ -2797,12 +2950,12 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
cpu = pma.pm_cpu;
- if (cpu < 0 || cpu >= mp_ncpus) {
+ if (cpu < 0 || cpu >= (int) pmc_cpu_max()) {
error = EINVAL;
break;
}
- if (pmc_cpu_is_disabled(cpu)) {
+ if (!pmc_cpu_is_active(cpu)) {
error = ENXIO;
break;
}
@@ -2872,14 +3025,15 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
case PMC_OP_PMCALLOCATE:
{
- uint32_t caps;
+ int adjri, n;
u_int cpu;
- int n;
- enum pmc_mode mode;
+ uint32_t caps;
struct pmc *pmc;
+ enum pmc_mode mode;
struct pmc_hw *phw;
- struct pmc_op_pmcallocate pa;
struct pmc_binding pb;
+ struct pmc_classdep *pcd;
+ struct pmc_op_pmcallocate pa;
if ((error = copyin(arg, &pa, sizeof(pa))) != 0)
break;
@@ -2890,7 +3044,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
if ((mode != PMC_MODE_SS && mode != PMC_MODE_SC &&
mode != PMC_MODE_TS && mode != PMC_MODE_TC) ||
- (cpu != (u_int) PMC_CPU_ANY && cpu >= (u_int) mp_ncpus)) {
+ (cpu != (u_int) PMC_CPU_ANY && cpu >= pmc_cpu_max())) {
error = EINVAL;
break;
}
@@ -2907,10 +3061,10 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
}
/*
- * Check that a disabled CPU is not being asked for.
+ * Check that an inactive CPU is not being asked for.
*/
- if (PMC_IS_SYSTEM_MODE(mode) && pmc_cpu_is_disabled(cpu)) {
+ if (PMC_IS_SYSTEM_MODE(mode) && !pmc_cpu_is_active(cpu)) {
error = ENXIO;
break;
}
@@ -2943,7 +3097,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
*/
if ((pa.pm_flags & ~(PMC_F_DESCENDANTS | PMC_F_LOG_PROCCSW |
- PMC_F_LOG_PROCEXIT)) != 0) {
+ PMC_F_LOG_PROCEXIT | PMC_F_CALLCHAIN)) != 0) {
error = EINVAL;
break;
}
@@ -2964,7 +3118,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
/* A valid class specifier should have been passed in. */
for (n = 0; n < md->pmd_nclass; n++)
- if (md->pmd_classes[n].pm_class == pa.pm_class)
+ if (md->pmd_classdep[n].pcd_class == pa.pm_class)
break;
if (n == md->pmd_nclass) {
error = EINVAL;
@@ -2972,7 +3126,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
}
/* The requested PMC capabilities should be feasible. */
- if ((md->pmd_classes[n].pm_caps & caps) != caps) {
+ if ((md->pmd_classdep[n].pcd_caps & caps) != caps) {
error = EOPNOTSUPP;
break;
}
@@ -2999,24 +3153,27 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
if (PMC_IS_SYSTEM_MODE(mode)) {
pmc_select_cpu(cpu);
- for (n = 0; n < (int) md->pmd_npmc; n++)
+ for (n = 0; n < (int) md->pmd_npmc; n++) {
+ pcd = pmc_ri_to_classdep(md, n, &adjri);
if (pmc_can_allocate_row(n, mode) == 0 &&
pmc_can_allocate_rowindex(
curthread->td_proc, n, cpu) == 0 &&
(PMC_IS_UNALLOCATED(cpu, n) ||
PMC_IS_SHAREABLE_PMC(cpu, n)) &&
- md->pmd_allocate_pmc(cpu, n, pmc,
+ pcd->pcd_allocate_pmc(cpu, adjri, pmc,
&pa) == 0)
break;
+ }
} else {
/* Process virtual mode */
for (n = 0; n < (int) md->pmd_npmc; n++) {
+ pcd = pmc_ri_to_classdep(md, n, &adjri);
if (pmc_can_allocate_row(n, mode) == 0 &&
pmc_can_allocate_rowindex(
curthread->td_proc, n,
PMC_CPU_ANY) == 0 &&
- md->pmd_allocate_pmc(curthread->td_oncpu,
- n, pmc, &pa) == 0)
+ pcd->pcd_allocate_pmc(curthread->td_oncpu,
+ adjri, pmc, &pa) == 0)
break;
}
}
@@ -3058,10 +3215,11 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
pmc_select_cpu(cpu);
phw = pmc_pcpu[cpu]->pc_hwpmcs[n];
+ pcd = pmc_ri_to_classdep(md, n, &adjri);
if ((phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) == 0 ||
- (error = md->pmd_config_pmc(cpu, n, pmc)) != 0) {
- (void) md->pmd_release_pmc(cpu, n, pmc);
+ (error = pcd->pcd_config_pmc(cpu, adjri, pmc)) != 0) {
+ (void) pcd->pcd_release_pmc(cpu, adjri, pmc);
pmc_destroy_pmc_descriptor(pmc);
FREE(pmc, M_PMC);
pmc = NULL;
@@ -3227,19 +3385,14 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
case PMC_OP_PMCGETMSR:
{
- int ri;
- struct pmc *pm;
+ int adjri, ri;
+ struct pmc *pm;
struct pmc_target *pt;
struct pmc_op_getmsr gm;
+ struct pmc_classdep *pcd;
PMC_DOWNGRADE_SX();
- /* CPU has no 'GETMSR' support */
- if (md->pmd_get_msr == NULL) {
- error = ENOSYS;
- break;
- }
-
if ((error = copyin(arg, &gm, sizeof(gm))) != 0)
break;
@@ -3279,8 +3432,15 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
}
ri = PMC_TO_ROWINDEX(pm);
+ pcd = pmc_ri_to_classdep(md, ri, &adjri);
+
+ /* PMC class has no 'GETMSR' support */
+ if (pcd->pcd_get_msr == NULL) {
+ error = ENOSYS;
+ break;
+ }
- if ((error = (*md->pmd_get_msr)(ri, &gm.pm_msr)) < 0)
+ if ((error = (*pcd->pcd_get_msr)(adjri, &gm.pm_msr)) < 0)
break;
if ((error = copyout(&gm, arg, sizeof(gm))) < 0)
@@ -3344,12 +3504,14 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
case PMC_OP_PMCRW:
{
- uint32_t cpu, ri;
+ int adjri;
struct pmc *pm;
- struct pmc_op_pmcrw *pprw;
- struct pmc_op_pmcrw prw;
- struct pmc_binding pb;
+ uint32_t cpu, ri;
pmc_value_t oldvalue;
+ struct pmc_binding pb;
+ struct pmc_op_pmcrw prw;
+ struct pmc_classdep *pcd;
+ struct pmc_op_pmcrw *pprw;
PMC_DOWNGRADE_SX();
@@ -3402,6 +3564,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
*/
ri = PMC_TO_ROWINDEX(pm);
+ pcd = pmc_ri_to_classdep(md, ri, &adjri);
mtx_pool_lock_spin(pmc_mtxpool, pm);
cpu = curthread->td_oncpu;
@@ -3409,7 +3572,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
if (prw.pm_flags & PMC_F_OLDVALUE) {
if ((pm->pm_flags & PMC_F_ATTACHED_TO_OWNER) &&
(pm->pm_state == PMC_STATE_RUNNING))
- error = (*md->pmd_read_pmc)(cpu, ri,
+ error = (*pcd->pcd_read_pmc)(cpu, adjri,
&oldvalue);
else
oldvalue = pm->pm_gv.pm_savedvalue;
@@ -3422,8 +3585,9 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
} else { /* System mode PMCs */
cpu = PMC_TO_CPU(pm);
ri = PMC_TO_ROWINDEX(pm);
+ pcd = pmc_ri_to_classdep(md, ri, &adjri);
- if (pmc_cpu_is_disabled(cpu)) {
+ if (!pmc_cpu_is_active(cpu)) {
error = ENXIO;
break;
}
@@ -3435,12 +3599,12 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
critical_enter();
/* save old value */
if (prw.pm_flags & PMC_F_OLDVALUE)
- if ((error = (*md->pmd_read_pmc)(cpu, ri,
+ if ((error = (*pcd->pcd_read_pmc)(cpu, adjri,
&oldvalue)))
goto error;
/* write out new value */
if (prw.pm_flags & PMC_F_NEWVALUE)
- error = (*md->pmd_write_pmc)(cpu, ri,
+ error = (*pcd->pcd_write_pmc)(cpu, adjri,
prw.pm_value);
error:
critical_exit();
@@ -3631,56 +3795,120 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
/*
+ * Mark the thread as needing callchain capture and post an AST. The
+ * actual callchain capture will be done in a context where it is safe
+ * to take page faults.
+ */
+
+static void
+pmc_post_callchain_callback(void)
+{
+ struct thread *td;
+
+ td = curthread;
+
+ KASSERT((td->td_pflags & TDP_CALLCHAIN) == 0,
+ ("[pmc,%d] thread %p already marked for callchain capture",
+ __LINE__, (void *) td));
+
+ /*
+ * Mark this thread as needing callchain capture.
+ * `td->td_pflags' will be safe to touch because this thread
+ * was in user space when it was interrupted.
+ */
+ td->td_pflags |= TDP_CALLCHAIN;
+
+ /*
+ * Don't let this thread migrate between CPUs until callchain
+ * capture completes.
+ */
+ sched_pin();
+
+ return;
+}
+
+/*
* Interrupt processing.
*
- * Find a free slot in the per-cpu array of PC samples and write the
- * current (PMC,PID,PC) triple to it. If an event was successfully
- * added, a bit is set in mask 'pmc_cpumask' denoting that the
- * DO_SAMPLES hook needs to be invoked from the clock handler.
+ * Find a free slot in the per-cpu array of samples and capture the
+ * current callchain there. If a sample was successfully added, a bit
+ * is set in mask 'pmc_cpumask' denoting that the DO_SAMPLES hook
+ * needs to be invoked from the clock handler.
*
* This function is meant to be called from an NMI handler. It cannot
* use any of the locking primitives supplied by the OS.
*/
int
-pmc_process_interrupt(int cpu, struct pmc *pm, uintfptr_t pc, int usermode)
+pmc_process_interrupt(int cpu, struct pmc *pm, struct trapframe *tf,
+ int inuserspace)
{
- int error, ri;
+ int error, callchaindepth;
struct thread *td;
struct pmc_sample *ps;
struct pmc_samplebuffer *psb;
error = 0;
- ri = PMC_TO_ROWINDEX(pm);
+ /*
+ * Allocate space for a sample buffer.
+ */
psb = pmc_pcpu[cpu]->pc_sb;
ps = psb->ps_write;
- if (ps->ps_pc) { /* in use, reader hasn't caught up */
+ if (ps->ps_nsamples) { /* in use, reader hasn't caught up */
pm->pm_stalled = 1;
atomic_add_int(&pmc_stats.pm_intr_bufferfull, 1);
- PMCDBG(SAM,INT,1,"(spc) cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d",
- cpu, pm, (uint64_t) pc, usermode,
+ PMCDBG(SAM,INT,1,"(spc) cpu=%d pm=%p tf=%p um=%d wr=%d rd=%d",
+ cpu, pm, (void *) tf, inuserspace,
(int) (psb->ps_write - psb->ps_samples),
(int) (psb->ps_read - psb->ps_samples));
error = ENOMEM;
goto done;
}
- /* fill in entry */
- PMCDBG(SAM,INT,1,"cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d", cpu, pm,
- (uint64_t) pc, usermode,
+
+ /* Fill in entry. */
+ PMCDBG(SAM,INT,1,"cpu=%d pm=%p tf=%p um=%d wr=%d rd=%d", cpu, pm,
+ (void *) tf, inuserspace,
(int) (psb->ps_write - psb->ps_samples),
(int) (psb->ps_read - psb->ps_samples));
- atomic_add_rel_32(&pm->pm_runcount, 1); /* hold onto PMC */
+ KASSERT(pm->pm_runcount >= 0,
+ ("[pmc,%d] pm=%p runcount %d", __LINE__, (void *) pm,
+ pm->pm_runcount));
+
+ atomic_add_rel_32(&pm->pm_runcount, 1); /* hold onto PMC */
ps->ps_pmc = pm;
if ((td = curthread) && td->td_proc)
ps->ps_pid = td->td_proc->p_pid;
else
ps->ps_pid = -1;
- ps->ps_usermode = usermode;
- ps->ps_pc = pc; /* mark entry as in use */
+ ps->ps_cpu = cpu;
+ ps->ps_td = td;
+ ps->ps_flags = inuserspace ? PMC_CC_F_USERSPACE : 0;
+
+ callchaindepth = (pm->pm_flags & PMC_F_CALLCHAIN) ?
+ pmc_callchaindepth : 1;
+
+ if (callchaindepth == 1)
+ ps->ps_pc[0] = PMC_TRAPFRAME_TO_PC(tf);
+ else {
+ /*
+ * Kernel stack traversals can be done immediately,
+ * while we defer to an AST for user space traversals.
+ */
+ if (!inuserspace)
+ callchaindepth =
+ pmc_save_kernel_callchain(ps->ps_pc,
+ callchaindepth, tf);
+ else {
+ pmc_post_callchain_callback();
+ callchaindepth = PMC_SAMPLE_INUSE;
+ }
+ }
+
+ ps->ps_nsamples = callchaindepth; /* mark entry as in use */
/* increment write pointer, modulo ring buffer size */
ps++;
@@ -3693,7 +3921,83 @@ pmc_process_interrupt(int cpu, struct pmc *pm, uintfptr_t pc, int usermode)
/* mark CPU as needing processing */
atomic_set_rel_int(&pmc_cpumask, (1 << cpu));
- return error;
+ return (error);
+}
+
+/*
+ * Capture a user call chain. This function will be called from ast()
+ * before control returns to userland and before the process gets
+ * rescheduled.
+ */
+
+static void
+pmc_capture_user_callchain(int cpu, struct trapframe *tf)
+{
+ int i;
+ struct pmc *pm;
+ struct thread *td;
+ struct pmc_sample *ps;
+ struct pmc_samplebuffer *psb;
+#ifdef INVARIANTS
+ int ncallchains;
+#endif
+
+ sched_unpin(); /* Can migrate safely now. */
+
+ psb = pmc_pcpu[cpu]->pc_sb;
+ td = curthread;
+
+ KASSERT(td->td_pflags & TDP_CALLCHAIN,
+ ("[pmc,%d] Retrieving callchain for thread that doesn't want it",
+ __LINE__));
+
+#ifdef INVARIANTS
+ ncallchains = 0;
+#endif
+
+ /*
+ * Iterate through all deferred callchain requests.
+ */
+
+ ps = psb->ps_samples;
+ for (i = 0; i < pmc_nsamples; i++, ps++) {
+
+ if (ps->ps_nsamples != PMC_SAMPLE_INUSE)
+ continue;
+ if (ps->ps_td != td)
+ continue;
+
+ KASSERT(ps->ps_cpu == cpu,
+ ("[pmc,%d] cpu mismatch ps_cpu=%d pcpu=%d", __LINE__,
+ ps->ps_cpu, PCPU_GET(cpuid)));
+
+ pm = ps->ps_pmc;
+
+ KASSERT(pm->pm_flags & PMC_F_CALLCHAIN,
+ ("[pmc,%d] Retrieving callchain for PMC that doesn't "
+ "want it", __LINE__));
+
+ KASSERT(pm->pm_runcount > 0,
+ ("[pmc,%d] runcount %d", __LINE__, pm->pm_runcount));
+
+ /*
+ * Retrieve the callchain and mark the sample buffer
+ * as 'processable' by the timer tick sweep code.
+ */
+ ps->ps_nsamples = pmc_save_user_callchain(ps->ps_pc,
+ pmc_callchaindepth, tf);
+
+#ifdef INVARIANTS
+ ncallchains++;
+#endif
+
+ }
+
+ KASSERT(ncallchains > 0,
+ ("[pmc,%d] cpu %d didn't find a sample to collect", __LINE__,
+ cpu));
+
+ return;
}
@@ -3704,11 +4008,12 @@ pmc_process_interrupt(int cpu, struct pmc *pm, uintfptr_t pc, int usermode)
static void
pmc_process_samples(int cpu)
{
- int n, ri;
struct pmc *pm;
+ int adjri, n;
struct thread *td;
struct pmc_owner *po;
struct pmc_sample *ps;
+ struct pmc_classdep *pcd;
struct pmc_samplebuffer *psb;
KASSERT(PCPU_GET(cpuid) == cpu,
@@ -3720,10 +4025,20 @@ pmc_process_samples(int cpu)
for (n = 0; n < pmc_nsamples; n++) { /* bound on #iterations */
ps = psb->ps_read;
- if (ps->ps_pc == (uintfptr_t) 0) /* no data */
+ if (ps->ps_nsamples == PMC_SAMPLE_FREE)
break;
+ if (ps->ps_nsamples == PMC_SAMPLE_INUSE) {
+ /* Need a rescan at a later time. */
+ atomic_set_rel_int(&pmc_cpumask, (1 << cpu));
+ break;
+ }
pm = ps->ps_pmc;
+
+ KASSERT(pm->pm_runcount > 0,
+ ("[pmc,%d] pm=%p runcount %d", __LINE__, (void *) pm,
+ pm->pm_runcount));
+
po = pm->pm_owner;
KASSERT(PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)),
@@ -3734,8 +4049,8 @@ pmc_process_samples(int cpu)
if (pm->pm_state != PMC_STATE_RUNNING)
goto entrydone;
- PMCDBG(SAM,OPS,1,"cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d", cpu,
- pm, (uint64_t) ps->ps_pc, ps->ps_usermode,
+ PMCDBG(SAM,OPS,1,"cpu=%d pm=%p n=%d fl=%x wr=%d rd=%d", cpu,
+ pm, ps->ps_nsamples, ps->ps_flags,
(int) (psb->ps_write - psb->ps_samples),
(int) (psb->ps_read - psb->ps_samples));
@@ -3746,9 +4061,9 @@ pmc_process_samples(int cpu)
* would have done.
*/
if (pm->pm_flags & PMC_F_ATTACHED_TO_OWNER) {
- if (ps->ps_usermode) {
+ if (ps->ps_flags & PMC_CC_F_USERSPACE) {
td = FIRST_THREAD_IN_PROC(po->po_owner);
- addupc_intr(td, ps->ps_pc, 1);
+ addupc_intr(td, ps->ps_pc[0], 1);
}
goto entrydone;
}
@@ -3760,10 +4075,10 @@ pmc_process_samples(int cpu)
* entry to the PMC's owner process.
*/
- pmclog_process_pcsample(pm, ps);
+ pmclog_process_callchain(pm, ps);
entrydone:
- ps->ps_pc = (uintfptr_t) 0; /* mark entry as free */
+ ps->ps_nsamples = 0; /* mark entry as free */
atomic_subtract_rel_32(&pm->pm_runcount, 1);
/* increment read pointer, modulo sample size */
@@ -3787,7 +4102,11 @@ pmc_process_samples(int cpu)
* the next hardclock tick.
*/
for (n = 0; n < md->pmd_npmc; n++) {
- (void) (*md->pmd_get_config)(cpu,n,&pm);
+ pcd = pmc_ri_to_classdep(md, n, &adjri);
+ KASSERT(pcd != NULL,
+ ("[pmc,%d] null pcd ri=%d", __LINE__, n));
+ (void) (*pcd->pcd_get_config)(cpu,adjri,&pm);
+
if (pm == NULL || /* !cfg'ed */
pm->pm_state != PMC_STATE_RUNNING || /* !active */
!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)) || /* !sampling */
@@ -3795,8 +4114,7 @@ pmc_process_samples(int cpu)
continue;
pm->pm_stalled = 0;
- ri = PMC_TO_ROWINDEX(pm);
- (*md->pmd_start_pmc)(cpu, ri);
+ (*pcd->pcd_start_pmc)(cpu, adjri);
}
}
@@ -3824,12 +4142,13 @@ pmc_process_samples(int cpu)
static void
pmc_process_exit(void *arg __unused, struct proc *p)
{
- int is_using_hwpmcs;
- int cpu;
- unsigned int ri;
struct pmc *pm;
- struct pmc_process *pp;
+ int adjri, cpu;
+ unsigned int ri;
+ int is_using_hwpmcs;
struct pmc_owner *po;
+ struct pmc_process *pp;
+ struct pmc_classdep *pcd;
pmc_value_t newvalue, tmp;
PROC_LOCK(p);
@@ -3890,7 +4209,10 @@ pmc_process_exit(void *arg __unused, struct proc *p)
* state similar to the CSW_OUT code.
*/
pm = NULL;
- (void) (*md->pmd_get_config)(cpu, ri, &pm);
+
+ pcd = pmc_ri_to_classdep(md, ri, &adjri);
+
+ (void) (*pcd->pcd_get_config)(cpu, adjri, &pm);
PMCDBG(PRC,EXT,2, "ri=%d pm=%p", ri, pm);
@@ -3910,7 +4232,7 @@ pmc_process_exit(void *arg __unused, struct proc *p)
("[pmc,%d] pm %p != pp_pmcs[%d] %p",
__LINE__, pm, ri, pp->pp_pmcs[ri].pp_pmc));
- (void) md->pmd_stop_pmc(cpu, ri);
+ (void) pcd->pcd_stop_pmc(cpu, adjri);
KASSERT(pm->pm_runcount > 0,
("[pmc,%d] bad runcount ri %d rc %d",
@@ -3919,7 +4241,7 @@ pmc_process_exit(void *arg __unused, struct proc *p)
/* Stop hardware only if it is actually running */
if (pm->pm_state == PMC_STATE_RUNNING &&
pm->pm_stalled == 0) {
- md->pmd_read_pmc(cpu, ri, &newvalue);
+ pcd->pcd_read_pmc(cpu, adjri, &newvalue);
tmp = newvalue -
PMC_PCPU_SAVED(cpu,ri);
@@ -3934,7 +4256,7 @@ pmc_process_exit(void *arg __unused, struct proc *p)
KASSERT((int) pm->pm_runcount >= 0,
("[pmc,%d] runcount is %d", __LINE__, ri));
- (void) md->pmd_config_pmc(cpu, ri, NULL);
+ (void) pcd->pcd_config_pmc(cpu, adjri, NULL);
}
/*
@@ -4083,8 +4405,11 @@ static const char *pmc_name_of_pmcclass[] = {
static int
pmc_initialize(void)
{
- int cpu, error, n;
+ int c, cpu, error, n, ri;
+ unsigned int maxcpu;
struct pmc_binding pb;
+ struct pmc_sample *ps;
+ struct pmc_classdep *pcd;
struct pmc_samplebuffer *sb;
md = NULL;
@@ -4117,58 +4442,99 @@ pmc_initialize(void)
*/
if (pmc_hashsize <= 0) {
- (void) printf("hwpmc: tunable hashsize=%d must be greater "
- "than zero.\n", pmc_hashsize);
+ (void) printf("hwpmc: tunable \"hashsize\"=%d must be "
+ "greater than zero.\n", pmc_hashsize);
pmc_hashsize = PMC_HASH_SIZE;
}
if (pmc_nsamples <= 0 || pmc_nsamples > 65535) {
- (void) printf("hwpmc: tunable nsamples=%d out of range.\n",
- pmc_nsamples);
+ (void) printf("hwpmc: tunable \"nsamples\"=%d out of "
+ "range.\n", pmc_nsamples);
pmc_nsamples = PMC_NSAMPLES;
}
+ if (pmc_callchaindepth <= 0 ||
+ pmc_callchaindepth > PMC_CALLCHAIN_DEPTH_MAX) {
+ (void) printf("hwpmc: tunable \"callchaindepth\"=%d out of "
+ "range.\n", pmc_callchaindepth);
+ pmc_callchaindepth = PMC_CALLCHAIN_DEPTH;
+ }
+
md = pmc_md_initialize();
- if (md == NULL || md->pmd_init == NULL)
- return ENOSYS;
+ if (md == NULL)
+ return (ENOSYS);
+
+ KASSERT(md->pmd_nclass >= 1 && md->pmd_npmc >= 1,
+ ("[pmc,%d] no classes or pmcs", __LINE__));
+
+ /* Compute the map from row-indices to classdep pointers. */
+ pmc_rowindex_to_classdep = malloc(sizeof(struct pmc_classdep *) *
+ md->pmd_npmc, M_PMC, M_WAITOK|M_ZERO);
+
+ for (n = 0; n < md->pmd_npmc; n++)
+ pmc_rowindex_to_classdep[n] = NULL;
+ for (ri = c = 0; c < md->pmd_nclass; c++) {
+ pcd = &md->pmd_classdep[c];
+ for (n = 0; n < pcd->pcd_num; n++, ri++)
+ pmc_rowindex_to_classdep[ri] = pcd;
+ }
+
+ KASSERT(ri == md->pmd_npmc,
+ ("[pmc,%d] npmc miscomputed: ri=%d, md->npmc=%d", __LINE__,
+ ri, md->pmd_npmc));
+
+ maxcpu = pmc_cpu_max();
/* allocate space for the per-cpu array */
- MALLOC(pmc_pcpu, struct pmc_cpu **, mp_ncpus * sizeof(struct pmc_cpu *),
- M_PMC, M_WAITOK|M_ZERO);
+ pmc_pcpu = malloc(maxcpu * sizeof(struct pmc_cpu *), M_PMC,
+ M_WAITOK|M_ZERO);
/* per-cpu 'saved values' for managing process-mode PMCs */
MALLOC(pmc_pcpu_saved, pmc_value_t *,
- sizeof(pmc_value_t) * mp_ncpus * md->pmd_npmc, M_PMC, M_WAITOK);
+ sizeof(pmc_value_t) * maxcpu * md->pmd_npmc, M_PMC, M_WAITOK);
- /* perform cpu dependent initialization */
+ /* Perform CPU-dependent initialization. */
pmc_save_cpu_binding(&pb);
- for (cpu = 0; cpu < mp_ncpus; cpu++) {
- if (pmc_cpu_is_disabled(cpu))
+ error = 0;
+ for (cpu = 0; error == 0 && cpu < maxcpu; cpu++) {
+ if (!pmc_cpu_is_active(cpu))
continue;
pmc_select_cpu(cpu);
- if ((error = md->pmd_init(cpu)) != 0)
- break;
+ pmc_pcpu[cpu] = malloc(sizeof(struct pmc_cpu) +
+ md->pmd_npmc * sizeof(struct pmc_hw *), M_PMC,
+ M_WAITOK|M_ZERO);
+ if (md->pmd_pcpu_init)
+ error = md->pmd_pcpu_init(md, cpu);
+ for (n = 0; error == 0 && n < md->pmd_nclass; n++)
+ error = md->pmd_classdep[n].pcd_pcpu_init(md, cpu);
}
pmc_restore_cpu_binding(&pb);
- if (error != 0)
- return error;
+ if (error)
+ return (error);
/* allocate space for the sample array */
- for (cpu = 0; cpu < mp_ncpus; cpu++) {
- if (pmc_cpu_is_disabled(cpu))
+ for (cpu = 0; cpu < maxcpu; cpu++) {
+ if (!pmc_cpu_is_active(cpu))
continue;
- MALLOC(sb, struct pmc_samplebuffer *,
- sizeof(struct pmc_samplebuffer) +
+
+ sb = malloc(sizeof(struct pmc_samplebuffer) +
pmc_nsamples * sizeof(struct pmc_sample), M_PMC,
M_WAITOK|M_ZERO);
-
sb->ps_read = sb->ps_write = sb->ps_samples;
sb->ps_fence = sb->ps_samples + pmc_nsamples;
+
KASSERT(pmc_pcpu[cpu] != NULL,
("[pmc,%d] cpu=%d Null per-cpu data", __LINE__, cpu));
+ sb->ps_callchains = malloc(pmc_callchaindepth * pmc_nsamples *
+ sizeof(uintptr_t), M_PMC, M_WAITOK|M_ZERO);
+
+ for (n = 0, ps = sb->ps_samples; n < pmc_nsamples; n++, ps++)
+ ps->ps_pc = sb->ps_callchains +
+ (n * pmc_callchaindepth);
+
pmc_pcpu[cpu]->pc_sb = sb;
}
@@ -4219,10 +4585,12 @@ pmc_initialize(void)
if (error == 0) {
printf(PMC_MODULE_NAME ":");
for (n = 0; n < (int) md->pmd_nclass; n++) {
- printf(" %s/%d/0x%b",
- pmc_name_of_pmcclass[md->pmd_classes[n].pm_class],
- md->pmd_nclasspmcs[n],
- md->pmd_classes[n].pm_caps,
+ pcd = &md->pmd_classdep[n];
+ printf(" %s/%d/%d/0x%b",
+ pmc_name_of_pmcclass[pcd->pcd_class],
+ pcd->pcd_num,
+ pcd->pcd_width,
+ pcd->pcd_caps,
"\20"
"\1INT\2USR\3SYS\4EDG\5THR"
"\6REA\7WRI\10INV\11QUA\12PRC"
@@ -4231,14 +4599,15 @@ pmc_initialize(void)
printf("\n");
}
- return error;
+ return (error);
}
/* prepare to be unloaded */
static void
pmc_cleanup(void)
{
- int cpu;
+ int c, cpu;
+ unsigned int maxcpu;
struct pmc_ownerhash *ph;
struct pmc_owner *po, *tmp;
struct pmc_binding pb;
@@ -4318,37 +4687,44 @@ pmc_cleanup(void)
KASSERT(pmc_ss_count == 0,
("[pmc,%d] Global SS count not empty", __LINE__));
- /* free the per-cpu sample buffers */
- for (cpu = 0; cpu < mp_ncpus; cpu++) {
- if (pmc_cpu_is_disabled(cpu))
- continue;
- KASSERT(pmc_pcpu[cpu]->pc_sb != NULL,
- ("[pmc,%d] Null cpu sample buffer cpu=%d", __LINE__,
- cpu));
- FREE(pmc_pcpu[cpu]->pc_sb, M_PMC);
- pmc_pcpu[cpu]->pc_sb = NULL;
- }
+ /* do processor and pmc-class dependent cleanup */
+ maxcpu = pmc_cpu_max();
- /* do processor dependent cleanup */
PMCDBG(MOD,INI,3, "%s", "md cleanup");
if (md) {
pmc_save_cpu_binding(&pb);
- for (cpu = 0; cpu < mp_ncpus; cpu++) {
+ for (cpu = 0; cpu < maxcpu; cpu++) {
PMCDBG(MOD,INI,1,"pmc-cleanup cpu=%d pcs=%p",
cpu, pmc_pcpu[cpu]);
- if (pmc_cpu_is_disabled(cpu))
+ if (!pmc_cpu_is_active(cpu) || pmc_pcpu[cpu] == NULL)
continue;
pmc_select_cpu(cpu);
- if (pmc_pcpu[cpu])
- (void) md->pmd_cleanup(cpu);
+ for (c = 0; c < md->pmd_nclass; c++)
+ md->pmd_classdep[c].pcd_pcpu_fini(md, cpu);
+ if (md->pmd_pcpu_fini)
+ md->pmd_pcpu_fini(md, cpu);
}
- FREE(md, M_PMC);
+
+ pmc_md_finalize(md);
+
+ free(md, M_PMC);
md = NULL;
pmc_restore_cpu_binding(&pb);
}
- /* deallocate per-cpu structures */
- FREE(pmc_pcpu, M_PMC);
+ /* Free per-cpu descriptors. */
+ for (cpu = 0; cpu < maxcpu; cpu++) {
+ if (!pmc_cpu_is_active(cpu))
+ continue;
+ KASSERT(pmc_pcpu[cpu]->pc_sb != NULL,
+ ("[pmc,%d] Null cpu sample buffer cpu=%d", __LINE__,
+ cpu));
+ free(pmc_pcpu[cpu]->pc_sb->ps_callchains, M_PMC);
+ free(pmc_pcpu[cpu]->pc_sb, M_PMC);
+ free(pmc_pcpu[cpu], M_PMC);
+ }
+
+ free(pmc_pcpu, M_PMC);
pmc_pcpu = NULL;
FREE(pmc_pcpu_saved, M_PMC);
@@ -4359,6 +4735,11 @@ pmc_cleanup(void)
pmc_pmcdisp = NULL;
}
+ if (pmc_rowindex_to_classdep) {
+ free(pmc_rowindex_to_classdep, M_PMC);
+ pmc_rowindex_to_classdep = NULL;
+ }
+
pmclog_shutdown();
sx_xunlock(&pmc_sx); /* we are done */
@@ -4381,8 +4762,8 @@ load (struct module *module __unused, int cmd, void *arg __unused)
error = pmc_initialize();
if (error != 0)
break;
- PMCDBG(MOD,INI,1, "syscall=%d ncpus=%d",
- pmc_syscall_num, mp_ncpus);
+ PMCDBG(MOD,INI,1, "syscall=%d maxcpu=%d",
+ pmc_syscall_num, pmc_cpu_max());
break;
diff --git a/sys/dev/hwpmc/hwpmc_pentium.c b/sys/dev/hwpmc/hwpmc_pentium.c
index fc26b5252649..0084fa845f64 100644
--- a/sys/dev/hwpmc/hwpmc_pentium.c
+++ b/sys/dev/hwpmc/hwpmc_pentium.c
@@ -44,8 +44,14 @@ __FBSDID("$FreeBSD$");
*/
int
-pmc_initialize_p5(struct pmc_mdep *pmc_mdep)
+pmc_p5_initialize(struct pmc_mdep *pmc_mdep, int ncpus)
+{
+ (void) pmc_mdep; (void) ncpus;
+ return (ENOSYS); /* nothing here yet */
+}
+
+void
+pmc_p5_finalize(struct pmc_mdep *pmc_mdep)
{
(void) pmc_mdep;
- return ENOSYS; /* nothing here yet */
}
diff --git a/sys/dev/hwpmc/hwpmc_pentium.h b/sys/dev/hwpmc/hwpmc_pentium.h
index 36ecc64b60a6..9bb8e781fbe7 100644
--- a/sys/dev/hwpmc/hwpmc_pentium.h
+++ b/sys/dev/hwpmc/hwpmc_pentium.h
@@ -33,7 +33,7 @@
/* Intel Pentium PMCs */
-#define PENTIUM_NPMCS 3 /* 1 TSC + 2 PMCs */
+#define PENTIUM_NPMCS 2
#define PENTIUM_CESR_PC1 (1 << 25)
#define PENTIUM_CESR_CC1_MASK 0x01C00000
#define PENTIUM_CESR_TO_CC1(C) (((C) & 0x07) << 22)
@@ -66,7 +66,8 @@ struct pmc_md_pentium_pmc {
* Prototypes
*/
-int pmc_initialize_p5(struct pmc_mdep *); /* Pentium PMCs */
+int pmc_p5_initialize(struct pmc_mdep *_md, int _ncpus);
+void pmc_p5_finalize(struct pmc_mdep *_md);
#endif /* _KERNEL */
#endif /* _DEV_HWPMC_PENTIUM_H_ */
diff --git a/sys/dev/hwpmc/hwpmc_piv.c b/sys/dev/hwpmc/hwpmc_piv.c
index a6cd3fe6fe22..601395c135e8 100644
--- a/sys/dev/hwpmc/hwpmc_piv.c
+++ b/sys/dev/hwpmc/hwpmc_piv.c
@@ -1,7 +1,11 @@
/*-
- * Copyright (c) 2003-2005 Joseph Koshy
+ * Copyright (c) 2003-2007 Joseph Koshy
+ * Copyright (c) 2007 The FreeBSD Foundation
* All rights reserved.
*
+ * Portions of this software were developed by A. Joseph Koshy under
+ * sponsorship from the FreeBSD Foundation and Google, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -35,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/smp.h>
#include <sys/systm.h>
+#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/md_var.h>
#include <machine/specialreg.h>
@@ -148,11 +153,6 @@ __FBSDID("$FreeBSD$");
* the two logical processors in the package. We keep track of config
* and de-config operations using the CFGFLAGS fields of the per-physical
* cpu state.
- *
- * Handling TSCs
- *
- * TSCs are architectural state and each CPU in a HTT pair has its own
- * TSC register.
*/
#define P4_PMCS() \
@@ -359,28 +359,6 @@ struct p4pmc_descr {
};
static struct p4pmc_descr p4_pmcdesc[P4_NPMCS] = {
-
- /*
- * TSC descriptor
- */
-
- {
- .pm_descr =
- {
- .pd_name = "TSC",
- .pd_class = PMC_CLASS_TSC,
- .pd_caps = PMC_CAP_READ | PMC_CAP_WRITE,
- .pd_width = 64
- },
- .pm_pmcnum = ~0,
- .pm_cccr_msr = ~0,
- .pm_pmc_msr = 0x10,
- },
-
- /*
- * P4 PMCS
- */
-
#define P4_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | PMC_CAP_SYSTEM | \
PMC_CAP_EDGE | PMC_CAP_THRESHOLD | PMC_CAP_READ | PMC_CAP_WRITE | \
PMC_CAP_INVERT | PMC_CAP_QUALIFIER | PMC_CAP_PRECISE | \
@@ -430,8 +408,6 @@ static int p4_system_has_htt;
/*
* Per-CPU data structure for P4 class CPUs
*
- * [common stuff]
- * [19 struct pmc_hw pointers]
* [19 struct pmc_hw structures]
* [45 ESCRs status bytes]
* [per-cpu spin mutex]
@@ -443,8 +419,6 @@ static int p4_system_has_htt;
*/
struct p4_cpu {
- struct pmc_cpu pc_common;
- struct pmc_hw *pc_hwpmcs[P4_NPMCS];
struct pmc_hw pc_p4pmcs[P4_NPMCS];
char pc_escrs[P4_NESCR];
struct mtx pc_mtx; /* spin lock */
@@ -458,19 +432,7 @@ struct p4_cpu {
pmc_value_t pc_pmc_values[P4_NPMCS * P4_NHTT];
};
-/*
- * A 'logical' CPU shares PMC resources with partner 'physical' CPU,
- * except the TSC, which is architectural and hence seperate. The
- * 'logical' CPU descriptor thus has pointers to the physical CPUs
- * descriptor state except for the TSC (rowindex 0) which is not
- * shared.
- */
-
-struct p4_logicalcpu {
- struct pmc_cpu pc_common;
- struct pmc_hw *pc_hwpmcs[P4_NPMCS];
- struct pmc_hw pc_tsc;
-};
+static struct p4_cpu **p4_pcpu;
#define P4_PCPU_PMC_VALUE(PC,RI,CPU) (PC)->pc_pmc_values[(RI)*((CPU) & 1)]
#define P4_PCPU_HW_VALUE(PC,RI,CPU) (PC)->pc_si.pc_hw[(RI)*((CPU) & 1)]
@@ -527,8 +489,8 @@ static int p4_escrdisp[P4_NESCR];
KASSERT(p4_escrdisp[(E)] <= 0, ("[p4,%d] row disposition error",\
__LINE__)); \
atomic_add_int(&p4_escrdisp[(E)], -1); \
- KASSERT(p4_escrdisp[(E)] >= (-mp_ncpus), ("[p4,%d] row " \
- "disposition error", __LINE__)); \
+ KASSERT(p4_escrdisp[(E)] >= (-pmc_cpu_max_active()), \
+ ("[p4,%d] row disposition error", __LINE__)); \
} while (0)
#define P4_ESCR_UNMARK_ROW_STANDALONE(E) do { \
@@ -574,8 +536,8 @@ p4_find_event(enum pmc_event ev)
if (p4_events[n].pm_event == ev)
break;
if (n == P4_NEVENTS)
- return NULL;
- return &p4_events[n];
+ return (NULL);
+ return (&p4_events[n]);
}
/*
@@ -583,19 +545,21 @@ p4_find_event(enum pmc_event ev)
*/
static int
-p4_init(int cpu)
+p4_pcpu_init(struct pmc_mdep *md, int cpu)
{
- int n, phycpu;
char *pescr;
- struct p4_cpu *pcs;
- struct p4_logicalcpu *plcs;
+ int n, first_ri, phycpu;
struct pmc_hw *phw;
+ struct p4_cpu *p4c;
+ struct pmc_cpu *pc, *plc;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p4,%d] insane cpu number %d", __LINE__, cpu));
- PMCDBG(MDP,INI,0, "p4-init cpu=%d logical=%d", cpu,
- pmc_cpu_is_logical(cpu) != 0);
+ PMCDBG(MDP,INI,0, "p4-init cpu=%d is-primary=%d", cpu,
+ pmc_cpu_is_primary(cpu) != 0);
+
+ first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_P4].pcd_ri;
/*
* The two CPUs in an HT pair share their per-cpu state.
@@ -609,62 +573,55 @@ p4_init(int cpu)
* secondary.
*/
- if (pmc_cpu_is_logical(cpu) && (cpu & 1)) {
+ if (!pmc_cpu_is_primary(cpu) && (cpu & 1)) {
p4_system_has_htt = 1;
phycpu = P4_TO_HTT_PRIMARY(cpu);
- pcs = (struct p4_cpu *) pmc_pcpu[phycpu];
- PMCDBG(MDP,INI,1, "p4-init cpu=%d phycpu=%d pcs=%p",
- cpu, phycpu, pcs);
- KASSERT(pcs,
- ("[p4,%d] Null Per-Cpu state cpu=%d phycpu=%d", __LINE__,
- cpu, phycpu));
- if (pcs == NULL) /* decline to init */
- return ENXIO;
+ pc = pmc_pcpu[phycpu];
+ plc = pmc_pcpu[cpu];
- MALLOC(plcs, struct p4_logicalcpu *,
- sizeof(struct p4_logicalcpu), M_PMC, M_WAITOK|M_ZERO);
+ KASSERT(plc != pc, ("[p4,%d] per-cpu config error", __LINE__));
- /* The TSC is architectural state and is not shared */
- plcs->pc_hwpmcs[0] = &plcs->pc_tsc;
- plcs->pc_tsc.phw_state = PMC_PHW_FLAG_IS_ENABLED |
- PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(0) |
- PMC_PHW_FLAG_IS_SHAREABLE;
+ PMCDBG(MDP,INI,1, "p4-init cpu=%d phycpu=%d pc=%p", cpu,
+ phycpu, pc);
+ KASSERT(pc, ("[p4,%d] Null Per-Cpu state cpu=%d phycpu=%d",
+ __LINE__, cpu, phycpu));
- /* Other PMCs are shared with the physical CPU */
- for (n = 1; n < P4_NPMCS; n++)
- plcs->pc_hwpmcs[n] = pcs->pc_hwpmcs[n];
+ /* PMCs are shared with the physical CPU. */
+ for (n = 0; n < P4_NPMCS; n++)
+ plc->pc_hwpmcs[n + first_ri] =
+ pc->pc_hwpmcs[n + first_ri];
- pmc_pcpu[cpu] = (struct pmc_cpu *) plcs;
- return 0;
+ return (0);
}
- MALLOC(pcs, struct p4_cpu *, sizeof(struct p4_cpu), M_PMC,
- M_WAITOK|M_ZERO);
+ p4c = malloc(sizeof(struct p4_cpu), M_PMC, M_WAITOK|M_ZERO);
+
+ if (p4c == NULL)
+ return (ENOMEM);
- if (pcs == NULL)
- return ENOMEM;
- phw = pcs->pc_p4pmcs;
+ pc = pmc_pcpu[cpu];
+
+ KASSERT(pc != NULL, ("[p4,%d] cpu %d null per-cpu", __LINE__, cpu));
+
+ p4_pcpu[cpu] = p4c;
+ phw = p4c->pc_p4pmcs;
for (n = 0; n < P4_NPMCS; n++, phw++) {
phw->phw_state = PMC_PHW_FLAG_IS_ENABLED |
PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(n);
phw->phw_pmc = NULL;
- pcs->pc_hwpmcs[n] = phw;
+ pc->pc_hwpmcs[n + first_ri] = phw;
}
- /* Mark the TSC as shareable */
- pcs->pc_hwpmcs[0]->phw_state |= PMC_PHW_FLAG_IS_SHAREABLE;
-
- pescr = pcs->pc_escrs;
+ pescr = p4c->pc_escrs;
for (n = 0; n < P4_NESCR; n++)
*pescr++ = P4_INVALID_PMC_INDEX;
- pmc_pcpu[cpu] = (struct pmc_cpu *) pcs;
- mtx_init(&pcs->pc_mtx, "p4-pcpu", "pmc-leaf", MTX_SPIN);
+ mtx_init(&p4c->pc_mtx, "p4-pcpu", "pmc-leaf", MTX_SPIN);
- return 0;
+ return (0);
}
/*
@@ -672,74 +629,39 @@ p4_init(int cpu)
*/
static int
-p4_cleanup(int cpu)
+p4_pcpu_fini(struct pmc_mdep *md, int cpu)
{
- int i;
- struct p4_cpu *pcs;
+ int first_ri, i;
+ struct p4_cpu *p4c;
+ struct pmc_cpu *pc;
PMCDBG(MDP,INI,0, "p4-cleanup cpu=%d", cpu);
- if ((pcs = (struct p4_cpu *) pmc_pcpu[cpu]) == NULL)
- return 0;
-
- /* Turn off all PMCs on this CPU */
- for (i = 0; i < P4_NPMCS - 1; i++)
- wrmsr(P4_CCCR_MSR_FIRST + i,
- rdmsr(P4_CCCR_MSR_FIRST + i) & ~P4_CCCR_ENABLE);
-
- /*
- * If the CPU is physical we need to teardown the
- * full MD state.
- */
- if (!P4_CPU_IS_HTT_SECONDARY(cpu))
- mtx_destroy(&pcs->pc_mtx);
+ pc = pmc_pcpu[cpu];
+ first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_P4].pcd_ri;
- FREE(pcs, M_PMC);
+ for (i = 0; i < P4_NPMCS; i++)
+ pc->pc_hwpmcs[i + first_ri] = NULL;
- pmc_pcpu[cpu] = NULL;
+ if (!pmc_cpu_is_primary(cpu) && (cpu & 1))
+ return (0);
- return 0;
-}
+ p4c = p4_pcpu[cpu];
-/*
- * Context switch in.
- */
+ KASSERT(p4c != NULL, ("[p4,%d] NULL pcpu", __LINE__));
-static int
-p4_switch_in(struct pmc_cpu *pc, struct pmc_process *pp)
-{
- (void) pc;
-
- PMCDBG(MDP,SWI,1, "pc=%p pp=%p enable-msr=%d", pc, pp,
- (pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS) != 0);
-
- /* enable the RDPMC instruction */
- if (pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS)
- load_cr4(rcr4() | CR4_PCE);
-
- PMCDBG(MDP,SWI,2, "cr4=0x%x", (uint32_t) rcr4());
-
- return 0;
-}
-
-/*
- * Context switch out.
- */
-
-static int
-p4_switch_out(struct pmc_cpu *pc, struct pmc_process *pp)
-{
- (void) pc;
- (void) pp; /* can be null */
+ /* Turn off all PMCs on this CPU */
+ for (i = 0; i < P4_NPMCS - 1; i++)
+ wrmsr(P4_CCCR_MSR_FIRST + i,
+ rdmsr(P4_CCCR_MSR_FIRST + i) & ~P4_CCCR_ENABLE);
- PMCDBG(MDP,SWO,1, "pc=%p pp=%p", pc, pp);
+ mtx_destroy(&p4c->pc_mtx);
- /* always disallow the RDPMC instruction */
- load_cr4(rcr4() & ~CR4_PCE);
+ free(p4c, M_PMC);
- PMCDBG(MDP,SWO,2, "cr4=0x%x", (uint32_t) rcr4());
+ p4_pcpu[cpu] = NULL;
- return 0;
+ return (0);
}
/*
@@ -749,50 +671,27 @@ p4_switch_out(struct pmc_cpu *pc, struct pmc_process *pp)
static int
p4_read_pmc(int cpu, int ri, pmc_value_t *v)
{
- enum pmc_mode mode;
- struct p4pmc_descr *pd;
struct pmc *pm;
- struct p4_cpu *pc;
- struct pmc_hw *phw;
pmc_value_t tmp;
+ struct p4_cpu *pc;
+ enum pmc_mode mode;
+ struct p4pmc_descr *pd;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p4,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < P4_NPMCS,
("[p4,%d] illegal row-index %d", __LINE__, ri));
-
- if (ri == 0) { /* TSC */
-#ifdef DEBUG
- pc = (struct p4_cpu *) pmc_pcpu[cpu];
- phw = pc->pc_hwpmcs[ri];
- pm = phw->phw_pmc;
-
- KASSERT(pm, ("[p4,%d] cpu=%d ri=%d not configured", __LINE__,
- cpu, ri));
- KASSERT(PMC_TO_CLASS(pm) == PMC_CLASS_TSC,
- ("[p4,%d] cpu=%d ri=%d not a TSC (%d)", __LINE__, cpu, ri,
- PMC_TO_CLASS(pm)));
- KASSERT(PMC_IS_COUNTING_MODE(PMC_TO_MODE(pm)),
- ("[p4,%d] TSC counter in non-counting mode", __LINE__));
-#endif
- *v = rdtsc();
- PMCDBG(MDP,REA,2, "p4-read -> %jx", *v);
- return 0;
- }
-
- pc = (struct p4_cpu *) pmc_pcpu[P4_TO_HTT_PRIMARY(cpu)];
- phw = pc->pc_hwpmcs[ri];
- pd = &p4_pmcdesc[ri];
- pm = phw->phw_pmc;
+ pc = p4_pcpu[P4_TO_HTT_PRIMARY(cpu)];
+ pm = pc->pc_p4pmcs[ri].phw_pmc;
+ pd = &p4_pmcdesc[ri];
KASSERT(pm != NULL,
- ("[p4,%d] No owner for HWPMC [cpu%d,pmc%d]", __LINE__,
- cpu, ri));
+ ("[p4,%d] No owner for HWPMC [cpu%d,pmc%d]", __LINE__, cpu, ri));
KASSERT(pd->pm_descr.pd_class == PMC_TO_CLASS(pm),
("[p4,%d] class mismatch pd %d != id class %d", __LINE__,
- pd->pm_descr.pd_class, PMC_TO_CLASS(pm)));
+ pd->pm_descr.pd_class, PMC_TO_CLASS(pm)));
mode = PMC_TO_MODE(pm);
@@ -818,7 +717,8 @@ p4_read_pmc(int cpu, int ri, pmc_value_t *v)
*v = tmp;
PMCDBG(MDP,REA,2, "p4-read -> %jx", *v);
- return 0;
+
+ return (0);
}
/*
@@ -834,34 +734,13 @@ p4_write_pmc(int cpu, int ri, pmc_value_t v)
const struct pmc_hw *phw;
const struct p4pmc_descr *pd;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[amd,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < P4_NPMCS,
("[amd,%d] illegal row-index %d", __LINE__, ri));
-
- /*
- * The P4's TSC register is writeable, but we don't allow a
- * write as changing the TSC's value could interfere with
- * timekeeping and other system functions.
- */
- if (ri == 0) {
-#ifdef DEBUG
- pc = (struct p4_cpu *) pmc_pcpu[cpu];
- phw = pc->pc_hwpmcs[ri];
- pm = phw->phw_pmc;
- KASSERT(pm, ("[p4,%d] cpu=%d ri=%d not configured", __LINE__,
- cpu, ri));
- KASSERT(PMC_TO_CLASS(pm) == PMC_CLASS_TSC,
- ("[p4,%d] cpu=%d ri=%d not a TSC (%d)", __LINE__,
- cpu, ri, PMC_TO_CLASS(pm)));
-#endif
- return 0;
- }
-
- /* Shared PMCs */
- pc = (struct p4_cpu *) pmc_pcpu[P4_TO_HTT_PRIMARY(cpu)];
- phw = pc->pc_hwpmcs[ri];
+ pc = p4_pcpu[P4_TO_HTT_PRIMARY(cpu)];
+ phw = &pc->pc_p4pmcs[ri];
pm = phw->phw_pmc;
pd = &p4_pmcdesc[ri];
@@ -887,7 +766,7 @@ p4_write_pmc(int cpu, int ri, pmc_value_t v)
else
P4_PCPU_PMC_VALUE(pc,ri,cpu) = v;
- return 0;
+ return (0);
}
/*
@@ -908,27 +787,16 @@ p4_config_pmc(int cpu, int ri, struct pmc *pm)
struct p4_cpu *pc;
int cfgflags, cpuflag;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p4,%d] illegal CPU %d", __LINE__, cpu));
+
KASSERT(ri >= 0 && ri < P4_NPMCS,
("[p4,%d] illegal row-index %d", __LINE__, ri));
PMCDBG(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm);
- if (ri == 0) { /* TSC */
- pc = (struct p4_cpu *) pmc_pcpu[cpu];
- phw = pc->pc_hwpmcs[ri];
-
- KASSERT(pm == NULL || phw->phw_pmc == NULL,
- ("[p4,%d] hwpmc doubly config'ed", __LINE__));
- phw->phw_pmc = pm;
- return 0;
- }
-
- /* Shared PMCs */
-
- pc = (struct p4_cpu *) pmc_pcpu[P4_TO_HTT_PRIMARY(cpu)];
- phw = pc->pc_hwpmcs[ri];
+ pc = p4_pcpu[P4_TO_HTT_PRIMARY(cpu)];
+ phw = &pc->pc_p4pmcs[ri];
KASSERT(pm == NULL || phw->phw_pmc == NULL ||
(p4_system_has_htt && phw->phw_pmc == pm),
@@ -971,7 +839,7 @@ p4_config_pmc(int cpu, int ri, struct pmc *pm)
mtx_unlock_spin(&pc->pc_mtx);
- return 0;
+ return (0);
}
/*
@@ -981,19 +849,22 @@ p4_config_pmc(int cpu, int ri, struct pmc *pm)
static int
p4_get_config(int cpu, int ri, struct pmc **ppm)
{
- struct p4_cpu *pc;
- struct pmc_hw *phw;
int cfgflags;
+ struct p4_cpu *pc;
- pc = (struct p4_cpu *) pmc_pcpu[P4_TO_HTT_PRIMARY(cpu)];
- phw = pc->pc_hwpmcs[ri];
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[p4,%d] illegal CPU %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < P4_NPMCS,
+ ("[p4,%d] illegal row-index %d", __LINE__, ri));
+
+ pc = p4_pcpu[P4_TO_HTT_PRIMARY(cpu)];
mtx_lock_spin(&pc->pc_mtx);
cfgflags = P4_PCPU_GET_CFGFLAGS(pc,ri);
mtx_unlock_spin(&pc->pc_mtx);
if (cfgflags & P4_CPU_TO_FLAG(cpu))
- *ppm = phw->phw_pmc; /* PMC config'ed on this CPU */
+ *ppm = pc->pc_p4pmcs[ri].phw_pmc; /* PMC config'ed on this CPU */
else
*ppm = NULL;
@@ -1045,7 +916,7 @@ p4_allocate_pmc(int cpu, int ri, struct pmc *pm,
struct p4_event_descr *pevent;
const struct p4pmc_descr *pd;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p4,%d] illegal CPU %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < P4_NPMCS,
("[p4,%d] illegal row-index value %d", __LINE__, ri));
@@ -1058,20 +929,12 @@ p4_allocate_pmc(int cpu, int ri, struct pmc *pm,
/* check class */
if (pd->pm_descr.pd_class != a->pm_class)
- return EINVAL;
+ return (EINVAL);
/* check requested capabilities */
caps = a->pm_caps;
if ((pd->pm_descr.pd_caps & caps) != caps)
- return EPERM;
-
- if (pd->pm_descr.pd_class == PMC_CLASS_TSC) {
- /* TSC's are always allocated in system-wide counting mode */
- if (a->pm_ev != PMC_EV_TSC_TSC ||
- a->pm_mode != PMC_MODE_SC)
- return EINVAL;
- return 0;
- }
+ return (EPERM);
/*
* If the system has HTT enabled, and the desired allocation
@@ -1082,7 +945,7 @@ p4_allocate_pmc(int cpu, int ri, struct pmc *pm,
if (p4_system_has_htt &&
PMC_IS_VIRTUAL_MODE(PMC_TO_MODE(pm)) &&
pmc_getrowdisp(ri) != 0)
- return EBUSY;
+ return (EBUSY);
KASSERT(pd->pm_descr.pd_class == PMC_CLASS_P4,
("[p4,%d] unknown PMC class %d", __LINE__,
@@ -1090,10 +953,10 @@ p4_allocate_pmc(int cpu, int ri, struct pmc *pm,
if (pm->pm_event < PMC_EV_P4_FIRST ||
pm->pm_event > PMC_EV_P4_LAST)
- return EINVAL;
+ return (EINVAL);
if ((pevent = p4_find_event(pm->pm_event)) == NULL)
- return ESRCH;
+ return (ESRCH);
PMCDBG(MDP,ALL,2, "pevent={ev=%d,escrsel=0x%x,cccrsel=0x%x,isti=%d}",
pevent->pm_event, pevent->pm_escr_eventselect,
@@ -1108,9 +971,9 @@ p4_allocate_pmc(int cpu, int ri, struct pmc *pm,
if (P4_EVENT_IS_TI(pevent) &&
PMC_IS_VIRTUAL_MODE(PMC_TO_MODE(pm)) &&
p4_system_has_htt)
- return EINVAL;
+ return (EINVAL);
- pc = (struct p4_cpu *) pmc_pcpu[P4_TO_HTT_PRIMARY(cpu)];
+ pc = p4_pcpu[P4_TO_HTT_PRIMARY(cpu)];
found = 0;
@@ -1166,7 +1029,7 @@ p4_allocate_pmc(int cpu, int ri, struct pmc *pm,
}
if (found == 0)
- return ESRCH;
+ return (ESRCH);
KASSERT((int) escr >= 0 && escr < P4_NESCR,
("[p4,%d] illegal ESCR value %d", __LINE__, escr));
@@ -1239,7 +1102,7 @@ p4_allocate_pmc(int cpu, int ri, struct pmc *pm,
"escr=%d escrmsr=0x%x escrval=0x%x", pevent->pm_cccr_select,
cccrvalue, escr, pm->pm_md.pm_p4.pm_p4_escrmsr, escrvalue);
- return 0;
+ return (0);
}
/*
@@ -1250,21 +1113,19 @@ static int
p4_release_pmc(int cpu, int ri, struct pmc *pm)
{
enum pmc_p4escr escr;
- struct pmc_hw *phw;
struct p4_cpu *pc;
- if (p4_pmcdesc[ri].pm_descr.pd_class == PMC_CLASS_TSC)
- return 0;
+ KASSERT(ri >= 0 && ri < P4_NPMCS,
+ ("[p4,%d] illegal row-index %d", __LINE__, ri));
escr = pm->pm_md.pm_p4.pm_p4_escr;
PMCDBG(MDP,REL,1, "p4-release cpu=%d ri=%d escr=%d", cpu, ri, escr);
if (PMC_IS_SYSTEM_MODE(PMC_TO_MODE(pm))) {
- pc = (struct p4_cpu *) pmc_pcpu[P4_TO_HTT_PRIMARY(cpu)];
- phw = pc->pc_hwpmcs[ri];
+ pc = p4_pcpu[P4_TO_HTT_PRIMARY(cpu)];
- KASSERT(phw->phw_pmc == NULL,
+ KASSERT(pc->pc_p4pmcs[ri].phw_pmc == NULL,
("[p4,%d] releasing configured PMC ri=%d", __LINE__, ri));
P4_ESCR_UNMARK_ROW_STANDALONE(escr);
@@ -1275,7 +1136,7 @@ p4_release_pmc(int cpu, int ri, struct pmc *pm)
} else
P4_ESCR_UNMARK_ROW_THREAD(escr);
- return 0;
+ return (0);
}
/*
@@ -1286,31 +1147,25 @@ static int
p4_start_pmc(int cpu, int ri)
{
int rc;
- uint32_t cccrvalue, cccrtbits, escrvalue, escrmsr, escrtbits;
struct pmc *pm;
struct p4_cpu *pc;
- struct pmc_hw *phw;
struct p4pmc_descr *pd;
+ uint32_t cccrvalue, cccrtbits, escrvalue, escrmsr, escrtbits;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p4,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < P4_NPMCS,
("[p4,%d] illegal row-index %d", __LINE__, ri));
- pc = (struct p4_cpu *) pmc_pcpu[P4_TO_HTT_PRIMARY(cpu)];
- phw = pc->pc_hwpmcs[ri];
- pm = phw->phw_pmc;
- pd = &p4_pmcdesc[ri];
+ pc = p4_pcpu[P4_TO_HTT_PRIMARY(cpu)];
+ pm = pc->pc_p4pmcs[ri].phw_pmc;
+ pd = &p4_pmcdesc[ri];
KASSERT(pm != NULL,
- ("[p4,%d] starting cpu%d,pmc%d with null pmc", __LINE__,
- cpu, ri));
+ ("[p4,%d] starting cpu%d,pmc%d with null pmc", __LINE__, cpu, ri));
PMCDBG(MDP,STA,1, "p4-start cpu=%d ri=%d", cpu, ri);
- if (pd->pm_descr.pd_class == PMC_CLASS_TSC) /* TSC are always on */
- return 0;
-
KASSERT(pd->pm_descr.pd_class == PMC_CLASS_P4,
("[p4,%d] wrong PMC class %d", __LINE__,
pd->pm_descr.pd_class));
@@ -1426,7 +1281,7 @@ p4_start_pmc(int cpu, int ri)
ri, pm->pm_md.pm_p4.pm_p4_escr, escrmsr, escrvalue,
cccrvalue, P4_PCPU_HW_VALUE(pc,ri,cpu));
- return 0;
+ return (0);
}
/*
@@ -1440,27 +1295,17 @@ p4_stop_pmc(int cpu, int ri)
uint32_t cccrvalue, cccrtbits, escrvalue, escrmsr, escrtbits;
struct pmc *pm;
struct p4_cpu *pc;
- struct pmc_hw *phw;
struct p4pmc_descr *pd;
pmc_value_t tmp;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p4,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < P4_NPMCS,
("[p4,%d] illegal row index %d", __LINE__, ri));
- pd = &p4_pmcdesc[ri];
-
- if (pd->pm_descr.pd_class == PMC_CLASS_TSC)
- return 0;
-
- pc = (struct p4_cpu *) pmc_pcpu[P4_TO_HTT_PRIMARY(cpu)];
- phw = pc->pc_hwpmcs[ri];
-
- KASSERT(phw != NULL,
- ("[p4,%d] null phw for cpu%d, ri%d", __LINE__, cpu, ri));
-
- pm = phw->phw_pmc;
+ pd = &p4_pmcdesc[ri];
+ pc = p4_pcpu[P4_TO_HTT_PRIMARY(cpu)];
+ pm = pc->pc_p4pmcs[ri].phw_pmc;
KASSERT(pm != NULL,
("[p4,%d] null pmc for cpu%d, ri%d", __LINE__, cpu, ri));
@@ -1470,7 +1315,7 @@ p4_stop_pmc(int cpu, int ri)
if (PMC_IS_SYSTEM_MODE(PMC_TO_MODE(pm))) {
wrmsr(pd->pm_cccr_msr,
pm->pm_md.pm_p4.pm_p4_cccrvalue & ~P4_CCCR_ENABLE);
- return 0;
+ return (0);
}
/*
@@ -1478,7 +1323,7 @@ p4_stop_pmc(int cpu, int ri)
*
* On HTT machines, this PMC may be in use by two threads
* running on two logical CPUS. Thus we look at the
- * 'pm_runcount' field and only turn off the appropriate TO/T1
+ * 'runcount' field and only turn off the appropriate TO/T1
* bits (and keep the PMC running) if two logical CPUs were
* using the PMC.
*
@@ -1562,25 +1407,25 @@ p4_stop_pmc(int cpu, int ri)
*/
static int
-p4_intr(int cpu, uintptr_t eip, int usermode)
+p4_intr(int cpu, struct trapframe *tf)
{
- int i, did_interrupt, error, ri;
uint32_t cccrval, ovf_mask, ovf_partner;
+ int did_interrupt, error, ri;
struct p4_cpu *pc;
- struct pmc_hw *phw;
struct pmc *pm;
pmc_value_t v;
- PMCDBG(MDP,INT, 1, "cpu=%d eip=%p um=%d", cpu, (void *) eip, usermode);
+ PMCDBG(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf,
+ TRAPF_USERMODE(tf));
- pc = (struct p4_cpu *) pmc_pcpu[P4_TO_HTT_PRIMARY(cpu)];
+ pc = p4_pcpu[P4_TO_HTT_PRIMARY(cpu)];
ovf_mask = P4_CPU_IS_HTT_SECONDARY(cpu) ?
P4_CCCR_OVF_PMI_T1 : P4_CCCR_OVF_PMI_T0;
ovf_mask |= P4_CCCR_OVF;
if (p4_system_has_htt)
- ovf_partner = P4_CPU_IS_HTT_SECONDARY(cpu) ? P4_CCCR_OVF_PMI_T0 :
- P4_CCCR_OVF_PMI_T1;
+ ovf_partner = P4_CPU_IS_HTT_SECONDARY(cpu) ?
+ P4_CCCR_OVF_PMI_T0 : P4_CCCR_OVF_PMI_T1;
else
ovf_partner = 0;
did_interrupt = 0;
@@ -1592,9 +1437,7 @@ p4_intr(int cpu, uintptr_t eip, int usermode)
* Loop through all CCCRs, looking for ones that have
* interrupted this CPU.
*/
- for (i = 0; i < P4_NPMCS-1; i++) {
-
- ri = i + 1; /* row index */
+ for (ri = 0; ri < P4_NPMCS; ri++) {
/*
* Check if our partner logical CPU has already marked
@@ -1610,14 +1453,14 @@ p4_intr(int cpu, uintptr_t eip, int usermode)
* Ignore de-configured or stopped PMCs.
* Ignore PMCs not in sampling mode.
*/
- phw = pc->pc_hwpmcs[ri];
- pm = phw->phw_pmc;
+ pm = pc->pc_p4pmcs[ri].phw_pmc;
if (pm == NULL ||
pm->pm_state != PMC_STATE_RUNNING ||
!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) {
continue;
}
- (void) pmc_process_interrupt(cpu, pm, eip, usermode);
+ (void) pmc_process_interrupt(cpu, pm, tf,
+ TRAPF_USERMODE(tf));
continue;
}
@@ -1626,7 +1469,7 @@ p4_intr(int cpu, uintptr_t eip, int usermode)
* and the OVF_Tx bit for this logical
* processor being set.
*/
- cccrval = rdmsr(P4_CCCR_MSR_FIRST + i);
+ cccrval = rdmsr(P4_CCCR_MSR_FIRST + ri);
if ((cccrval & ovf_mask) != ovf_mask)
continue;
@@ -1640,13 +1483,13 @@ p4_intr(int cpu, uintptr_t eip, int usermode)
if (p4_system_has_htt && (cccrval & ovf_partner))
P4_PCPU_SET_INTRFLAG(pc, ri, 1);
- v = rdmsr(P4_PERFCTR_MSR_FIRST + i);
+ v = rdmsr(P4_PERFCTR_MSR_FIRST + ri);
PMCDBG(MDP,INT, 2, "ri=%d v=%jx", ri, v);
/* Stop the counter, and reset the overflow bit */
cccrval &= ~(P4_CCCR_OVF | P4_CCCR_ENABLE);
- wrmsr(P4_CCCR_MSR_FIRST + i, cccrval);
+ wrmsr(P4_CCCR_MSR_FIRST + ri, cccrval);
did_interrupt = 1;
@@ -1654,8 +1497,7 @@ p4_intr(int cpu, uintptr_t eip, int usermode)
* Ignore de-configured or stopped PMCs. Ignore PMCs
* not in sampling mode.
*/
- phw = pc->pc_hwpmcs[ri];
- pm = phw->phw_pmc;
+ pm = pc->pc_p4pmcs[ri].phw_pmc;
if (pm == NULL ||
pm->pm_state != PMC_STATE_RUNNING ||
@@ -1667,7 +1509,8 @@ p4_intr(int cpu, uintptr_t eip, int usermode)
* Process the interrupt. Re-enable the PMC if
* processing was successful.
*/
- error = pmc_process_interrupt(cpu, pm, eip, usermode);
+ error = pmc_process_interrupt(cpu, pm, tf,
+ TRAPF_USERMODE(tf));
/*
* Only the first processor executing the NMI handler
@@ -1676,9 +1519,9 @@ p4_intr(int cpu, uintptr_t eip, int usermode)
*/
v = P4_RELOAD_COUNT_TO_PERFCTR_VALUE(
pm->pm_sc.pm_reloadcount);
- wrmsr(P4_PERFCTR_MSR_FIRST + i, v);
+ wrmsr(P4_PERFCTR_MSR_FIRST + ri, v);
if (error == 0)
- wrmsr(P4_CCCR_MSR_FIRST + i,
+ wrmsr(P4_CCCR_MSR_FIRST + ri,
cccrval | P4_CCCR_ENABLE);
}
@@ -1698,7 +1541,7 @@ p4_intr(int cpu, uintptr_t eip, int usermode)
atomic_add_int(did_interrupt ? &pmc_stats.pm_intr_processed :
&pmc_stats.pm_intr_ignored, 1);
- return did_interrupt;
+ return (did_interrupt);
}
/*
@@ -1711,10 +1554,9 @@ p4_describe(int cpu, int ri, struct pmc_info *pi,
{
int error;
size_t copied;
- struct pmc_hw *phw;
const struct p4pmc_descr *pd;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p4,%d] illegal CPU %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < P4_NPMCS,
("[p4,%d] row-index %d out of range", __LINE__, ri));
@@ -1722,26 +1564,25 @@ p4_describe(int cpu, int ri, struct pmc_info *pi,
PMCDBG(MDP,OPS,1,"p4-describe cpu=%d ri=%d", cpu, ri);
if (P4_CPU_IS_HTT_SECONDARY(cpu))
- return EINVAL;
+ return (EINVAL);
- phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
pd = &p4_pmcdesc[ri];
if ((error = copystr(pd->pm_descr.pd_name, pi->pm_name,
- PMC_NAME_MAX, &copied)) != 0)
- return error;
+ PMC_NAME_MAX, &copied)) != 0)
+ return (error);
pi->pm_class = pd->pm_descr.pd_class;
- if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
+ if (p4_pcpu[cpu]->pc_p4pmcs[ri].phw_state & PMC_PHW_FLAG_IS_ENABLED) {
pi->pm_enabled = TRUE;
- *ppmc = phw->phw_pmc;
+ *ppmc = p4_pcpu[cpu]->pc_p4pmcs[ri].phw_pmc;
} else {
pi->pm_enabled = FALSE;
*ppmc = NULL;
}
- return 0;
+ return (0);
}
/*
@@ -1763,41 +1604,52 @@ p4_get_msr(int ri, uint32_t *msr)
int
-pmc_initialize_p4(struct pmc_mdep *pmc_mdep)
+pmc_p4_initialize(struct pmc_mdep *md, int ncpus)
{
+ struct pmc_classdep *pcd;
struct p4_event_descr *pe;
+ KASSERT(md != NULL, ("[p4,%d] md is NULL", __LINE__));
KASSERT(strcmp(cpu_vendor, "GenuineIntel") == 0,
("[p4,%d] Initializing non-intel processor", __LINE__));
PMCDBG(MDP,INI,1, "%s", "p4-initialize");
- switch (pmc_mdep->pmd_cputype) {
+ /* Allocate space for pointers to per-cpu descriptors. */
+ p4_pcpu = malloc(sizeof(struct p4_cpu **) * ncpus, M_PMC,
+ M_ZERO|M_WAITOK);
+
+ /* Fill in the class dependent descriptor. */
+ pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_P4];
+
+ switch (md->pmd_cputype) {
case PMC_CPU_INTEL_PIV:
- pmc_mdep->pmd_npmc = P4_NPMCS;
- pmc_mdep->pmd_classes[1].pm_class = PMC_CLASS_P4;
- pmc_mdep->pmd_classes[1].pm_caps = P4_PMC_CAPS;
- pmc_mdep->pmd_classes[1].pm_width = 40;
- pmc_mdep->pmd_nclasspmcs[1] = 18;
+ pcd->pcd_caps = P4_PMC_CAPS;
+ pcd->pcd_class = PMC_CLASS_P4;
+ pcd->pcd_num = P4_NPMCS;
+ pcd->pcd_ri = md->pmd_npmc;
+ pcd->pcd_width = 40;
- pmc_mdep->pmd_init = p4_init;
- pmc_mdep->pmd_cleanup = p4_cleanup;
- pmc_mdep->pmd_switch_in = p4_switch_in;
- pmc_mdep->pmd_switch_out = p4_switch_out;
- pmc_mdep->pmd_read_pmc = p4_read_pmc;
- pmc_mdep->pmd_write_pmc = p4_write_pmc;
- pmc_mdep->pmd_config_pmc = p4_config_pmc;
- pmc_mdep->pmd_get_config = p4_get_config;
- pmc_mdep->pmd_allocate_pmc = p4_allocate_pmc;
- pmc_mdep->pmd_release_pmc = p4_release_pmc;
- pmc_mdep->pmd_start_pmc = p4_start_pmc;
- pmc_mdep->pmd_stop_pmc = p4_stop_pmc;
- pmc_mdep->pmd_intr = p4_intr;
- pmc_mdep->pmd_describe = p4_describe;
- pmc_mdep->pmd_get_msr = p4_get_msr; /* i386 */
+ pcd->pcd_allocate_pmc = p4_allocate_pmc;
+ pcd->pcd_config_pmc = p4_config_pmc;
+ pcd->pcd_describe = p4_describe;
+ pcd->pcd_get_config = p4_get_config;
+ pcd->pcd_get_msr = p4_get_msr;
+ pcd->pcd_pcpu_fini = p4_pcpu_fini;
+ pcd->pcd_pcpu_init = p4_pcpu_init;
+ pcd->pcd_read_pmc = p4_read_pmc;
+ pcd->pcd_release_pmc = p4_release_pmc;
+ pcd->pcd_start_pmc = p4_start_pmc;
+ pcd->pcd_stop_pmc = p4_stop_pmc;
+ pcd->pcd_write_pmc = p4_write_pmc;
- /* model specific munging */
+ md->pmd_pcpu_fini = NULL;
+ md->pmd_pcpu_init = NULL;
+ md->pmd_intr = p4_intr;
+ md->pmd_npmc += P4_NPMCS;
+
+ /* model specific configuration */
if ((cpu_id & 0xFFF) < 0xF27) {
/*
@@ -1817,5 +1669,26 @@ pmc_initialize_p4(struct pmc_mdep *pmc_mdep)
return ENOSYS;
}
- return 0;
+ return (0);
+}
+
+void
+pmc_p4_finalize(struct pmc_mdep *md)
+{
+#if defined(INVARIANTS)
+ int i, ncpus;
+#endif
+
+ KASSERT(p4_pcpu != NULL,
+ ("[p4,%d] NULL p4_pcpu", __LINE__));
+
+#if defined(INVARIANTS)
+ ncpus = pmc_cpu_max();
+ for (i = 0; i < ncpus; i++)
+ KASSERT(p4_pcpu[i] == NULL, ("[p4,%d] non-null pcpu %d",
+ __LINE__, i));
+#endif
+
+ free(p4_pcpu, M_PMC);
+ p4_pcpu = NULL;
}
diff --git a/sys/dev/hwpmc/hwpmc_piv.h b/sys/dev/hwpmc/hwpmc_piv.h
index 0837b263b639..ebde966167f5 100644
--- a/sys/dev/hwpmc/hwpmc_piv.h
+++ b/sys/dev/hwpmc/hwpmc_piv.h
@@ -33,7 +33,7 @@
/* Intel P4 PMCs */
-#define P4_NPMCS 19 /* 1 TSC + 18 PMCS */
+#define P4_NPMCS 18
#define P4_NESCR 45
#define P4_INVALID_PMC_INDEX -1
#define P4_MAX_ESCR_PER_EVENT 2
@@ -118,7 +118,8 @@ struct pmc_md_p4_pmc {
* Prototypes
*/
-int pmc_initialize_p4(struct pmc_mdep *); /* Pentium IV PMCs */
+int pmc_p4_initialize(struct pmc_mdep *_md, int _ncpus);
+void pmc_p4_finalize(struct pmc_mdep *md);
#endif /* _KERNEL */
-#endif /* _MACHINE_PMC_MDEP_H */
+#endif /* _DEV_HWPMC_PIV_H_ */
diff --git a/sys/dev/hwpmc/hwpmc_powerpc.c b/sys/dev/hwpmc/hwpmc_powerpc.c
index af905b66924e..ce1caf69e108 100644
--- a/sys/dev/hwpmc/hwpmc_powerpc.c
+++ b/sys/dev/hwpmc/hwpmc_powerpc.c
@@ -38,3 +38,29 @@ pmc_md_initialize()
{
return NULL;
}
+
+void
+pmc_md_finalize(struct pmc_mdep *md)
+{
+ (void) md;
+}
+
+int
+pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
+ struct trapframe *tf)
+{
+ (void) cc;
+ (void) maxsamples;
+ (void) tf;
+ return (0);
+}
+
+int
+pmc_save_user_callchain(uintptr_t *cc, int maxsamples,
+ struct trapframe *tf)
+{
+ (void) cc;
+ (void) maxsamples;
+ (void) tf;
+ return (0);
+}
diff --git a/sys/dev/hwpmc/hwpmc_ppro.c b/sys/dev/hwpmc/hwpmc_ppro.c
index 993a2bf26560..deb09c75a9da 100644
--- a/sys/dev/hwpmc/hwpmc_ppro.c
+++ b/sys/dev/hwpmc/hwpmc_ppro.c
@@ -1,7 +1,11 @@
/*-
- * Copyright (c) 2003-2005 Joseph Koshy
+ * Copyright (c) 2003-2005,2008 Joseph Koshy
+ * Copyright (c) 2007 The FreeBSD Foundation
* All rights reserved.
*
+ * Portions of this software were developed by A. Joseph Koshy under
+ * sponsorship from the FreeBSD Foundation and Google, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -35,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/smp.h>
#include <sys/systm.h>
+#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/md_var.h>
#include <machine/pmc_mdep.h>
@@ -68,19 +73,6 @@ struct p6pmc_descr {
static struct p6pmc_descr p6_pmcdesc[P6_NPMCS] = {
- /* TSC */
- {
- .pm_descr =
- {
- .pd_name = "TSC",
- .pd_class = PMC_CLASS_TSC,
- .pd_caps = PMC_CAP_READ,
- .pd_width = 64
- },
- .pm_pmc_msr = 0x10,
- .pm_evsel_msr = ~0
- },
-
#define P6_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | PMC_CAP_SYSTEM | \
PMC_CAP_EDGE | PMC_CAP_THRESHOLD | PMC_CAP_READ | PMC_CAP_WRITE | \
PMC_CAP_INVERT | PMC_CAP_QUALIFIER)
@@ -116,6 +108,11 @@ static enum pmc_cputype p6_cputype;
/*
* P6 Event descriptor
+ *
+ * The 'pm_flags' field has the following structure:
+ * - The upper 4 bits are used to track which counter an event is valid on.
+ * - The lower bits form a bitmask of flags indicating support for the event
+ * on a given CPU.
*/
struct p6_event_descr {
@@ -125,6 +122,23 @@ struct p6_event_descr {
uint32_t pm_unitmask;
};
+#define P6F_CTR(C) (1 << (28 + (C)))
+#define P6F_CTR0 P6F_CTR(0)
+#define P6F_CTR1 P6F_CTR(1)
+#define P6F(CPU) (1 << ((CPU) - PMC_CPU_INTEL_P6))
+#define _P6F(C) P6F(PMC_CPU_INTEL_##C)
+#define P6F_P6 _P6F(P6)
+#define P6F_CL _P6F(CL)
+#define P6F_PII _P6F(PII)
+#define P6F_PIII _P6F(PIII)
+#define P6F_PM _P6F(PM)
+#define P6F_ALL_CPUS (P6F_P6 | P6F_PII | P6F_CL | P6F_PIII | P6F_PM)
+#define P6F_ALL_CTRS (P6F_CTR0 | P6F_CTR1)
+#define P6F_ALL (P6F_ALL_CPUS | P6F_ALL_CTRS)
+
+#define P6_EVENT_VALID_FOR_CPU(P,CPU) ((P)->pm_flags & P6F(CPU))
+#define P6_EVENT_VALID_FOR_CTR(P,CTR) ((P)->pm_flags & P6F_CTR(CTR))
+
static const struct p6_event_descr p6_events[] = {
#define P6_EVDESCR(NAME, EVSEL, FLAGS, UMASK) \
@@ -135,20 +149,6 @@ static const struct p6_event_descr p6_events[] = {
.pm_unitmask = (UMASK) \
}
-#define P6F_P6 (1 << PMC_CPU_INTEL_P6)
-#define P6F_CL (1 << PMC_CPU_INTEL_CL)
-#define P6F_PII (1 << PMC_CPU_INTEL_PII)
-#define P6F_PIII (1 << PMC_CPU_INTEL_PIII)
-#define P6F_PM (1 << PMC_CPU_INTEL_PM)
-#define P6F_CTR0 0x0001
-#define P6F_CTR1 0x0002
-#define P6F_ALL_CPUS (P6F_P6 | P6F_PII | P6F_CL | P6F_PIII | P6F_PM)
-#define P6F_ALL_CTRS (P6F_CTR0 | P6F_CTR1)
-#define P6F_ALL (P6F_ALL_CPUS | P6F_ALL_CTRS)
-
-#define P6_EVENT_VALID_FOR_CPU(P,CPU) ((P)->pm_flags & (1 << (CPU)))
-#define P6_EVENT_VALID_FOR_CTR(P,CTR) ((P)->pm_flags & (1 << (CTR)))
-
P6_EVDESCR(DATA_MEM_REFS, 0x43, P6F_ALL, 0x00),
P6_EVDESCR(DCU_LINES_IN, 0x45, P6F_ALL, 0x00),
P6_EVDESCR(DCU_M_LINES_IN, 0x46, P6F_ALL, 0x00),
@@ -293,12 +293,12 @@ p6_find_event(enum pmc_event ev)
*/
struct p6_cpu {
- struct pmc_cpu pc_common;
- struct pmc_hw *pc_hwpmcs[P6_NPMCS];
struct pmc_hw pc_p6pmcs[P6_NPMCS];
uint32_t pc_state;
};
+static struct p6_cpu **p6_pcpu;
+
/*
* If CTR1 is active, we need to keep the 'EN' bit if CTR0 set,
* with the rest of CTR0 being zero'ed out.
@@ -325,105 +325,83 @@ struct p6_cpu {
} while (0)
static int
-p6_init(int cpu)
+p6_pcpu_init(struct pmc_mdep *md, int cpu)
{
- int n;
- struct p6_cpu *pcs;
+ int first_ri, n;
+ struct p6_cpu *p6c;
+ struct pmc_cpu *pc;
struct pmc_hw *phw;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p6,%d] bad cpu %d", __LINE__, cpu));
PMCDBG(MDP,INI,0,"p6-init cpu=%d", cpu);
- MALLOC(pcs, struct p6_cpu *, sizeof(struct p6_cpu), M_PMC,
- M_WAITOK|M_ZERO);
+ p6c = malloc(sizeof (struct p6_cpu), M_PMC, M_WAITOK|M_ZERO);
+ pc = pmc_pcpu[cpu];
+
+ KASSERT(pc != NULL, ("[p6,%d] cpu %d null per-cpu", __LINE__, cpu));
- phw = pcs->pc_p6pmcs;
+ phw = p6c->pc_p6pmcs;
+ p6_pcpu[cpu] = p6c;
+
+ first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_P6].pcd_ri;
for (n = 0; n < P6_NPMCS; n++, phw++) {
phw->phw_state = PMC_PHW_FLAG_IS_ENABLED |
PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(n);
phw->phw_pmc = NULL;
- pcs->pc_hwpmcs[n] = phw;
+ pc->pc_hwpmcs[n + first_ri] = phw;
}
- /* Mark the TSC as shareable */
- pcs->pc_hwpmcs[0]->phw_state |= PMC_PHW_FLAG_IS_SHAREABLE;
-
- pmc_pcpu[cpu] = (struct pmc_cpu *) pcs;
-
- return 0;
+ return (0);
}
static int
-p6_cleanup(int cpu)
+p6_pcpu_fini(struct pmc_mdep *md, int cpu)
{
- struct pmc_cpu *pcs;
+ int first_ri, n;
+ struct p6_cpu *p6c;
+ struct pmc_cpu *pc;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p6,%d] bad cpu %d", __LINE__, cpu));
PMCDBG(MDP,INI,0,"p6-cleanup cpu=%d", cpu);
- if ((pcs = pmc_pcpu[cpu]) != NULL)
- FREE(pcs, M_PMC);
- pmc_pcpu[cpu] = NULL;
+ p6c = p6_pcpu[cpu];
+ p6_pcpu[cpu] = NULL;
- return 0;
-}
-
-static int
-p6_switch_in(struct pmc_cpu *pc, struct pmc_process *pp)
-{
- (void) pc;
+ KASSERT(p6c != NULL, ("[p6,%d] null pcpu", __LINE__));
- PMCDBG(MDP,SWI,1, "pc=%p pp=%p enable-msr=%d", pc, pp,
- pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS);
+ free(p6c, M_PMC);
- /* allow the RDPMC instruction if needed */
- if (pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS)
- load_cr4(rcr4() | CR4_PCE);
+ first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_P6].pcd_ri;
+ pc = pmc_pcpu[cpu];
+ for (n = 0; n < P6_NPMCS; n++)
+ pc->pc_hwpmcs[n + first_ri] = NULL;
- PMCDBG(MDP,SWI,1, "cr4=0x%x", rcr4());
-
- return 0;
-}
-
-static int
-p6_switch_out(struct pmc_cpu *pc, struct pmc_process *pp)
-{
- (void) pc;
- (void) pp; /* can be NULL */
-
- PMCDBG(MDP,SWO,1, "pc=%p pp=%p cr4=0x%x", pc, pp, rcr4());
-
- /* always turn off the RDPMC instruction */
- load_cr4(rcr4() & ~CR4_PCE);
-
- return 0;
+ return (0);
}
static int
p6_read_pmc(int cpu, int ri, pmc_value_t *v)
{
- struct pmc_hw *phw;
struct pmc *pm;
struct p6pmc_descr *pd;
pmc_value_t tmp;
- phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
- pm = phw->phw_pmc;
- pd = &p6_pmcdesc[ri];
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[p6,%d] illegal cpu value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < P6_NPMCS,
+ ("[p6,%d] illegal row-index %d", __LINE__, ri));
+
+ pm = p6_pcpu[cpu]->pc_p6pmcs[ri].phw_pmc;
+ pd = &p6_pmcdesc[ri];
KASSERT(pm,
("[p6,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, ri));
- if (pd->pm_descr.pd_class == PMC_CLASS_TSC) {
- *v = rdtsc();
- return 0;
- }
-
tmp = rdmsr(pd->pm_pmc_msr) & P6_PERFCTR_READ_MASK;
if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
*v = P6_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp);
@@ -433,26 +411,26 @@ p6_read_pmc(int cpu, int ri, pmc_value_t *v)
PMCDBG(MDP,REA,1, "p6-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
pd->pm_pmc_msr, *v);
- return 0;
+ return (0);
}
static int
p6_write_pmc(int cpu, int ri, pmc_value_t v)
{
- struct pmc_hw *phw;
struct pmc *pm;
struct p6pmc_descr *pd;
- phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
- pm = phw->phw_pmc;
- pd = &p6_pmcdesc[ri];
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[p6,%d] illegal cpu value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < P6_NPMCS,
+ ("[p6,%d] illegal row-index %d", __LINE__, ri));
+
+ pm = p6_pcpu[cpu]->pc_p6pmcs[ri].phw_pmc;
+ pd = &p6_pmcdesc[ri];
KASSERT(pm,
("[p6,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, ri));
- if (pd->pm_descr.pd_class == PMC_CLASS_TSC)
- return 0;
-
PMCDBG(MDP,WRI,1, "p6-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri,
pd->pm_pmc_msr, v);
@@ -461,20 +439,26 @@ p6_write_pmc(int cpu, int ri, pmc_value_t v)
wrmsr(pd->pm_pmc_msr, v & P6_PERFCTR_WRITE_MASK);
- return 0;
+ return (0);
}
static int
p6_config_pmc(int cpu, int ri, struct pmc *pm)
{
- struct pmc_hw *phw;
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[p6,%d] illegal CPU %d", __LINE__, cpu));
+
+ KASSERT(ri >= 0 && ri < P6_NPMCS,
+ ("[p6,%d] illegal row-index %d", __LINE__, ri));
PMCDBG(MDP,CFG,1, "p6-config cpu=%d ri=%d pm=%p", cpu, ri, pm);
- phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
- phw->phw_pmc = pm;
+ KASSERT(p6_pcpu[cpu] != NULL, ("[p6,%d] null per-cpu %d", __LINE__,
+ cpu));
+
+ p6_pcpu[cpu]->pc_p6pmcs[ri].phw_pmc = pm;
- return 0;
+ return (0);
}
/*
@@ -484,9 +468,15 @@ p6_config_pmc(int cpu, int ri, struct pmc *pm)
static int
p6_get_config(int cpu, int ri, struct pmc **ppm)
{
- *ppm = pmc_pcpu[cpu]->pc_hwpmcs[ri]->phw_pmc;
- return 0;
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[p6,%d] illegal CPU %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < P6_NPMCS,
+ ("[p6,%d] illegal row-index %d", __LINE__, ri));
+
+ *ppm = p6_pcpu[cpu]->pc_p6pmcs[ri].phw_pmc;
+
+ return (0);
}
@@ -507,10 +497,10 @@ p6_allocate_pmc(int cpu, int ri, struct pmc *pm,
(void) cpu;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
- ("[p4,%d] illegal CPU %d", __LINE__, cpu));
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[p6,%d] illegal CPU %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < P6_NPMCS,
- ("[p4,%d] illegal row-index value %d", __LINE__, ri));
+ ("[p6,%d] illegal row-index value %d", __LINE__, ri));
pd = &p6_pmcdesc[ri];
@@ -520,36 +510,24 @@ p6_allocate_pmc(int cpu, int ri, struct pmc *pm,
/* check class */
if (pd->pm_descr.pd_class != a->pm_class)
- return EINVAL;
+ return (EINVAL);
/* check requested capabilities */
caps = a->pm_caps;
if ((pd->pm_descr.pd_caps & caps) != caps)
- return EPERM;
-
- if (pd->pm_descr.pd_class == PMC_CLASS_TSC) {
- /* TSC's are always allocated in system-wide counting mode */
- if (a->pm_ev != PMC_EV_TSC_TSC ||
- a->pm_mode != PMC_MODE_SC)
- return EINVAL;
- return 0;
- }
-
- /*
- * P6 class events
- */
+ return (EPERM);
ev = pm->pm_event;
if (ev < PMC_EV_P6_FIRST || ev > PMC_EV_P6_LAST)
- return EINVAL;
+ return (EINVAL);
if ((pevent = p6_find_event(ev)) == NULL)
- return ESRCH;
+ return (ESRCH);
if (!P6_EVENT_VALID_FOR_CPU(pevent, p6_cputype) ||
!P6_EVENT_VALID_FOR_CTR(pevent, (ri-1)))
- return EINVAL;
+ return (EINVAL);
/* For certain events, Pentium M differs from the stock P6 */
allowed_unitmask = 0;
@@ -564,7 +542,7 @@ p6_allocate_pmc(int cpu, int ri, struct pmc *pm,
unitmask = a->pm_md.pm_ppro.pm_ppro_config & P6_EVSEL_UMASK_MASK;
if (unitmask & ~allowed_unitmask) /* disallow reserved bits */
- return EINVAL;
+ return (EINVAL);
if (ev == PMC_EV_P6_MMX_UOPS_EXEC) /* hardcoded mask */
unitmask = P6_EVSEL_TO_UMASK(0x0F);
@@ -599,29 +577,25 @@ p6_allocate_pmc(int cpu, int ri, struct pmc *pm,
PMCDBG(MDP,ALL,2, "p6-allocate config=0x%x", config);
- return 0;
+ return (0);
}
static int
p6_release_pmc(int cpu, int ri, struct pmc *pm)
{
- struct pmc_hw *phw;
-
(void) pm;
PMCDBG(MDP,REL,1, "p6-release cpu=%d ri=%d pm=%p", cpu, ri, pm);
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p6,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < P6_NPMCS,
("[p6,%d] illegal row-index %d", __LINE__, ri));
- phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
+ KASSERT(p6_pcpu[cpu]->pc_p6pmcs[ri].phw_pmc == NULL,
+ ("[p6,%d] PHW pmc non-NULL", __LINE__));
- KASSERT(phw->phw_pmc == NULL,
- ("[p6,%d] PHW pmc %p != pmc %p", __LINE__, phw->phw_pmc, pm));
-
- return 0;
+ return (0);
}
static int
@@ -630,18 +604,16 @@ p6_start_pmc(int cpu, int ri)
uint32_t config;
struct pmc *pm;
struct p6_cpu *pc;
- struct pmc_hw *phw;
const struct p6pmc_descr *pd;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p6,%d] illegal CPU value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < P6_NPMCS,
("[p6,%d] illegal row-index %d", __LINE__, ri));
- pc = (struct p6_cpu *) pmc_pcpu[cpu];
- phw = pc->pc_common.pc_hwpmcs[ri];
- pm = phw->phw_pmc;
- pd = &p6_pmcdesc[ri];
+ pc = p6_pcpu[cpu];
+ pm = pc->pc_p6pmcs[ri].phw_pmc;
+ pd = &p6_pmcdesc[ri];
KASSERT(pm,
("[p6,%d] starting cpu%d,ri%d with no pmc configured",
@@ -649,13 +621,6 @@ p6_start_pmc(int cpu, int ri)
PMCDBG(MDP,STA,1, "p6-start cpu=%d ri=%d", cpu, ri);
- if (pd->pm_descr.pd_class == PMC_CLASS_TSC)
- return 0; /* TSC are always running */
-
- KASSERT(pd->pm_descr.pd_class == PMC_CLASS_P6,
- ("[p6,%d] unknown PMC class %d", __LINE__,
- pd->pm_descr.pd_class));
-
config = pm->pm_md.pm_ppro.pm_ppro_evsel;
PMCDBG(MDP,STA,2, "p6-start/2 cpu=%d ri=%d evselmsr=0x%x config=0x%x",
@@ -666,7 +631,7 @@ p6_start_pmc(int cpu, int ri)
P6_SYNC_CTR_STATE(pc);
- return 0;
+ return (0);
}
static int
@@ -674,30 +639,21 @@ p6_stop_pmc(int cpu, int ri)
{
struct pmc *pm;
struct p6_cpu *pc;
- struct pmc_hw *phw;
struct p6pmc_descr *pd;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p6,%d] illegal cpu value %d", __LINE__, cpu));
KASSERT(ri >= 0 && ri < P6_NPMCS,
("[p6,%d] illegal row index %d", __LINE__, ri));
- pc = (struct p6_cpu *) pmc_pcpu[cpu];
- phw = pc->pc_common.pc_hwpmcs[ri];
- pm = phw->phw_pmc;
- pd = &p6_pmcdesc[ri];
+ pc = p6_pcpu[cpu];
+ pm = pc->pc_p6pmcs[ri].phw_pmc;
+ pd = &p6_pmcdesc[ri];
KASSERT(pm,
("[p6,%d] cpu%d ri%d no configured PMC to stop", __LINE__,
cpu, ri));
- if (pd->pm_descr.pd_class == PMC_CLASS_TSC)
- return 0;
-
- KASSERT(pd->pm_descr.pd_class == PMC_CLASS_P6,
- ("[p6,%d] unknown PMC class %d", __LINE__,
- pd->pm_descr.pd_class));
-
PMCDBG(MDP,STO,1, "p6-stop cpu=%d ri=%d", cpu, ri);
wrmsr(pd->pm_evsel_msr, 0); /* stop hw */
@@ -706,52 +662,52 @@ p6_stop_pmc(int cpu, int ri)
P6_SYNC_CTR_STATE(pc); /* restart CTR1 if need be */
PMCDBG(MDP,STO,2, "p6-stop/2 cpu=%d ri=%d", cpu, ri);
- return 0;
+
+ return (0);
}
static int
-p6_intr(int cpu, uintptr_t eip, int usermode)
+p6_intr(int cpu, struct trapframe *tf)
{
- int i, error, retval, ri;
+ int error, retval, ri;
uint32_t perf0cfg;
struct pmc *pm;
struct p6_cpu *pc;
- struct pmc_hw *phw;
pmc_value_t v;
- KASSERT(cpu >= 0 && cpu < mp_ncpus,
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
("[p6,%d] CPU %d out of range", __LINE__, cpu));
retval = 0;
- pc = (struct p6_cpu *) pmc_pcpu[cpu];
+ pc = p6_pcpu[cpu];
/* stop both PMCs */
perf0cfg = rdmsr(P6_MSR_EVSEL0);
wrmsr(P6_MSR_EVSEL0, perf0cfg & ~P6_EVSEL_EN);
- for (i = 0; i < P6_NPMCS-1; i++) {
- ri = i + 1;
+ for (ri = 0; ri < P6_NPMCS; ri++) {
- if (!P6_PMC_HAS_OVERFLOWED(i))
- continue;
-
- phw = pc->pc_common.pc_hwpmcs[ri];
-
- if ((pm = phw->phw_pmc) == NULL ||
- pm->pm_state != PMC_STATE_RUNNING ||
+ if ((pm = pc->pc_p6pmcs[ri].phw_pmc) == NULL ||
!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) {
continue;
}
+ if (!P6_PMC_HAS_OVERFLOWED(ri))
+ continue;
+
retval = 1;
- error = pmc_process_interrupt(cpu, pm, eip, usermode);
+ if (pm->pm_state != PMC_STATE_RUNNING)
+ continue;
+
+ error = pmc_process_interrupt(cpu, pm, tf,
+ TRAPF_USERMODE(tf));
if (error)
P6_MARK_STOPPED(pc,ri);
/* reload sampling count */
v = pm->pm_sc.pm_reloadcount;
- wrmsr(P6_MSR_PERFCTR0 + i,
+ wrmsr(P6_MSR_PERFCTR0 + ri,
P6_RELOAD_COUNT_TO_PERFCTR_VALUE(v));
}
@@ -769,7 +725,7 @@ p6_intr(int cpu, uintptr_t eip, int usermode)
/* restart counters that can be restarted */
P6_SYNC_CTR_STATE(pc);
- return retval;
+ return (retval);
}
static int
@@ -781,12 +737,20 @@ p6_describe(int cpu, int ri, struct pmc_info *pi,
struct pmc_hw *phw;
struct p6pmc_descr *pd;
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[p6,%d] illegal CPU %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < P6_NPMCS,
+ ("[p6,%d] row-index %d out of range", __LINE__, ri));
+
phw = pmc_pcpu[cpu]->pc_hwpmcs[ri];
pd = &p6_pmcdesc[ri];
+ KASSERT(phw == &p6_pcpu[cpu]->pc_p6pmcs[ri],
+ ("[p6,%d] phw mismatch", __LINE__));
+
if ((error = copystr(pd->pm_descr.pd_name, pi->pm_name,
PMC_NAME_MAX, &copied)) != 0)
- return error;
+ return (error);
pi->pm_class = pd->pm_descr.pd_class;
@@ -798,7 +762,7 @@ p6_describe(int cpu, int ri, struct pmc_info *pi,
*ppmc = NULL;
}
- return 0;
+ return (0);
}
static int
@@ -808,58 +772,91 @@ p6_get_msr(int ri, uint32_t *msr)
("[p6,%d ri %d out of range", __LINE__, ri));
*msr = p6_pmcdesc[ri].pm_pmc_msr - P6_MSR_PERFCTR0;
- return 0;
+
+ return (0);
}
int
-pmc_initialize_p6(struct pmc_mdep *pmc_mdep)
+pmc_p6_initialize(struct pmc_mdep *md, int ncpus)
{
+ struct pmc_classdep *pcd;
+
KASSERT(strcmp(cpu_vendor, "GenuineIntel") == 0,
("[p6,%d] Initializing non-intel processor", __LINE__));
PMCDBG(MDP,INI,1, "%s", "p6-initialize");
- switch (pmc_mdep->pmd_cputype) {
+ /* Allocate space for pointers to per-cpu descriptors. */
+ p6_pcpu = malloc(sizeof(struct p6_cpu **) * ncpus, M_PMC,
+ M_ZERO|M_WAITOK);
+
+ /* Fill in the class dependent descriptor. */
+ pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_P6];
+
+ switch (md->pmd_cputype) {
/*
* P6 Family Processors
*/
-
case PMC_CPU_INTEL_P6:
case PMC_CPU_INTEL_CL:
case PMC_CPU_INTEL_PII:
case PMC_CPU_INTEL_PIII:
case PMC_CPU_INTEL_PM:
- p6_cputype = pmc_mdep->pmd_cputype;
+ p6_cputype = md->pmd_cputype;
- pmc_mdep->pmd_npmc = P6_NPMCS;
- pmc_mdep->pmd_classes[1].pm_class = PMC_CLASS_P6;
- pmc_mdep->pmd_classes[1].pm_caps = P6_PMC_CAPS;
- pmc_mdep->pmd_classes[1].pm_width = 40;
- pmc_mdep->pmd_nclasspmcs[1] = 2;
+ pcd->pcd_caps = P6_PMC_CAPS;
+ pcd->pcd_class = PMC_CLASS_P6;
+ pcd->pcd_num = P6_NPMCS;
+ pcd->pcd_ri = md->pmd_npmc;
+ pcd->pcd_width = 40;
- pmc_mdep->pmd_init = p6_init;
- pmc_mdep->pmd_cleanup = p6_cleanup;
- pmc_mdep->pmd_switch_in = p6_switch_in;
- pmc_mdep->pmd_switch_out = p6_switch_out;
- pmc_mdep->pmd_read_pmc = p6_read_pmc;
- pmc_mdep->pmd_write_pmc = p6_write_pmc;
- pmc_mdep->pmd_config_pmc = p6_config_pmc;
- pmc_mdep->pmd_get_config = p6_get_config;
- pmc_mdep->pmd_allocate_pmc = p6_allocate_pmc;
- pmc_mdep->pmd_release_pmc = p6_release_pmc;
- pmc_mdep->pmd_start_pmc = p6_start_pmc;
- pmc_mdep->pmd_stop_pmc = p6_stop_pmc;
- pmc_mdep->pmd_intr = p6_intr;
- pmc_mdep->pmd_describe = p6_describe;
- pmc_mdep->pmd_get_msr = p6_get_msr; /* i386 */
+ pcd->pcd_allocate_pmc = p6_allocate_pmc;
+ pcd->pcd_config_pmc = p6_config_pmc;
+ pcd->pcd_describe = p6_describe;
+ pcd->pcd_get_config = p6_get_config;
+ pcd->pcd_get_msr = p6_get_msr;
+ pcd->pcd_pcpu_fini = p6_pcpu_fini;
+ pcd->pcd_pcpu_init = p6_pcpu_init;
+ pcd->pcd_read_pmc = p6_read_pmc;
+ pcd->pcd_release_pmc = p6_release_pmc;
+ pcd->pcd_start_pmc = p6_start_pmc;
+ pcd->pcd_stop_pmc = p6_stop_pmc;
+ pcd->pcd_write_pmc = p6_write_pmc;
+
+ md->pmd_pcpu_fini = NULL;
+ md->pmd_pcpu_init = NULL;
+ md->pmd_intr = p6_intr;
+
+ md->pmd_npmc += P6_NPMCS;
break;
+
default:
KASSERT(0,("[p6,%d] Unknown CPU type", __LINE__));
return ENOSYS;
}
- return 0;
+ return (0);
+}
+
+void
+pmc_p6_finalize(struct pmc_mdep *md)
+{
+#if defined(INVARIANTS)
+ int i, ncpus;
+#endif
+
+ KASSERT(p6_pcpu != NULL, ("[p6,%d] NULL p6_pcpu", __LINE__));
+
+#if defined(INVARIANTS)
+ ncpus = pmc_cpu_max();
+ for (i = 0; i < ncpus; i++)
+ KASSERT(p6_pcpu[i] == NULL, ("[p6,%d] non-null pcpu %d",
+ __LINE__, i));
+#endif
+
+ free(p6_pcpu, M_PMC);
+ p6_pcpu = NULL;
}
diff --git a/sys/dev/hwpmc/hwpmc_ppro.h b/sys/dev/hwpmc/hwpmc_ppro.h
index f750735c85ea..c42a2b4d315d 100644
--- a/sys/dev/hwpmc/hwpmc_ppro.h
+++ b/sys/dev/hwpmc/hwpmc_ppro.h
@@ -33,7 +33,7 @@
/* Intel PPro, Celeron, P-II, P-III, Pentium-M PMCS */
-#define P6_NPMCS 3 /* 1 TSC + 2 PMCs */
+#define P6_NPMCS 2 /* 2 PMCs */
#define P6_EVSEL_CMASK_MASK 0xFF000000
#define P6_EVSEL_TO_CMASK(C) (((C) & 0xFF) << 24)
@@ -77,7 +77,8 @@ struct pmc_md_ppro_pmc {
* Prototypes
*/
-int pmc_initialize_p6(struct pmc_mdep *); /* Pentium Pro PMCs */
+int pmc_p6_initialize(struct pmc_mdep *_md, int _ncpus);
+void pmc_p6_finalize(struct pmc_mdep *_md);
#endif /* _KERNEL */
#endif /* _DEV_HWPMC_PPRO_H_ */
diff --git a/sys/dev/hwpmc/hwpmc_sparc64.c b/sys/dev/hwpmc/hwpmc_sparc64.c
index af905b66924e..ce1caf69e108 100644
--- a/sys/dev/hwpmc/hwpmc_sparc64.c
+++ b/sys/dev/hwpmc/hwpmc_sparc64.c
@@ -38,3 +38,29 @@ pmc_md_initialize()
{
return NULL;
}
+
+void
+pmc_md_finalize(struct pmc_mdep *md)
+{
+ (void) md;
+}
+
+int
+pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
+ struct trapframe *tf)
+{
+ (void) cc;
+ (void) maxsamples;
+ (void) tf;
+ return (0);
+}
+
+int
+pmc_save_user_callchain(uintptr_t *cc, int maxsamples,
+ struct trapframe *tf)
+{
+ (void) cc;
+ (void) maxsamples;
+ (void) tf;
+ return (0);
+}
diff --git a/sys/dev/hwpmc/hwpmc_tsc.c b/sys/dev/hwpmc/hwpmc_tsc.c
new file mode 100644
index 000000000000..0b71a5be62fe
--- /dev/null
+++ b/sys/dev/hwpmc/hwpmc_tsc.c
@@ -0,0 +1,388 @@
+/*-
+ * Copyright (c) 2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/pmc.h>
+#include <sys/pmckern.h>
+#include <sys/systm.h>
+
+#include <machine/specialreg.h>
+
+/*
+ * TSC support.
+ */
+
+#define TSC_CAPS PMC_CAP_READ
+
+struct tsc_descr {
+ struct pmc_descr pm_descr; /* "base class" */
+};
+
+static struct tsc_descr tsc_pmcdesc[TSC_NPMCS] =
+{
+ {
+ .pm_descr =
+ {
+ .pd_name = "TSC",
+ .pd_class = PMC_CLASS_TSC,
+ .pd_caps = TSC_CAPS,
+ .pd_width = 64
+ }
+ }
+};
+
+/*
+ * Per-CPU data structure for TSCs.
+ */
+
+struct tsc_cpu {
+ struct pmc_hw tc_hw;
+};
+
+static struct tsc_cpu **tsc_pcpu;
+
+static int
+tsc_allocate_pmc(int cpu, int ri, struct pmc *pm,
+ const struct pmc_op_pmcallocate *a)
+{
+ (void) cpu;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[tsc,%d] illegal CPU value %d", __LINE__, cpu));
+ KASSERT(ri >= 0 && ri < TSC_NPMCS,
+ ("[tsc,%d] illegal row index %d", __LINE__, ri));
+
+ if (a->pm_class != PMC_CLASS_TSC)
+ return (EINVAL);
+
+ if ((pm->pm_caps & TSC_CAPS) == 0)
+ return (EINVAL);
+
+ if ((pm->pm_caps & ~TSC_CAPS) != 0)
+ return (EPERM);
+
+ if (a->pm_ev != PMC_EV_TSC_TSC ||
+ a->pm_mode != PMC_MODE_SC)
+ return (EINVAL);
+
+ return (0);
+}
+
+static int
+tsc_config_pmc(int cpu, int ri, struct pmc *pm)
+{
+ struct pmc_hw *phw;
+
+ PMCDBG(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm);
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[tsc,%d] illegal CPU value %d", __LINE__, cpu));
+ KASSERT(ri == 0, ("[tsc,%d] illegal row-index %d", __LINE__, ri));
+
+ phw = &tsc_pcpu[cpu]->tc_hw;
+
+ KASSERT(pm == NULL || phw->phw_pmc == NULL,
+ ("[tsc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", __LINE__,
+ pm, phw->phw_pmc));
+
+ phw->phw_pmc = pm;
+
+ return (0);
+}
+
+static int
+tsc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
+{
+ int error;
+ size_t copied;
+ const struct tsc_descr *pd;
+ struct pmc_hw *phw;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[tsc,%d] illegal CPU %d", __LINE__, cpu));
+ KASSERT(ri == 0, ("[tsc,%d] illegal row-index %d", __LINE__, ri));
+
+ phw = &tsc_pcpu[cpu]->tc_hw;
+ pd = &tsc_pmcdesc[ri];
+
+ if ((error = copystr(pd->pm_descr.pd_name, pi->pm_name,
+ PMC_NAME_MAX, &copied)) != 0)
+ return (error);
+
+ pi->pm_class = pd->pm_descr.pd_class;
+
+ if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
+ pi->pm_enabled = TRUE;
+ *ppmc = phw->phw_pmc;
+ } else {
+ pi->pm_enabled = FALSE;
+ *ppmc = NULL;
+ }
+
+ return (0);
+}
+
+static int
+tsc_get_config(int cpu, int ri, struct pmc **ppm)
+{
+ (void) ri;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[tsc,%d] illegal CPU %d", __LINE__, cpu));
+ KASSERT(ri == 0, ("[tsc,%d] illegal row-index %d", __LINE__, ri));
+
+ *ppm = tsc_pcpu[cpu]->tc_hw.phw_pmc;
+
+ return (0);
+}
+
+static int
+tsc_get_msr(int ri, uint32_t *msr)
+{
+ (void) ri;
+
+ KASSERT(ri >= 0 && ri < TSC_NPMCS,
+ ("[tsc,%d] ri %d out of range", __LINE__, ri));
+
+ *msr = MSR_TSC;
+
+ return (0);
+}
+
+static int
+tsc_pcpu_fini(struct pmc_mdep *md, int cpu)
+{
+ int ri;
+ struct pmc_cpu *pc;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[tsc,%d] illegal cpu %d", __LINE__, cpu));
+ KASSERT(tsc_pcpu[cpu] != NULL, ("[tsc,%d] null pcpu", __LINE__));
+
+ free(tsc_pcpu[cpu], M_PMC);
+ tsc_pcpu[cpu] = NULL;
+
+ ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_TSC].pcd_ri;
+
+ KASSERT(ri == 0 && ri < TSC_NPMCS, ("[tsc,%d] ri=%d", __LINE__,
+ ri));
+
+ pc = pmc_pcpu[cpu];
+ pc->pc_hwpmcs[ri] = NULL;
+
+ return (0);
+}
+
+static int
+tsc_pcpu_init(struct pmc_mdep *md, int cpu)
+{
+ int ri;
+ struct pmc_cpu *pc;
+ struct tsc_cpu *tsc_pc;
+
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[tsc,%d] illegal cpu %d", __LINE__, cpu));
+ KASSERT(tsc_pcpu, ("[tsc,%d] null pcpu", __LINE__));
+ KASSERT(tsc_pcpu[cpu] == NULL, ("[tsc,%d] non-null per-cpu",
+ __LINE__));
+
+ tsc_pc = malloc(sizeof(struct tsc_cpu), M_PMC, M_WAITOK|M_ZERO);
+
+ tsc_pc->tc_hw.phw_state = PMC_PHW_FLAG_IS_ENABLED |
+ PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(0) |
+ PMC_PHW_FLAG_IS_SHAREABLE;
+
+ tsc_pcpu[cpu] = tsc_pc;
+
+ ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_TSC].pcd_ri;
+
+ KASSERT(pmc_pcpu, ("[tsc,%d] null generic pcpu", __LINE__));
+
+ pc = pmc_pcpu[cpu];
+
+ KASSERT(pc, ("[tsc,%d] null generic per-cpu", __LINE__));
+
+ pc->pc_hwpmcs[ri] = &tsc_pc->tc_hw;
+
+ return (0);
+}
+
+static int
+tsc_read_pmc(int cpu, int ri, pmc_value_t *v)
+{
+ struct pmc *pm;
+ enum pmc_mode mode;
+ const struct pmc_hw *phw;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[tsc,%d] illegal CPU value %d", __LINE__, cpu));
+ KASSERT(ri == 0, ("[tsc,%d] illegal ri %d", __LINE__, ri));
+
+ phw = &tsc_pcpu[cpu]->tc_hw;
+ pm = phw->phw_pmc;
+
+ KASSERT(pm != NULL,
+ ("[tsc,%d] no owner for PHW [cpu%d,pmc%d]", __LINE__, cpu, ri));
+
+ mode = PMC_TO_MODE(pm);
+
+ KASSERT(mode == PMC_MODE_SC,
+ ("[tsc,%d] illegal pmc mode %d", __LINE__, mode));
+
+ PMCDBG(MDP,REA,1,"tsc-read id=%d", ri);
+
+ *v = rdtsc();
+
+ return (0);
+}
+
+static int
+tsc_release_pmc(int cpu, int ri, struct pmc *pmc)
+{
+ struct pmc_hw *phw;
+
+ (void) pmc;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[tsc,%d] illegal CPU value %d", __LINE__, cpu));
+ KASSERT(ri == 0,
+ ("[tsc,%d] illegal row-index %d", __LINE__, ri));
+
+ phw = &tsc_pcpu[cpu]->tc_hw;
+
+ KASSERT(phw->phw_pmc == NULL,
+ ("[tsc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc));
+
+ /*
+ * Nothing to do.
+ */
+ return (0);
+}
+
+static int
+tsc_start_pmc(int cpu, int ri)
+{
+ (void) cpu;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[tsc,%d] illegal CPU value %d", __LINE__, cpu));
+ KASSERT(ri == 0, ("[tsc,%d] illegal row-index %d", __LINE__, ri));
+
+ return (0); /* TSCs are always running. */
+}
+
+static int
+tsc_stop_pmc(int cpu, int ri)
+{
+ (void) cpu; (void) ri;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[tsc,%d] illegal CPU value %d", __LINE__, cpu));
+ KASSERT(ri == 0, ("[tsc,%d] illegal row-index %d", __LINE__, ri));
+
+ return (0); /* Cannot actually stop a TSC. */
+}
+
+static int
+tsc_write_pmc(int cpu, int ri, pmc_value_t v)
+{
+ (void) cpu; (void) ri; (void) v;
+
+ KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+ ("[tsc,%d] illegal CPU value %d", __LINE__, cpu));
+ KASSERT(ri == 0, ("[tsc,%d] illegal row-index %d", __LINE__, ri));
+
+ /*
+ * The TSCs are used as timecounters by the kernel, so even
+ * though some i386 CPUs support writeable TSCs, we don't
+ * support writing changing TSC values through the HWPMC API.
+ */
+ return (0);
+}
+
+int
+pmc_tsc_initialize(struct pmc_mdep *md, int maxcpu)
+{
+ struct pmc_classdep *pcd;
+
+ KASSERT(md != NULL, ("[tsc,%d] md is NULL", __LINE__));
+ KASSERT(md->pmd_nclass >= 1, ("[tsc,%d] dubious md->nclass %d",
+ __LINE__, md->pmd_nclass));
+
+ tsc_pcpu = malloc(sizeof(struct tsc_cpu *) * maxcpu, M_PMC,
+ M_ZERO|M_WAITOK);
+
+ pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_TSC];
+
+ pcd->pcd_caps = PMC_CAP_READ;
+ pcd->pcd_class = PMC_CLASS_TSC;
+ pcd->pcd_num = TSC_NPMCS;
+ pcd->pcd_ri = md->pmd_npmc;
+ pcd->pcd_width = 64;
+
+ pcd->pcd_allocate_pmc = tsc_allocate_pmc;
+ pcd->pcd_config_pmc = tsc_config_pmc;
+ pcd->pcd_describe = tsc_describe;
+ pcd->pcd_get_config = tsc_get_config;
+ pcd->pcd_get_msr = tsc_get_msr;
+ pcd->pcd_pcpu_init = tsc_pcpu_init;
+ pcd->pcd_pcpu_fini = tsc_pcpu_fini;
+ pcd->pcd_read_pmc = tsc_read_pmc;
+ pcd->pcd_release_pmc = tsc_release_pmc;
+ pcd->pcd_start_pmc = tsc_start_pmc;
+ pcd->pcd_stop_pmc = tsc_stop_pmc;
+ pcd->pcd_write_pmc = tsc_write_pmc;
+
+ md->pmd_npmc += TSC_NPMCS;
+
+ return (0);
+}
+
+void
+pmc_tsc_finalize(struct pmc_mdep *md)
+{
+#ifdef INVARIANTS
+ int i, ncpus;
+
+ ncpus = pmc_cpu_max();
+ for (i = 0; i < ncpus; i++)
+ KASSERT(tsc_pcpu[i] == NULL, ("[tsc,%d] non-null pcpu cpu %d",
+ __LINE__, i));
+
+ KASSERT(md->pmd_classdep[PMC_MDEP_CLASS_INDEX_TSC].pcd_class ==
+ PMC_CLASS_TSC, ("[tsc,%d] class mismatch", __LINE__));
+
+#else
+ (void) md;
+#endif
+
+ free(tsc_pcpu, M_PMC);
+ tsc_pcpu = NULL;
+}
diff --git a/sys/dev/hwpmc/hwpmc_tsc.h b/sys/dev/hwpmc/hwpmc_tsc.h
new file mode 100644
index 000000000000..a8b011e6ee31
--- /dev/null
+++ b/sys/dev/hwpmc/hwpmc_tsc.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2008 Joseph Koshy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_HWPMC_TSC_H_
+#define _DEV_HWPMC_TSC_H_ 1
+
+#ifdef _KERNEL
+
+#define TSC_NPMCS 1
+
+/*
+ * Prototypes.
+ */
+
+int pmc_tsc_initialize(struct pmc_mdep *_md, int _maxcpu);
+void pmc_tsc_finalize(struct pmc_mdep *_md);
+#endif /* _KERNEL */
+#endif /* _DEV_HWPMC_TSC_H */
diff --git a/sys/dev/hwpmc/hwpmc_x86.c b/sys/dev/hwpmc/hwpmc_x86.c
index cb6db23bc1b6..dd9c0e9f3d60 100644
--- a/sys/dev/hwpmc/hwpmc_x86.c
+++ b/sys/dev/hwpmc/hwpmc_x86.c
@@ -1,7 +1,11 @@
/*-
- * Copyright (c) 2005, Joseph Koshy
+ * Copyright (c) 2005,2008 Joseph Koshy
+ * Copyright (c) 2007 The FreeBSD Foundation
* All rights reserved.
*
+ * Portions of this software were developed by A. Joseph Koshy under
+ * sponsorship from the FreeBSD Foundation and Google, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -30,12 +34,18 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/pmc.h>
+#include <sys/proc.h>
#include <sys/systm.h>
+#include <machine/cpu.h>
#include <machine/apicreg.h>
#include <machine/pmc_mdep.h>
#include <machine/md_var.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
extern volatile lapic_t *lapic;
void
@@ -48,121 +58,188 @@ pmc_x86_lapic_enable_pmc_interrupt(void)
lapic->lvt_pcint = value;
}
+/*
+ * Attempt to walk a user call stack using a too-simple algorithm.
+ * In the general case we need unwind information associated with
+ * the executable to be able to walk the user stack.
+ *
+ * We are handed a trap frame laid down at the time the PMC interrupt
+ * was taken. If the application is using frame pointers, the saved
+ * PC value could be:
+ * a. at the beginning of a function before the stack frame is laid
+ * down,
+ * b. just before a 'ret', after the stack frame has been taken off,
+ * c. somewhere else in the function with a valid stack frame being
+ * present,
+ *
+ * If the application is not using frame pointers, this algorithm will
+ * fail to yield an interesting call chain.
+ *
+ * TODO: figure out a way to use unwind information.
+ */
-static struct pmc_mdep *
-pmc_intel_initialize(void)
+int
+pmc_save_user_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
{
- struct pmc_mdep *pmc_mdep;
- enum pmc_cputype cputype;
- int error, model;
+ int n;
+ uint32_t instr;
+ uintptr_t fp, oldfp, pc, r, sp;
- KASSERT(strcmp(cpu_vendor, "GenuineIntel") == 0,
- ("[intel,%d] Initializing non-intel processor", __LINE__));
+ KASSERT(TRAPF_USERMODE(tf), ("[x86,%d] Not a user trap frame tf=%p",
+ __LINE__, (void *) tf));
- PMCDBG(MDP,INI,0, "intel-initialize cpuid=0x%x", cpu_id);
+ pc = PMC_TRAPFRAME_TO_PC(tf);
+ oldfp = fp = PMC_TRAPFRAME_TO_FP(tf);
+ sp = PMC_TRAPFRAME_TO_USER_SP(tf);
- cputype = -1;
+ *cc++ = pc; n = 1;
- switch (cpu_id & 0xF00) {
-#if defined(__i386__)
- case 0x500: /* Pentium family processors */
- cputype = PMC_CPU_INTEL_P5;
- break;
- case 0x600: /* Pentium Pro, Celeron, Pentium II & III */
- switch ((cpu_id & 0xF0) >> 4) { /* model number field */
- case 0x1:
- cputype = PMC_CPU_INTEL_P6;
- break;
- case 0x3: case 0x5:
- cputype = PMC_CPU_INTEL_PII;
- break;
- case 0x6:
- cputype = PMC_CPU_INTEL_CL;
+ r = fp + sizeof(uintptr_t); /* points to return address */
+
+ if (!PMC_IN_USERSPACE(pc))
+ return (n);
+
+ if (copyin((void *) pc, &instr, sizeof(instr)) != 0)
+ return (n);
+
+ if (PMC_AT_FUNCTION_PROLOGUE_PUSH_BP(instr) ||
+ PMC_AT_FUNCTION_EPILOGUE_RET(instr)) { /* ret */
+ if (copyin((void *) sp, &pc, sizeof(pc)) != 0)
+ return (n);
+ } else if (PMC_AT_FUNCTION_PROLOGUE_MOV_SP_BP(instr)) {
+ sp += sizeof(uintptr_t);
+ if (copyin((void *) sp, &pc, sizeof(pc)) != 0)
+ return (n);
+ } else if (copyin((void *) r, &pc, sizeof(pc)) != 0 ||
+ copyin((void *) fp, &fp, sizeof(fp) != 0))
+ return (n);
+
+ for (; n < nframes;) {
+ if (pc == 0 || !PMC_IN_USERSPACE(pc))
break;
- case 0x7: case 0x8: case 0xA: case 0xB:
- cputype = PMC_CPU_INTEL_PIII;
+
+ *cc++ = pc; n++;
+
+ if (fp < oldfp)
break;
- case 0x9: case 0xD:
- cputype = PMC_CPU_INTEL_PM;
+
+ r = fp + sizeof(uintptr_t); /* address of return address */
+ oldfp = fp;
+
+ if (copyin((void *) r, &pc, sizeof(pc)) != 0 ||
+ copyin((void *) fp, &fp, sizeof(fp)) != 0)
break;
- }
- break;
-#endif
-#if defined(__i386__) || defined(__amd64__)
- case 0xF00: /* P4 */
- model = ((cpu_id & 0xF0000) >> 12) | ((cpu_id & 0xF0) >> 4);
- if (model >= 0 && model <= 6) /* known models */
- cputype = PMC_CPU_INTEL_PIV;
- break;
}
-#endif
- if ((int) cputype == -1) {
- printf("pmc: Unknown Intel CPU.\n");
- return NULL;
- }
+ return (n);
+}
- MALLOC(pmc_mdep, struct pmc_mdep *, sizeof(struct pmc_mdep),
- M_PMC, M_WAITOK|M_ZERO);
+/*
+ * Walking the kernel call stack.
+ *
+ * We are handed the trap frame laid down at the time the PMC
+ * interrupt was taken. The saved PC could be:
+ * a. in the lowlevel trap handler, meaning that there isn't a C stack
+ * to traverse,
+ * b. at the beginning of a function before the stack frame is laid
+ * down,
+ * c. just before a 'ret', after the stack frame has been taken off,
+ * d. somewhere else in a function with a valid stack frame being
+ * present.
+ *
+ * In case (d), the previous frame pointer is at [%ebp]/[%rbp] and
+ * the return address is at [%ebp+4]/[%rbp+8].
+ *
+ * For cases (b) and (c), the return address is at [%esp]/[%rsp] and
+ * the frame pointer doesn't need to be changed when going up one
+ * level in the stack.
+ *
+ * For case (a), we check if the PC lies in low-level trap handling
+ * code, and if so we terminate our trace.
+ */
- pmc_mdep->pmd_cputype = cputype;
- pmc_mdep->pmd_nclass = 2;
- pmc_mdep->pmd_classes[0].pm_class = PMC_CLASS_TSC;
- pmc_mdep->pmd_classes[0].pm_caps = PMC_CAP_READ;
- pmc_mdep->pmd_classes[0].pm_width = 64;
- pmc_mdep->pmd_nclasspmcs[0] = 1;
+int
+pmc_save_kernel_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
+{
+ int n;
+ uint32_t instr;
+ uintptr_t fp, pc, r, sp, stackstart, stackend;
+ struct thread *td;
- error = 0;
+ KASSERT(TRAPF_USERMODE(tf) == 0,("[x86,%d] not a kernel backtrace",
+ __LINE__));
- switch (cputype) {
+ pc = PMC_TRAPFRAME_TO_PC(tf);
+ fp = PMC_TRAPFRAME_TO_FP(tf);
+ sp = PMC_TRAPFRAME_TO_KERNEL_SP(tf);
-#if defined(__i386__) || defined(__amd64__)
+ *cc++ = pc;
+ r = fp + sizeof(uintptr_t); /* points to return address */
- /*
- * Intel Pentium 4 Processors, and P4/EMT64 processors.
- */
+ if ((td = curthread) == NULL)
+ return (1);
- case PMC_CPU_INTEL_PIV:
- error = pmc_initialize_p4(pmc_mdep);
- break;
-#endif
+ if (nframes <= 1)
+ return (1);
-#if defined(__i386__)
- /*
- * P6 Family Processors
- */
+ stackstart = (uintptr_t) td->td_kstack;
+ stackend = (uintptr_t) td->td_kstack + td->td_kstack_pages * PAGE_SIZE;
- case PMC_CPU_INTEL_P6:
- case PMC_CPU_INTEL_CL:
- case PMC_CPU_INTEL_PII:
- case PMC_CPU_INTEL_PIII:
- case PMC_CPU_INTEL_PM:
+ if (PMC_IN_TRAP_HANDLER(pc) ||
+ !PMC_IN_KERNEL(pc) || !PMC_IN_KERNEL(r) ||
+ !PMC_IN_KERNEL_STACK(sp, stackstart, stackend) ||
+ !PMC_IN_KERNEL_STACK(fp, stackstart, stackend))
+ return (1);
- error = pmc_initialize_p6(pmc_mdep);
- break;
+ instr = *(uint32_t *) pc;
+ /*
+ * Determine whether the interrupted function was in the
+ * processing of either laying down its stack frame or taking
+ * it off.
+ *
+ * If we haven't started laying down a stack frame, or are
+ * just about to return, then our caller's address is at
+ * *sp, and we don't have a frame to unwind.
+ */
+ if (PMC_AT_FUNCTION_PROLOGUE_PUSH_BP(instr) ||
+ PMC_AT_FUNCTION_EPILOGUE_RET(instr))
+ pc = *(uintptr_t *) sp;
+ else if (PMC_AT_FUNCTION_PROLOGUE_MOV_SP_BP(instr)) {
/*
- * Intel Pentium PMCs.
+ * The code was midway through laying down a frame.
+ * At this point sp[0] has a frame back pointer,
+ * and the caller's address is therefore at sp[1].
*/
+ sp += sizeof(uintptr_t);
+ if (!PMC_IN_KERNEL_STACK(sp, stackstart, stackend))
+ return (1);
+ pc = *(uintptr_t *) sp;
+ } else {
+ /*
+ * Not in the function prologue or epilogue.
+ */
+ pc = *(uintptr_t *) r;
+ fp = *(uintptr_t *) fp;
+ }
- case PMC_CPU_INTEL_P5:
- error = pmc_initialize_p5(pmc_mdep);
- break;
-#endif
+ for (n = 1; n < nframes; n++) {
+ *cc++ = pc;
- default:
- KASSERT(0,("[intel,%d] Unknown CPU type", __LINE__));
- }
+ if (PMC_IN_TRAP_HANDLER(pc))
+ break;
- if (error) {
- FREE(pmc_mdep, M_PMC);
- pmc_mdep = NULL;
+ r = fp + sizeof(uintptr_t);
+ if (!PMC_IN_KERNEL_STACK(fp, stackstart, stackend) ||
+ !PMC_IN_KERNEL(r))
+ break;
+ pc = *(uintptr_t *) r;
+ fp = *(uintptr_t *) fp;
}
- return pmc_mdep;
+ return (n);
}
-
/*
* Machine dependent initialization for x86 class platforms.
*/
@@ -179,11 +256,24 @@ pmc_md_initialize()
md = pmc_amd_initialize();
else if (strcmp(cpu_vendor, "GenuineIntel") == 0)
md = pmc_intel_initialize();
+ else
+ KASSERT(0, ("[x86,%d] Unknown vendor", __LINE__));
/* disallow sampling if we do not have an LAPIC */
if (md != NULL && lapic == NULL)
for (i = 1; i < md->pmd_nclass; i++)
- md->pmd_classes[i].pm_caps &= ~PMC_CAP_INTERRUPT;
+ md->pmd_classdep[i].pcd_caps &= ~PMC_CAP_INTERRUPT;
+
+ return (md);
+}
- return md;
+void
+pmc_md_finalize(struct pmc_mdep *md)
+{
+ if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
+ pmc_amd_finalize(md);
+ else if (strcmp(cpu_vendor, "GenuineIntel") == 0)
+ pmc_intel_finalize(md);
+ else
+ KASSERT(0, ("[x86,%d] Unknown vendor", __LINE__));
}
diff --git a/sys/dev/hwpmc/pmc_events.h b/sys/dev/hwpmc/pmc_events.h
index 23fc9dcb1a21..05078afc8f1a 100644
--- a/sys/dev/hwpmc/pmc_events.h
+++ b/sys/dev/hwpmc/pmc_events.h
@@ -32,7 +32,7 @@
/*
* PMC event codes.
*
- * __PMC_EV(CLASS, SYMBOLIC-NAME, VALUE, READABLE-NAME)
+ * __PMC_EV(CLASS, SYMBOLIC-NAME)
*
*/
@@ -41,207 +41,199 @@
* Optimization Guide" [Doc#22007K, Feb 2002]
*/
-#define __PMC_EV_K7() \
-__PMC_EV(K7, DC_ACCESSES, k7-dc-accesses) \
-__PMC_EV(K7, DC_MISSES, k7-dc-misses) \
-__PMC_EV(K7, DC_REFILLS_FROM_L2, k7-dc-refills-from-l2) \
-__PMC_EV(K7, DC_REFILLS_FROM_SYSTEM, k7-dc-refills-from-system) \
-__PMC_EV(K7, DC_WRITEBACKS, k7-dc-writebacks) \
-__PMC_EV(K7, L1_DTLB_MISS_AND_L2_DTLB_HITS, \
- k7-l1-dtlb-miss-and-l2-dtlb-hits) \
-__PMC_EV(K7, L1_AND_L2_DTLB_MISSES, k7-l1-and-l2-dtlb-misses) \
-__PMC_EV(K7, MISALIGNED_REFERENCES, k7-misaligned-references) \
-__PMC_EV(K7, IC_FETCHES, k7-ic-fetches) \
-__PMC_EV(K7, IC_MISSES, k7-ic-misses) \
-__PMC_EV(K7, L1_ITLB_MISSES, k7-l1-itlb-misses) \
-__PMC_EV(K7, L1_L2_ITLB_MISSES, k7-l1-l2-itlb-misses) \
-__PMC_EV(K7, RETIRED_INSTRUCTIONS, k7-retired-instructions) \
-__PMC_EV(K7, RETIRED_OPS, k7-retired-ops) \
-__PMC_EV(K7, RETIRED_BRANCHES, k7-retired-branches) \
-__PMC_EV(K7, RETIRED_BRANCHES_MISPREDICTED, \
- k7-retired-branches-mispredicted) \
-__PMC_EV(K7, RETIRED_TAKEN_BRANCHES, k7-retired-taken-branches) \
-__PMC_EV(K7, RETIRED_TAKEN_BRANCHES_MISPREDICTED, \
- k7-retired-taken-branches-mispredicted) \
-__PMC_EV(K7, RETIRED_FAR_CONTROL_TRANSFERS, \
- k7-retired-far-control-transfers) \
-__PMC_EV(K7, RETIRED_RESYNC_BRANCHES, k7-retired-resync-branches) \
-__PMC_EV(K7, INTERRUPTS_MASKED_CYCLES, k7-interrupts-masked-cycles) \
-__PMC_EV(K7, INTERRUPTS_MASKED_WHILE_PENDING_CYCLES, \
- k7-interrupts-masked-while-pending-cycles) \
-__PMC_EV(K7, HARDWARE_INTERRUPTS, k7-hardware-interrupts)
+#define __PMC_EV_K7() \
+__PMC_EV(K7, DC_ACCESSES) \
+__PMC_EV(K7, DC_MISSES) \
+__PMC_EV(K7, DC_REFILLS_FROM_L2) \
+__PMC_EV(K7, DC_REFILLS_FROM_SYSTEM) \
+__PMC_EV(K7, DC_WRITEBACKS) \
+__PMC_EV(K7, L1_DTLB_MISS_AND_L2_DTLB_HITS) \
+__PMC_EV(K7, L1_AND_L2_DTLB_MISSES) \
+__PMC_EV(K7, MISALIGNED_REFERENCES) \
+__PMC_EV(K7, IC_FETCHES) \
+__PMC_EV(K7, IC_MISSES) \
+__PMC_EV(K7, L1_ITLB_MISSES) \
+__PMC_EV(K7, L1_L2_ITLB_MISSES) \
+__PMC_EV(K7, RETIRED_INSTRUCTIONS) \
+__PMC_EV(K7, RETIRED_OPS) \
+__PMC_EV(K7, RETIRED_BRANCHES) \
+__PMC_EV(K7, RETIRED_BRANCHES_MISPREDICTED) \
+__PMC_EV(K7, RETIRED_TAKEN_BRANCHES) \
+__PMC_EV(K7, RETIRED_TAKEN_BRANCHES_MISPREDICTED) \
+__PMC_EV(K7, RETIRED_FAR_CONTROL_TRANSFERS) \
+__PMC_EV(K7, RETIRED_RESYNC_BRANCHES) \
+__PMC_EV(K7, INTERRUPTS_MASKED_CYCLES) \
+__PMC_EV(K7, INTERRUPTS_MASKED_WHILE_PENDING_CYCLES) \
+__PMC_EV(K7, HARDWARE_INTERRUPTS)
#define PMC_EV_K7_FIRST PMC_EV_K7_DC_ACCESSES
#define PMC_EV_K7_LAST PMC_EV_K7_HARDWARE_INTERRUPTS
+
/*
* Intel P4 Events, from "IA-32 Intel(r) Architecture Software
* Developer's Manual, Volume 3: System Programming Guide" [245472-012]
*/
-#define __PMC_EV_P4() \
-__PMC_EV(P4, TC_DELIVER_MODE, p4-tc-deliver-mode) \
-__PMC_EV(P4, BPU_FETCH_REQUEST, p4-bpu-fetch-request) \
-__PMC_EV(P4, ITLB_REFERENCE, p4-itlb-reference) \
-__PMC_EV(P4, MEMORY_CANCEL, p4-memory-cancel) \
-__PMC_EV(P4, MEMORY_COMPLETE, p4-memory-complete) \
-__PMC_EV(P4, LOAD_PORT_REPLAY, p4-load-port-replay) \
-__PMC_EV(P4, STORE_PORT_REPLAY, p4-store-port-replay) \
-__PMC_EV(P4, MOB_LOAD_REPLAY, p4-mob-load-replay) \
-__PMC_EV(P4, PAGE_WALK_TYPE, p4-page-walk-type) \
-__PMC_EV(P4, BSQ_CACHE_REFERENCE, p4-bsq-cache-reference) \
-__PMC_EV(P4, IOQ_ALLOCATION, p4-ioq-allocation) \
-__PMC_EV(P4, IOQ_ACTIVE_ENTRIES, p4-ioq-active-entries) \
-__PMC_EV(P4, FSB_DATA_ACTIVITY, p4-fsb-data-activity) \
-__PMC_EV(P4, BSQ_ALLOCATION, p4-bsq-allocation) \
-__PMC_EV(P4, BSQ_ACTIVE_ENTRIES, p4-bsq-active-entries) \
-__PMC_EV(P4, SSE_INPUT_ASSIST, p4-sse-input-assist) \
-__PMC_EV(P4, PACKED_SP_UOP, p4-packed-sp-uop) \
-__PMC_EV(P4, PACKED_DP_UOP, p4-packed-dp-uop) \
-__PMC_EV(P4, SCALAR_SP_UOP, p4-scalar-sp-uop) \
-__PMC_EV(P4, SCALAR_DP_UOP, p4-scalar-dp-uop) \
-__PMC_EV(P4, 64BIT_MMX_UOP, p4-64bit-mmx-uop) \
-__PMC_EV(P4, 128BIT_MMX_UOP, p4-128bit-mmx-uop) \
-__PMC_EV(P4, X87_FP_UOP, p4-x87-fp-uop) \
-__PMC_EV(P4, X87_SIMD_MOVES_UOP, p4-x87-simd-moves-uop) \
-__PMC_EV(P4, GLOBAL_POWER_EVENTS, p4-global-power-events) \
-__PMC_EV(P4, TC_MS_XFER, p4-tc-ms-xfer) \
-__PMC_EV(P4, UOP_QUEUE_WRITES, p4-uop-queue-writes) \
-__PMC_EV(P4, RETIRED_MISPRED_BRANCH_TYPE, \
- p4-retired-mispred-branch-type) \
-__PMC_EV(P4, RETIRED_BRANCH_TYPE, p4-retired-branch-type) \
-__PMC_EV(P4, RESOURCE_STALL, p4-resource-stall) \
-__PMC_EV(P4, WC_BUFFER, p4-wc-buffer) \
-__PMC_EV(P4, B2B_CYCLES, p4-b2b-cycles) \
-__PMC_EV(P4, BNR, p4-bnr) \
-__PMC_EV(P4, SNOOP, p4-snoop) \
-__PMC_EV(P4, RESPONSE, p4-response) \
-__PMC_EV(P4, FRONT_END_EVENT, p4-front-end-event) \
-__PMC_EV(P4, EXECUTION_EVENT, p4-execution-event) \
-__PMC_EV(P4, REPLAY_EVENT, p4-replay-event) \
-__PMC_EV(P4, INSTR_RETIRED, p4-instr-retired) \
-__PMC_EV(P4, UOPS_RETIRED, p4-uops-retired) \
-__PMC_EV(P4, UOP_TYPE, p4-uop-type) \
-__PMC_EV(P4, BRANCH_RETIRED, p4-branch-retired) \
-__PMC_EV(P4, MISPRED_BRANCH_RETIRED, p4-mispred-branch-retired) \
-__PMC_EV(P4, X87_ASSIST, p4-x87-assist) \
-__PMC_EV(P4, MACHINE_CLEAR, p4-machine-clear)
+#define __PMC_EV_P4() \
+__PMC_EV(P4, TC_DELIVER_MODE) \
+__PMC_EV(P4, BPU_FETCH_REQUEST) \
+__PMC_EV(P4, ITLB_REFERENCE) \
+__PMC_EV(P4, MEMORY_CANCEL) \
+__PMC_EV(P4, MEMORY_COMPLETE) \
+__PMC_EV(P4, LOAD_PORT_REPLAY) \
+__PMC_EV(P4, STORE_PORT_REPLAY) \
+__PMC_EV(P4, MOB_LOAD_REPLAY) \
+__PMC_EV(P4, PAGE_WALK_TYPE) \
+__PMC_EV(P4, BSQ_CACHE_REFERENCE) \
+__PMC_EV(P4, IOQ_ALLOCATION) \
+__PMC_EV(P4, IOQ_ACTIVE_ENTRIES) \
+__PMC_EV(P4, FSB_DATA_ACTIVITY) \
+__PMC_EV(P4, BSQ_ALLOCATION) \
+__PMC_EV(P4, BSQ_ACTIVE_ENTRIES) \
+__PMC_EV(P4, SSE_INPUT_ASSIST) \
+__PMC_EV(P4, PACKED_SP_UOP) \
+__PMC_EV(P4, PACKED_DP_UOP) \
+__PMC_EV(P4, SCALAR_SP_UOP) \
+__PMC_EV(P4, SCALAR_DP_UOP) \
+__PMC_EV(P4, 64BIT_MMX_UOP) \
+__PMC_EV(P4, 128BIT_MMX_UOP) \
+__PMC_EV(P4, X87_FP_UOP) \
+__PMC_EV(P4, X87_SIMD_MOVES_UOP) \
+__PMC_EV(P4, GLOBAL_POWER_EVENTS) \
+__PMC_EV(P4, TC_MS_XFER) \
+__PMC_EV(P4, UOP_QUEUE_WRITES) \
+__PMC_EV(P4, RETIRED_MISPRED_BRANCH_TYPE) \
+__PMC_EV(P4, RETIRED_BRANCH_TYPE) \
+__PMC_EV(P4, RESOURCE_STALL) \
+__PMC_EV(P4, WC_BUFFER) \
+__PMC_EV(P4, B2B_CYCLES) \
+__PMC_EV(P4, BNR) \
+__PMC_EV(P4, SNOOP) \
+__PMC_EV(P4, RESPONSE) \
+__PMC_EV(P4, FRONT_END_EVENT) \
+__PMC_EV(P4, EXECUTION_EVENT) \
+__PMC_EV(P4, REPLAY_EVENT) \
+__PMC_EV(P4, INSTR_RETIRED) \
+__PMC_EV(P4, UOPS_RETIRED) \
+__PMC_EV(P4, UOP_TYPE) \
+__PMC_EV(P4, BRANCH_RETIRED) \
+__PMC_EV(P4, MISPRED_BRANCH_RETIRED) \
+__PMC_EV(P4, X87_ASSIST) \
+__PMC_EV(P4, MACHINE_CLEAR)
#define PMC_EV_P4_FIRST PMC_EV_P4_TC_DELIVER_MODE
#define PMC_EV_P4_LAST PMC_EV_P4_MACHINE_CLEAR
/* Intel Pentium Pro, P-II, P-III and Pentium-M style events */
-#define __PMC_EV_P6() \
-__PMC_EV(P6, DATA_MEM_REFS, p6-data-mem-refs) \
-__PMC_EV(P6, DCU_LINES_IN, p6-dcu-lines-in) \
-__PMC_EV(P6, DCU_M_LINES_IN, p6-dcu-m-lines-in) \
-__PMC_EV(P6, DCU_M_LINES_OUT, p6-dcu-m-lines-out) \
-__PMC_EV(P6, DCU_MISS_OUTSTANDING, p6-dcu-miss-outstanding) \
-__PMC_EV(P6, IFU_FETCH, p6-ifu-fetch) \
-__PMC_EV(P6, IFU_FETCH_MISS, p6-ifu-fetch-miss) \
-__PMC_EV(P6, ITLB_MISS, p6-itlb-miss) \
-__PMC_EV(P6, IFU_MEM_STALL, p6-ifu-mem-stall) \
-__PMC_EV(P6, ILD_STALL, p6-ild-stall) \
-__PMC_EV(P6, L2_IFETCH, p6-l2-ifetch) \
-__PMC_EV(P6, L2_LD, p6-l2-ld) \
-__PMC_EV(P6, L2_ST, p6-l2-st) \
-__PMC_EV(P6, L2_LINES_IN, p6-l2-lines-in) \
-__PMC_EV(P6, L2_LINES_OUT, p6-l2-lines-out) \
-__PMC_EV(P6, L2_M_LINES_INM, p6-l2-m-lines-inm) \
-__PMC_EV(P6, L2_M_LINES_OUTM, p6-l2-m-lines-outm) \
-__PMC_EV(P6, L2_RQSTS, p6-l2-rqsts) \
-__PMC_EV(P6, L2_ADS, p6-l2-ads) \
-__PMC_EV(P6, L2_DBUS_BUSY, p6-l2-dbus-busy) \
-__PMC_EV(P6, L2_DBUS_BUSY_RD, p6-l2-dbus-busy-rd) \
-__PMC_EV(P6, BUS_DRDY_CLOCKS, p6-bus-drdy-clocks) \
-__PMC_EV(P6, BUS_LOCK_CLOCKS, p6-bus-lock-clocks) \
-__PMC_EV(P6, BUS_REQ_OUTSTANDING, p6-bus-req-outstanding) \
-__PMC_EV(P6, BUS_TRAN_BRD, p6-bus-tran-brd) \
-__PMC_EV(P6, BUS_TRAN_RFO, p6-bus-tran-rfo) \
-__PMC_EV(P6, BUS_TRANS_WB, p6-bus-trans-wb) \
-__PMC_EV(P6, BUS_TRAN_IFETCH, p6-bus-tran-ifetch) \
-__PMC_EV(P6, BUS_TRAN_INVAL, p6-bus-tran-inval) \
-__PMC_EV(P6, BUS_TRAN_PWR, p6-bus-tran-pwr) \
-__PMC_EV(P6, BUS_TRANS_P, p6-bus-trans-p) \
-__PMC_EV(P6, BUS_TRANS_IO, p6-bus-trans-io) \
-__PMC_EV(P6, BUS_TRAN_DEF, p6-bus-tran-def) \
-__PMC_EV(P6, BUS_TRAN_BURST, p6-bus-tran-burst) \
-__PMC_EV(P6, BUS_TRAN_ANY, p6-bus-tran-any) \
-__PMC_EV(P6, BUS_TRAN_MEM, p6-bus-tran-mem) \
-__PMC_EV(P6, BUS_DATA_RCV, p6-bus-data-rcv) \
-__PMC_EV(P6, BUS_BNR_DRV, p6-bus-bnr-drv) \
-__PMC_EV(P6, BUS_HIT_DRV, p6-bus-hit-drv) \
-__PMC_EV(P6, BUS_HITM_DRV, p6-bus-hitm-drv) \
-__PMC_EV(P6, BUS_SNOOP_STALL, p6-bus-snoop-stall) \
-__PMC_EV(P6, FLOPS, p6-flops) \
-__PMC_EV(P6, FP_COMPS_OPS_EXE, p6-fp-comps-ops-exe) \
-__PMC_EV(P6, FP_ASSIST, p6-fp-assist) \
-__PMC_EV(P6, MUL, p6-mul) \
-__PMC_EV(P6, DIV, p6-div) \
-__PMC_EV(P6, CYCLES_DIV_BUSY, p6-cycles-div-busy) \
-__PMC_EV(P6, LD_BLOCKS, p6-ld-blocks) \
-__PMC_EV(P6, SB_DRAINS, p6-sb-drains) \
-__PMC_EV(P6, MISALIGN_MEM_REF, p6-misalign-mem-ref) \
-__PMC_EV(P6, EMON_KNI_PREF_DISPATCHED, p6-emon-kni-pref-dispatched) \
-__PMC_EV(P6, EMON_KNI_PREF_MISS, p6-emon-kni-pref-miss) \
-__PMC_EV(P6, INST_RETIRED, p6-inst-retired) \
-__PMC_EV(P6, UOPS_RETIRED, p6-uops-retired) \
-__PMC_EV(P6, INST_DECODED, p6-inst-decoded) \
-__PMC_EV(P6, EMON_KNI_INST_RETIRED, p6-emon-kni-inst-retired) \
-__PMC_EV(P6, EMON_KNI_COMP_INST_RET, p6-emon-kni-comp-inst-ret) \
-__PMC_EV(P6, HW_INT_RX, p6-hw-int-rx) \
-__PMC_EV(P6, CYCLES_INT_MASKED, p6-cycles-int-masked) \
-__PMC_EV(P6, CYCLES_INT_PENDING_AND_MASKED, \
- p6-cycles-in-pending-and-masked) \
-__PMC_EV(P6, BR_INST_RETIRED, p6-br-inst-retired) \
-__PMC_EV(P6, BR_MISS_PRED_RETIRED, p6-br-miss-pred-retired) \
-__PMC_EV(P6, BR_TAKEN_RETIRED, p6-br-taken-retired) \
-__PMC_EV(P6, BR_MISS_PRED_TAKEN_RET, p6-br-miss-pred-taken-ret) \
-__PMC_EV(P6, BR_INST_DECODED, p6-br-inst-decoded) \
-__PMC_EV(P6, BTB_MISSES, p6-btb-misses) \
-__PMC_EV(P6, BR_BOGUS, p6-br-bogus) \
-__PMC_EV(P6, BACLEARS, p6-baclears) \
-__PMC_EV(P6, RESOURCE_STALLS, p6-resource-stalls) \
-__PMC_EV(P6, PARTIAL_RAT_STALLS, p6-partial-rat-stalls) \
-__PMC_EV(P6, SEGMENT_REG_LOADS, p6-segment-reg-loads) \
-__PMC_EV(P6, CPU_CLK_UNHALTED, p6-cpu-clk-unhalted) \
-__PMC_EV(P6, MMX_INSTR_EXEC, p6-mmx-instr-exec) \
-__PMC_EV(P6, MMX_SAT_INSTR_EXEC, p6-mmx-sat-instr-exec) \
-__PMC_EV(P6, MMX_UOPS_EXEC, p6-mmx-uops-exec) \
-__PMC_EV(P6, MMX_INSTR_TYPE_EXEC, p6-mmx-instr-type-exec) \
-__PMC_EV(P6, FP_MMX_TRANS, p6-fp-mmx-trans) \
-__PMC_EV(P6, MMX_ASSIST, p6-mmx-assist) \
-__PMC_EV(P6, MMX_INSTR_RET, p6-mmx-instr-ret) \
-__PMC_EV(P6, SEG_RENAME_STALLS, p6-seg-rename-stalls) \
-__PMC_EV(P6, SEG_REG_RENAMES, p6-seg-reg-renames) \
-__PMC_EV(P6, RET_SEG_RENAMES, p6-ret-seg-renames) \
-__PMC_EV(P6, EMON_EST_TRANS, p6-emon-est-trans) \
-__PMC_EV(P6, EMON_THERMAL_TRIP, p6-emon-thermal-trip) \
-__PMC_EV(P6, BR_INST_EXEC, p6-br-inst-exec) \
-__PMC_EV(P6, BR_MISSP_EXEC, p6-br-missp-exec) \
-__PMC_EV(P6, BR_BAC_MISSP_EXEC, p6-br-bac-missp-exec) \
-__PMC_EV(P6, BR_CND_EXEC, p6-br-cnd-exec) \
-__PMC_EV(P6, BR_CND_MISSP_EXEC, p6-br-cnd-missp-exec) \
-__PMC_EV(P6, BR_IND_EXEC, p6-br-ind-exec) \
-__PMC_EV(P6, BR_IND_MISSP_EXEC, p6-br-ind-missp-exec) \
-__PMC_EV(P6, BR_RET_EXEC, p6-br-ret-exec) \
-__PMC_EV(P6, BR_RET_MISSP_EXEC, p6-br-ret-missp-exec) \
-__PMC_EV(P6, BR_RET_BAC_MISSP_EXEC, p6-br-ret-bac-missp-exec) \
-__PMC_EV(P6, BR_CALL_EXEC, p6-br-call-exec) \
-__PMC_EV(P6, BR_CALL_MISSP_EXEC, p6-br-call-missp-exec) \
-__PMC_EV(P6, BR_IND_CALL_EXEC, p6-br-ind-call-exec) \
-__PMC_EV(P6, EMON_SIMD_INSTR_RETIRED, p6-emon-simd-instr-retired) \
-__PMC_EV(P6, EMON_SYNCH_UOPS, p6-emon-synch-uops) \
-__PMC_EV(P6, EMON_ESP_UOPS, p6-emon-esp-uops) \
-__PMC_EV(P6, EMON_FUSED_UOPS_RET, p6-emon-fused-uops-ret) \
-__PMC_EV(P6, EMON_UNFUSION, p6-emon-unfusion) \
-__PMC_EV(P6, EMON_PREF_RQSTS_UP, p6-emon-pref-rqsts-up) \
-__PMC_EV(P6, EMON_PREF_RQSTS_DN, p6-emon-pref-rqsts-dn) \
-__PMC_EV(P6, EMON_SSE_SSE2_INST_RETIRED, \
- p6-emon-sse-sse2-inst-retired) \
-__PMC_EV(P6, EMON_SSE_SSE2_COMP_INST_RETIRED, \
- p6-emon-sse-sse2-comp-inst-retired)
+#define __PMC_EV_P6() \
+__PMC_EV(P6, DATA_MEM_REFS) \
+__PMC_EV(P6, DCU_LINES_IN) \
+__PMC_EV(P6, DCU_M_LINES_IN) \
+__PMC_EV(P6, DCU_M_LINES_OUT) \
+__PMC_EV(P6, DCU_MISS_OUTSTANDING) \
+__PMC_EV(P6, IFU_FETCH) \
+__PMC_EV(P6, IFU_FETCH_MISS) \
+__PMC_EV(P6, ITLB_MISS) \
+__PMC_EV(P6, IFU_MEM_STALL) \
+__PMC_EV(P6, ILD_STALL) \
+__PMC_EV(P6, L2_IFETCH) \
+__PMC_EV(P6, L2_LD) \
+__PMC_EV(P6, L2_ST) \
+__PMC_EV(P6, L2_LINES_IN) \
+__PMC_EV(P6, L2_LINES_OUT) \
+__PMC_EV(P6, L2_M_LINES_INM) \
+__PMC_EV(P6, L2_M_LINES_OUTM) \
+__PMC_EV(P6, L2_RQSTS) \
+__PMC_EV(P6, L2_ADS) \
+__PMC_EV(P6, L2_DBUS_BUSY) \
+__PMC_EV(P6, L2_DBUS_BUSY_RD) \
+__PMC_EV(P6, BUS_DRDY_CLOCKS) \
+__PMC_EV(P6, BUS_LOCK_CLOCKS) \
+__PMC_EV(P6, BUS_REQ_OUTSTANDING) \
+__PMC_EV(P6, BUS_TRAN_BRD) \
+__PMC_EV(P6, BUS_TRAN_RFO) \
+__PMC_EV(P6, BUS_TRANS_WB) \
+__PMC_EV(P6, BUS_TRAN_IFETCH) \
+__PMC_EV(P6, BUS_TRAN_INVAL) \
+__PMC_EV(P6, BUS_TRAN_PWR) \
+__PMC_EV(P6, BUS_TRANS_P) \
+__PMC_EV(P6, BUS_TRANS_IO) \
+__PMC_EV(P6, BUS_TRAN_DEF) \
+__PMC_EV(P6, BUS_TRAN_BURST) \
+__PMC_EV(P6, BUS_TRAN_ANY) \
+__PMC_EV(P6, BUS_TRAN_MEM) \
+__PMC_EV(P6, BUS_DATA_RCV) \
+__PMC_EV(P6, BUS_BNR_DRV) \
+__PMC_EV(P6, BUS_HIT_DRV) \
+__PMC_EV(P6, BUS_HITM_DRV) \
+__PMC_EV(P6, BUS_SNOOP_STALL) \
+__PMC_EV(P6, FLOPS) \
+__PMC_EV(P6, FP_COMPS_OPS_EXE) \
+__PMC_EV(P6, FP_ASSIST) \
+__PMC_EV(P6, MUL) \
+__PMC_EV(P6, DIV) \
+__PMC_EV(P6, CYCLES_DIV_BUSY) \
+__PMC_EV(P6, LD_BLOCKS) \
+__PMC_EV(P6, SB_DRAINS) \
+__PMC_EV(P6, MISALIGN_MEM_REF) \
+__PMC_EV(P6, EMON_KNI_PREF_DISPATCHED) \
+__PMC_EV(P6, EMON_KNI_PREF_MISS) \
+__PMC_EV(P6, INST_RETIRED) \
+__PMC_EV(P6, UOPS_RETIRED) \
+__PMC_EV(P6, INST_DECODED) \
+__PMC_EV(P6, EMON_KNI_INST_RETIRED) \
+__PMC_EV(P6, EMON_KNI_COMP_INST_RET) \
+__PMC_EV(P6, HW_INT_RX) \
+__PMC_EV(P6, CYCLES_INT_MASKED) \
+__PMC_EV(P6, CYCLES_INT_PENDING_AND_MASKED) \
+__PMC_EV(P6, BR_INST_RETIRED) \
+__PMC_EV(P6, BR_MISS_PRED_RETIRED) \
+__PMC_EV(P6, BR_TAKEN_RETIRED) \
+__PMC_EV(P6, BR_MISS_PRED_TAKEN_RET) \
+__PMC_EV(P6, BR_INST_DECODED) \
+__PMC_EV(P6, BTB_MISSES) \
+__PMC_EV(P6, BR_BOGUS) \
+__PMC_EV(P6, BACLEARS) \
+__PMC_EV(P6, RESOURCE_STALLS) \
+__PMC_EV(P6, PARTIAL_RAT_STALLS) \
+__PMC_EV(P6, SEGMENT_REG_LOADS) \
+__PMC_EV(P6, CPU_CLK_UNHALTED) \
+__PMC_EV(P6, MMX_INSTR_EXEC) \
+__PMC_EV(P6, MMX_SAT_INSTR_EXEC) \
+__PMC_EV(P6, MMX_UOPS_EXEC) \
+__PMC_EV(P6, MMX_INSTR_TYPE_EXEC) \
+__PMC_EV(P6, FP_MMX_TRANS) \
+__PMC_EV(P6, MMX_ASSIST) \
+__PMC_EV(P6, MMX_INSTR_RET) \
+__PMC_EV(P6, SEG_RENAME_STALLS) \
+__PMC_EV(P6, SEG_REG_RENAMES) \
+__PMC_EV(P6, RET_SEG_RENAMES) \
+__PMC_EV(P6, EMON_EST_TRANS) \
+__PMC_EV(P6, EMON_THERMAL_TRIP) \
+__PMC_EV(P6, BR_INST_EXEC) \
+__PMC_EV(P6, BR_MISSP_EXEC) \
+__PMC_EV(P6, BR_BAC_MISSP_EXEC) \
+__PMC_EV(P6, BR_CND_EXEC) \
+__PMC_EV(P6, BR_CND_MISSP_EXEC) \
+__PMC_EV(P6, BR_IND_EXEC) \
+__PMC_EV(P6, BR_IND_MISSP_EXEC) \
+__PMC_EV(P6, BR_RET_EXEC) \
+__PMC_EV(P6, BR_RET_MISSP_EXEC) \
+__PMC_EV(P6, BR_RET_BAC_MISSP_EXEC) \
+__PMC_EV(P6, BR_CALL_EXEC) \
+__PMC_EV(P6, BR_CALL_MISSP_EXEC) \
+__PMC_EV(P6, BR_IND_CALL_EXEC) \
+__PMC_EV(P6, EMON_SIMD_INSTR_RETIRED) \
+__PMC_EV(P6, EMON_SYNCH_UOPS) \
+__PMC_EV(P6, EMON_ESP_UOPS) \
+__PMC_EV(P6, EMON_FUSED_UOPS_RET) \
+__PMC_EV(P6, EMON_UNFUSION) \
+__PMC_EV(P6, EMON_PREF_RQSTS_UP) \
+__PMC_EV(P6, EMON_PREF_RQSTS_DN) \
+__PMC_EV(P6, EMON_SSE_SSE2_INST_RETIRED) \
+__PMC_EV(P6, EMON_SSE_SSE2_COMP_INST_RETIRED)
#define PMC_EV_P6_FIRST PMC_EV_P6_DATA_MEM_REFS
@@ -250,281 +242,1724 @@ __PMC_EV(P6, EMON_SSE_SSE2_COMP_INST_RETIRED, \
/* AMD K8 PMCs */
#define __PMC_EV_K8() \
-__PMC_EV(K8, FP_DISPATCHED_FPU_OPS, k8-fp-dispatched-fpu-ops) \
-__PMC_EV(K8, FP_CYCLES_WITH_NO_FPU_OPS_RETIRED, \
- k8-fp-cycles-with-no-fpu-ops-retired) \
-__PMC_EV(K8, FP_DISPATCHED_FPU_FAST_FLAG_OPS, \
- k8-fp-dispatched-fpu-fast-flag-ops) \
-__PMC_EV(K8, LS_SEGMENT_REGISTER_LOAD, k8-ls-segment-register-load) \
-__PMC_EV(K8, LS_MICROARCHITECTURAL_RESYNC_BY_SELF_MODIFYING_CODE, \
- k8-ls-microarchitectural-resync-by-self-modifying-code) \
-__PMC_EV(K8, LS_MICROARCHITECTURAL_RESYNC_BY_SNOOP, \
- k8-ls-microarchitectural-resync-by-snoop) \
-__PMC_EV(K8, LS_BUFFER2_FULL, k8-ls-buffer2-full) \
-__PMC_EV(K8, LS_LOCKED_OPERATION, k8-ls-locked-operation) \
-__PMC_EV(K8, LS_MICROARCHITECTURAL_LATE_CANCEL, \
- k8-ls-microarchitectural-late-cancel) \
-__PMC_EV(K8, LS_RETIRED_CFLUSH_INSTRUCTIONS, \
- k8-ls-retired-cflush-instructions) \
-__PMC_EV(K8, LS_RETIRED_CPUID_INSTRUCTIONS, \
- k8-ls-retired-cpuid-instructions) \
-__PMC_EV(K8, DC_ACCESS, k8-dc-access) \
-__PMC_EV(K8, DC_MISS, k8-dc-miss) \
-__PMC_EV(K8, DC_REFILL_FROM_L2, k8-dc-refill-from-l2) \
-__PMC_EV(K8, DC_REFILL_FROM_SYSTEM, k8-dc-refill-from-system) \
-__PMC_EV(K8, DC_COPYBACK, k8-dc-copyback) \
-__PMC_EV(K8, DC_L1_DTLB_MISS_AND_L2_DTLB_HIT, \
- k8-dc-l1-dtlb-miss-and-l2-dtlb-hit) \
-__PMC_EV(K8, DC_L1_DTLB_MISS_AND_L2_DTLB_MISS, \
- k8-dc-l1-dtlb-miss-and-l2-dtlb-miss) \
-__PMC_EV(K8, DC_MISALIGNED_DATA_REFERENCE, \
- k8-dc-misaligned-data-reference) \
-__PMC_EV(K8, DC_MICROARCHITECTURAL_LATE_CANCEL, \
- k8-dc-microarchitectural-late-cancel-of-an-access) \
-__PMC_EV(K8, DC_MICROARCHITECTURAL_EARLY_CANCEL, \
- k8-dc-microarchitectural-early-cancel-of-an-access) \
-__PMC_EV(K8, DC_ONE_BIT_ECC_ERROR, k8-dc-one-bit-ecc-error) \
-__PMC_EV(K8, DC_DISPATCHED_PREFETCH_INSTRUCTIONS, \
- k8-dc-dispatched-prefetch-instructions) \
-__PMC_EV(K8, DC_DCACHE_ACCESSES_BY_LOCKS, \
- k8-dc-dcache-accesses-by-locks) \
-__PMC_EV(K8, BU_CPU_CLK_UNHALTED, k8-bu-cpu-clk-unhalted) \
-__PMC_EV(K8, BU_INTERNAL_L2_REQUEST, k8-bu-internal-l2-request) \
-__PMC_EV(K8, BU_FILL_REQUEST_L2_MISS, k8-bu-fill-request-l2-miss) \
-__PMC_EV(K8, BU_FILL_INTO_L2, k8-bu-fill-into-l2) \
-__PMC_EV(K8, IC_FETCH, k8-ic-fetch) \
-__PMC_EV(K8, IC_MISS, k8-ic-miss) \
-__PMC_EV(K8, IC_REFILL_FROM_L2, k8-ic-refill-from-l2) \
-__PMC_EV(K8, IC_REFILL_FROM_SYSTEM, k8-ic-refill-from-system) \
-__PMC_EV(K8, IC_L1_ITLB_MISS_AND_L2_ITLB_HIT, \
- k8-ic-l1-itlb-miss-and-l2-itlb-hit) \
-__PMC_EV(K8, IC_L1_ITLB_MISS_AND_L2_ITLB_MISS, \
- k8-ic-l1-itlb-miss-and-l2-itlb-miss) \
-__PMC_EV(K8, IC_MICROARCHITECTURAL_RESYNC_BY_SNOOP, \
- k8-ic-microarchitectural-resync-by-snoop) \
-__PMC_EV(K8, IC_INSTRUCTION_FETCH_STALL, \
- k8-ic-instruction-fetch-stall) \
-__PMC_EV(K8, IC_RETURN_STACK_HIT, k8-ic-return-stack-hit) \
-__PMC_EV(K8, IC_RETURN_STACK_OVERFLOW, k8-ic-return-stack-overflow) \
-__PMC_EV(K8, FR_RETIRED_X86_INSTRUCTIONS, \
- k8-fr-retired-x86-instructions) \
-__PMC_EV(K8, FR_RETIRED_UOPS, k8-fr-retired-uops) \
-__PMC_EV(K8, FR_RETIRED_BRANCHES, k8-fr-retired-branches) \
-__PMC_EV(K8, FR_RETIRED_BRANCHES_MISPREDICTED, \
- k8-fr-retired-branches-mispredicted) \
-__PMC_EV(K8, FR_RETIRED_TAKEN_BRANCHES, \
- k8-fr-retired-taken-branches) \
-__PMC_EV(K8, FR_RETIRED_TAKEN_BRANCHES_MISPREDICTED, \
- k8-fr-retired-taken-branches-mispredicted) \
-__PMC_EV(K8, FR_RETIRED_FAR_CONTROL_TRANSFERS, \
- k8-fr-retired-far-control-transfers) \
-__PMC_EV(K8, FR_RETIRED_RESYNCS, k8-fr-retired-resyncs) \
-__PMC_EV(K8, FR_RETIRED_NEAR_RETURNS, k8-fr-retired-near-returns) \
-__PMC_EV(K8, FR_RETIRED_NEAR_RETURNS_MISPREDICTED, \
- k8-fr-retired-near-returns-mispredicted) \
-__PMC_EV(K8, \
- FR_RETIRED_TAKEN_BRANCHES_MISPREDICTED_BY_ADDR_MISCOMPARE, \
- k8-fr-retired-taken-branches-mispredicted-by-addr-miscompare) \
-__PMC_EV(K8, FR_RETIRED_FPU_INSTRUCTIONS, \
- k8-fr-retired-fpu-instructions) \
-__PMC_EV(K8, FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS, \
- k8-fr-retired-fastpath-double-op-instructions) \
-__PMC_EV(K8, FR_INTERRUPTS_MASKED_CYCLES, \
- k8-fr-interrupts-masked-cycles) \
-__PMC_EV(K8, FR_INTERRUPTS_MASKED_WHILE_PENDING_CYCLES, \
- k8-fr-interrupts-masked-while-pending-cycles) \
-__PMC_EV(K8, FR_TAKEN_HARDWARE_INTERRUPTS, \
- k8-fr-taken-hardware-interrupts) \
-__PMC_EV(K8, FR_DECODER_EMPTY, k8-fr-decoder-empty) \
-__PMC_EV(K8, FR_DISPATCH_STALLS, k8-fr-dispatch-stalls) \
-__PMC_EV(K8, FR_DISPATCH_STALL_FROM_BRANCH_ABORT_TO_RETIRE, \
- k8-fr-dispatch-stall-from-branch-abort-to-retire) \
-__PMC_EV(K8, FR_DISPATCH_STALL_FOR_SERIALIZATION, \
- k8-fr-dispatch-stall-for-serialization) \
-__PMC_EV(K8, FR_DISPATCH_STALL_FOR_SEGMENT_LOAD, \
- k8-fr-dispatch-stall-for-segment-load) \
-__PMC_EV(K8, FR_DISPATCH_STALL_WHEN_REORDER_BUFFER_IS_FULL, \
- k8-fr-dispatch-stall-when-reorder-buffer-is-full) \
-__PMC_EV(K8, \
- FR_DISPATCH_STALL_WHEN_RESERVATION_STATIONS_ARE_FULL, \
- k8-fr-dispatch-stall-when-reservation-stations-are-full) \
-__PMC_EV(K8, FR_DISPATCH_STALL_WHEN_FPU_IS_FULL, \
- k8-fr-dispatch-stall-when-fpu-is-full) \
-__PMC_EV(K8, FR_DISPATCH_STALL_WHEN_LS_IS_FULL, \
- k8-fr-dispatch-stall-when-ls-is-full) \
-__PMC_EV(K8, FR_DISPATCH_STALL_WHEN_WAITING_FOR_ALL_TO_BE_QUIET, \
- k8-fr-dispatch-stall-when-waiting-for-all-to-be-quiet) \
-__PMC_EV(K8, \
- FR_DISPATCH_STALL_WHEN_FAR_XFER_OR_RESYNC_BRANCH_PENDING, \
- k8-fr-dispatch-stall-when-far-xfer-or-resync-branch-pending) \
-__PMC_EV(K8, FR_FPU_EXCEPTIONS, k8-fr-fpu-exceptions) \
-__PMC_EV(K8, FR_NUMBER_OF_BREAKPOINTS_FOR_DR0, \
- k8-fr-number-of-breakpoints-for-dr0) \
-__PMC_EV(K8, FR_NUMBER_OF_BREAKPOINTS_FOR_DR1, \
- k8-fr-number-of-breakpoints-for-dr1) \
-__PMC_EV(K8, FR_NUMBER_OF_BREAKPOINTS_FOR_DR2, \
- k8-fr-number-of-breakpoints-for-dr2) \
-__PMC_EV(K8, FR_NUMBER_OF_BREAKPOINTS_FOR_DR3, \
- k8-fr-number-of-breakpoints-for-dr3) \
-__PMC_EV(K8, NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT, \
- k8-nb-memory-controller-page-access-event) \
-__PMC_EV(K8, NB_MEMORY_CONTROLLER_PAGE_TABLE_OVERFLOW, \
- k8-nb-memory-controller-page-table-overflow) \
-__PMC_EV(K8, NB_MEMORY_CONTROLLER_DRAM_COMMAND_SLOTS_MISSED, \
- k8-nb-memory-controller-dram-slots-missed) \
-__PMC_EV(K8, NB_MEMORY_CONTROLLER_TURNAROUND, \
- k8-nb-memory-controller-turnaround) \
-__PMC_EV(K8, NB_MEMORY_CONTROLLER_BYPASS_SATURATION, \
- k8-nb-memory-controller-bypass-saturation) \
-__PMC_EV(K8, NB_SIZED_COMMANDS, k8-nb-sized-commands) \
-__PMC_EV(K8, NB_PROBE_RESULT, k8-nb-probe-result) \
-__PMC_EV(K8, NB_HT_BUS0_BANDWIDTH, k8-nb-ht-bus0-bandwidth) \
-__PMC_EV(K8, NB_HT_BUS1_BANDWIDTH, k8-nb-ht-bus1-bandwidth) \
-__PMC_EV(K8, NB_HT_BUS2_BANDWIDTH, k8-nb-ht-bus2-bandwidth)
+__PMC_EV(K8, FP_DISPATCHED_FPU_OPS) \
+__PMC_EV(K8, FP_CYCLES_WITH_NO_FPU_OPS_RETIRED) \
+__PMC_EV(K8, FP_DISPATCHED_FPU_FAST_FLAG_OPS) \
+__PMC_EV(K8, LS_SEGMENT_REGISTER_LOAD) \
+__PMC_EV(K8, LS_MICROARCHITECTURAL_RESYNC_BY_SELF_MODIFYING_CODE) \
+__PMC_EV(K8, LS_MICROARCHITECTURAL_RESYNC_BY_SNOOP) \
+__PMC_EV(K8, LS_BUFFER2_FULL) \
+__PMC_EV(K8, LS_LOCKED_OPERATION) \
+__PMC_EV(K8, LS_MICROARCHITECTURAL_LATE_CANCEL) \
+__PMC_EV(K8, LS_RETIRED_CFLUSH_INSTRUCTIONS) \
+__PMC_EV(K8, LS_RETIRED_CPUID_INSTRUCTIONS) \
+__PMC_EV(K8, DC_ACCESS) \
+__PMC_EV(K8, DC_MISS) \
+__PMC_EV(K8, DC_REFILL_FROM_L2) \
+__PMC_EV(K8, DC_REFILL_FROM_SYSTEM) \
+__PMC_EV(K8, DC_COPYBACK) \
+__PMC_EV(K8, DC_L1_DTLB_MISS_AND_L2_DTLB_HIT) \
+__PMC_EV(K8, DC_L1_DTLB_MISS_AND_L2_DTLB_MISS) \
+__PMC_EV(K8, DC_MISALIGNED_DATA_REFERENCE) \
+__PMC_EV(K8, DC_MICROARCHITECTURAL_LATE_CANCEL) \
+__PMC_EV(K8, DC_MICROARCHITECTURAL_EARLY_CANCEL) \
+__PMC_EV(K8, DC_ONE_BIT_ECC_ERROR) \
+__PMC_EV(K8, DC_DISPATCHED_PREFETCH_INSTRUCTIONS) \
+__PMC_EV(K8, DC_DCACHE_ACCESSES_BY_LOCKS) \
+__PMC_EV(K8, BU_CPU_CLK_UNHALTED) \
+__PMC_EV(K8, BU_INTERNAL_L2_REQUEST) \
+__PMC_EV(K8, BU_FILL_REQUEST_L2_MISS) \
+__PMC_EV(K8, BU_FILL_INTO_L2) \
+__PMC_EV(K8, IC_FETCH) \
+__PMC_EV(K8, IC_MISS) \
+__PMC_EV(K8, IC_REFILL_FROM_L2) \
+__PMC_EV(K8, IC_REFILL_FROM_SYSTEM) \
+__PMC_EV(K8, IC_L1_ITLB_MISS_AND_L2_ITLB_HIT) \
+__PMC_EV(K8, IC_L1_ITLB_MISS_AND_L2_ITLB_MISS) \
+__PMC_EV(K8, IC_MICROARCHITECTURAL_RESYNC_BY_SNOOP) \
+__PMC_EV(K8, IC_INSTRUCTION_FETCH_STALL) \
+__PMC_EV(K8, IC_RETURN_STACK_HIT) \
+__PMC_EV(K8, IC_RETURN_STACK_OVERFLOW) \
+__PMC_EV(K8, FR_RETIRED_X86_INSTRUCTIONS) \
+__PMC_EV(K8, FR_RETIRED_UOPS) \
+__PMC_EV(K8, FR_RETIRED_BRANCHES) \
+__PMC_EV(K8, FR_RETIRED_BRANCHES_MISPREDICTED) \
+__PMC_EV(K8, FR_RETIRED_TAKEN_BRANCHES) \
+__PMC_EV(K8, FR_RETIRED_TAKEN_BRANCHES_MISPREDICTED) \
+__PMC_EV(K8, FR_RETIRED_FAR_CONTROL_TRANSFERS) \
+__PMC_EV(K8, FR_RETIRED_RESYNCS) \
+__PMC_EV(K8, FR_RETIRED_NEAR_RETURNS) \
+__PMC_EV(K8, FR_RETIRED_NEAR_RETURNS_MISPREDICTED) \
+__PMC_EV(K8, FR_RETIRED_TAKEN_BRANCHES_MISPREDICTED_BY_ADDR_MISCOMPARE) \
+__PMC_EV(K8, FR_RETIRED_FPU_INSTRUCTIONS) \
+__PMC_EV(K8, FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS) \
+__PMC_EV(K8, FR_INTERRUPTS_MASKED_CYCLES) \
+__PMC_EV(K8, FR_INTERRUPTS_MASKED_WHILE_PENDING_CYCLES) \
+__PMC_EV(K8, FR_TAKEN_HARDWARE_INTERRUPTS) \
+__PMC_EV(K8, FR_DECODER_EMPTY) \
+__PMC_EV(K8, FR_DISPATCH_STALLS) \
+__PMC_EV(K8, FR_DISPATCH_STALL_FROM_BRANCH_ABORT_TO_RETIRE) \
+__PMC_EV(K8, FR_DISPATCH_STALL_FOR_SERIALIZATION) \
+__PMC_EV(K8, FR_DISPATCH_STALL_FOR_SEGMENT_LOAD) \
+__PMC_EV(K8, FR_DISPATCH_STALL_WHEN_REORDER_BUFFER_IS_FULL) \
+__PMC_EV(K8, FR_DISPATCH_STALL_WHEN_RESERVATION_STATIONS_ARE_FULL) \
+__PMC_EV(K8, FR_DISPATCH_STALL_WHEN_FPU_IS_FULL) \
+__PMC_EV(K8, FR_DISPATCH_STALL_WHEN_LS_IS_FULL) \
+__PMC_EV(K8, FR_DISPATCH_STALL_WHEN_WAITING_FOR_ALL_TO_BE_QUIET) \
+__PMC_EV(K8, FR_DISPATCH_STALL_WHEN_FAR_XFER_OR_RESYNC_BRANCH_PENDING) \
+__PMC_EV(K8, FR_FPU_EXCEPTIONS) \
+__PMC_EV(K8, FR_NUMBER_OF_BREAKPOINTS_FOR_DR0) \
+__PMC_EV(K8, FR_NUMBER_OF_BREAKPOINTS_FOR_DR1) \
+__PMC_EV(K8, FR_NUMBER_OF_BREAKPOINTS_FOR_DR2) \
+__PMC_EV(K8, FR_NUMBER_OF_BREAKPOINTS_FOR_DR3) \
+__PMC_EV(K8, NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT) \
+__PMC_EV(K8, NB_MEMORY_CONTROLLER_PAGE_TABLE_OVERFLOW) \
+__PMC_EV(K8, NB_MEMORY_CONTROLLER_DRAM_COMMAND_SLOTS_MISSED) \
+__PMC_EV(K8, NB_MEMORY_CONTROLLER_TURNAROUND) \
+__PMC_EV(K8, NB_MEMORY_CONTROLLER_BYPASS_SATURATION) \
+__PMC_EV(K8, NB_SIZED_COMMANDS) \
+__PMC_EV(K8, NB_PROBE_RESULT) \
+__PMC_EV(K8, NB_HT_BUS0_BANDWIDTH) \
+__PMC_EV(K8, NB_HT_BUS1_BANDWIDTH) \
+__PMC_EV(K8, NB_HT_BUS2_BANDWIDTH)
#define PMC_EV_K8_FIRST PMC_EV_K8_FP_DISPATCHED_FPU_OPS
#define PMC_EV_K8_LAST PMC_EV_K8_NB_HT_BUS2_BANDWIDTH
-/* Intel Pentium Events */
+/*
+ * Intel Pentium and Pentium MMX events, from the "Intel 64 and IA-32
+ * Architectures Software Developer's Manual, Volume 3B: System Programming
+ * Guide, Part 2, August 2007".
+ */
#define __PMC_EV_P5() \
-__PMC_EV(P5, DATA_READ, p5-data-read) \
-__PMC_EV(P5, DATA_WRITE, p5-data-write) \
-__PMC_EV(P5, DATA_TLB_MISS, p5-data-tlb-miss) \
-__PMC_EV(P5, DATA_READ_MISS, p5-data-read-miss) \
-__PMC_EV(P5, DATA_WRITE_MISS, p5-data-write-miss) \
-__PMC_EV(P5, WRITE_HIT_TO_M_OR_E_STATE_LINES, \
- p5-write-hit-to-m-or-e-state-lines) \
-__PMC_EV(P5, DATA_CACHE_LINES_WRITTEN_BACK, \
- p4-data-cache-lines-written-back) \
-__PMC_EV(P5, EXTERNAL_SNOOPS, p5-external-snoops) \
-__PMC_EV(P5, EXTERNAL_DATA_CACHE_SNOOP_HITS, \
- p5-external-data-cache-snoop-hits) \
-__PMC_EV(P5, MEMORY_ACCESSES_IN_BOTH_PIPES, \
- p5-memory-accesses-in-both-pipes) \
-__PMC_EV(P5, BANK_CONFLICTS, p5-bank-conflicts) \
-__PMC_EV(P5, MISALIGNED_DATA_OR_IO_REFERENCES, \
- p5-misaligned-data-or-io-references) \
-__PMC_EV(P5, CODE_READ, p5-code-read) \
-__PMC_EV(P5, CODE_TLB_MISS, p5-code-tlb-miss) \
-__PMC_EV(P5, CODE_CACHE_MISS, p5-code-cache-miss) \
-__PMC_EV(P5, ANY_SEGMENT_REGISTER_LOADED, \
- p5-any-segment-register-loaded) \
-__PMC_EV(P5, BRANCHES, p5-branches) \
-__PMC_EV(P5, BTB_HITS, p5-btb-hits) \
-__PMC_EV(P5, TAKEN_BRANCH_OR_BTB_HIT, \
- p5-taken-branch-or-btb-hit) \
-__PMC_EV(P5, PIPELINE_FLUSHES, p5-pipeline-flushes) \
-__PMC_EV(P5, INSTRUCTIONS_EXECUTED, p5-instructions-executed) \
-__PMC_EV(P5, INSTRUCTIONS_EXECUTED_V_PIPE, \
- p5-instructions-executed-v-pipe) \
-__PMC_EV(P5, BUS_CYCLE_DURATION, p5-bus-cycle-duration) \
-__PMC_EV(P5, WRITE_BUFFER_FULL_STALL_DURATION, \
- p5-write-buffer-full-stall-duration) \
-__PMC_EV(P5, WAITING_FOR_DATA_MEMORY_READ_STALL_DURATION, \
- p5-waiting-for-data-memory-read-stall-duration) \
-__PMC_EV(P5, STALL_ON_WRITE_TO_AN_E_OR_M_STATE_LINE, \
- p5-stall-on-write-to-an-e-or-m-state-line) \
-__PMC_EV(P5, LOCKED_BUS_CYCLE, p5-locked-bus-cycle) \
-__PMC_EV(P5, IO_READ_OR_WRITE_CYCLE, p5-io-read-or-write-cycle) \
-__PMC_EV(P5, NONCACHEABLE_MEMORY_READS, \
- p5-noncacheable-memory-reads) \
-__PMC_EV(P5, PIPELINE_AGI_STALLS, p5-pipeline-agi-stalls) \
-__PMC_EV(P5, FLOPS, p5-flops) \
-__PMC_EV(P5, BREAKPOINT_MATCH_ON_DR0_REGISTER, \
- p5-breakpoint-match-on-dr0-register) \
-__PMC_EV(P5, BREAKPOINT_MATCH_ON_DR1_REGISTER, \
- p5-breakpoint-match-on-dr1-register) \
-__PMC_EV(P5, BREAKPOINT_MATCH_ON_DR2_REGISTER, \
- p5-breakpoint-match-on-dr2-register) \
-__PMC_EV(P5, BREAKPOINT_MATCH_ON_DR3_REGISTER, \
- p5-breakpoint-match-on-dr3-register) \
-__PMC_EV(P5, HARDWARE_INTERRUPTS, p5-hardware-interrupts) \
-__PMC_EV(P5, DATA_READ_OR_WRITE, p5-data-read-or-write) \
-__PMC_EV(P5, DATA_READ_MISS_OR_WRITE_MISS, \
- p5-data-read-miss-or-write-miss) \
-__PMC_EV(P5, BUS_OWNERSHIP_LATENCY, p5-bus-ownership-latency) \
-__PMC_EV(P5, BUS_OWNERSHIP_TRANSFERS, p5-bus-ownership-transfers) \
-__PMC_EV(P5, MMX_INSTRUCTIONS_EXECUTED_U_PIPE, \
- p5-mmx-instructions-executed-u-pipe) \
-__PMC_EV(P5, MMX_INSTRUCTIONS_EXECUTED_V_PIPE, \
- p5-mmx-instructions-executed-v-pipe) \
-__PMC_EV(P5, CACHE_M_LINE_SHARING, p5-cache-m-line-sharing) \
-__PMC_EV(P5, CACHE_LINE_SHARING, p5-cache-line-sharing) \
-__PMC_EV(P5, EMMS_INSTRUCTIONS_EXECUTED, \
- p5-emms-instructions-executed) \
-__PMC_EV(P5, TRANSITIONS_BETWEEN_MMX_AND_FP_INSTRUCTIONS, \
- p5-transitions-between-mmx-and-fp-instructions) \
-__PMC_EV(P5, BUS_UTILIZATION_DUE_TO_PROCESSOR_ACTIVITY, \
- p5-bus-utilization-due-to-processor-activity) \
-__PMC_EV(P5, WRITES_TO_NONCACHEABLE_MEMORY, \
- p5-writes-to-noncacheable-memory) \
-__PMC_EV(P5, SATURATING_MMX_INSTRUCTIONS_EXECUTED, \
- p5-saturating-mmx-instructions-executed) \
-__PMC_EV(P5, SATURATIONS_PERFORMED, p5-saturations-performed) \
-__PMC_EV(P5, NUMBER_OF_CYCLES_NOT_IN_HALT_STATE, \
- p5-number-of-cycles-not-in-halt-state) \
-__PMC_EV(P5, DATA_CACHE_TLB_MISS_STALL_DURATION, \
- p5-data-cache-tlb-miss-stall-duration) \
-__PMC_EV(P5, MMX_INSTRUCTION_DATA_READS, \
- p5-mmx-instruction-data-reads) \
-__PMC_EV(P5, MMX_INSTRUCTION_DATA_READ_MISSES, \
- p5-mmx-instruction-data-read-misses) \
-__PMC_EV(P5, FLOATING_POINT_STALLS_DURATION, \
- p5-floating-point-stalls-duration) \
-__PMC_EV(P5, TAKEN_BRANCHES, p5-taken-branches) \
-__PMC_EV(P5, D1_STARVATION_AND_FIFO_IS_EMPTY, \
- p5-d1-starvation-and-fifo-is-empty) \
-__PMC_EV(P5, D1_STARVATION_AND_ONLY_ONE_INSTRUCTION_IN_FIFO, \
- p5-d1-starvation-and-only-instruction-in-fifo) \
-__PMC_EV(P5, MMX_INSTRUCTION_DATA_WRITES, \
- p5-mmx-instruction-data-writes) \
-__PMC_EV(P5, MMX_INSTRUCTION_DATA_WRITE_MISSES, \
- p5-mmx-instruction-data-write-misses) \
-__PMC_EV(P5, PIPELINE_FLUSHES_DUE_TO_WRONG_BRANCH_PREDICTIONS, \
- p5-pipeline-flushes-due-to-wrong-branch-predictions) \
+__PMC_EV(P5, DATA_READ) \
+__PMC_EV(P5, DATA_WRITE) \
+__PMC_EV(P5, DATA_TLB_MISS) \
+__PMC_EV(P5, DATA_READ_MISS) \
+__PMC_EV(P5, DATA_WRITE_MISS) \
+__PMC_EV(P5, WRITE_HIT_TO_M_OR_E_STATE_LINES) \
+__PMC_EV(P5, DATA_CACHE_LINES_WRITTEN_BACK) \
+__PMC_EV(P5, EXTERNAL_SNOOPS) \
+__PMC_EV(P5, EXTERNAL_DATA_CACHE_SNOOP_HITS) \
+__PMC_EV(P5, MEMORY_ACCESSES_IN_BOTH_PIPES) \
+__PMC_EV(P5, BANK_CONFLICTS) \
+__PMC_EV(P5, MISALIGNED_DATA_OR_IO_REFERENCES) \
+__PMC_EV(P5, CODE_READ) \
+__PMC_EV(P5, CODE_TLB_MISS) \
+__PMC_EV(P5, CODE_CACHE_MISS) \
+__PMC_EV(P5, ANY_SEGMENT_REGISTER_LOADED) \
+__PMC_EV(P5, BRANCHES) \
+__PMC_EV(P5, BTB_HITS) \
+__PMC_EV(P5, TAKEN_BRANCH_OR_BTB_HIT) \
+__PMC_EV(P5, PIPELINE_FLUSHES) \
+__PMC_EV(P5, INSTRUCTIONS_EXECUTED) \
+__PMC_EV(P5, INSTRUCTIONS_EXECUTED_V_PIPE) \
+__PMC_EV(P5, BUS_CYCLE_DURATION) \
+__PMC_EV(P5, WRITE_BUFFER_FULL_STALL_DURATION) \
+__PMC_EV(P5, WAITING_FOR_DATA_MEMORY_READ_STALL_DURATION) \
+__PMC_EV(P5, STALL_ON_WRITE_TO_AN_E_OR_M_STATE_LINE) \
+__PMC_EV(P5, LOCKED_BUS_CYCLE) \
+__PMC_EV(P5, IO_READ_OR_WRITE_CYCLE) \
+__PMC_EV(P5, NONCACHEABLE_MEMORY_READS) \
+__PMC_EV(P5, PIPELINE_AGI_STALLS) \
+__PMC_EV(P5, FLOPS) \
+__PMC_EV(P5, BREAKPOINT_MATCH_ON_DR0_REGISTER) \
+__PMC_EV(P5, BREAKPOINT_MATCH_ON_DR1_REGISTER) \
+__PMC_EV(P5, BREAKPOINT_MATCH_ON_DR2_REGISTER) \
+__PMC_EV(P5, BREAKPOINT_MATCH_ON_DR3_REGISTER) \
+__PMC_EV(P5, HARDWARE_INTERRUPTS) \
+__PMC_EV(P5, DATA_READ_OR_WRITE) \
+__PMC_EV(P5, DATA_READ_MISS_OR_WRITE_MISS) \
+__PMC_EV(P5, BUS_OWNERSHIP_LATENCY) \
+__PMC_EV(P5, BUS_OWNERSHIP_TRANSFERS) \
+__PMC_EV(P5, MMX_INSTRUCTIONS_EXECUTED_U_PIPE) \
+__PMC_EV(P5, MMX_INSTRUCTIONS_EXECUTED_V_PIPE) \
+__PMC_EV(P5, CACHE_M_LINE_SHARING) \
+__PMC_EV(P5, CACHE_LINE_SHARING) \
+__PMC_EV(P5, EMMS_INSTRUCTIONS_EXECUTED) \
+__PMC_EV(P5, TRANSITIONS_BETWEEN_MMX_AND_FP_INSTRUCTIONS) \
+__PMC_EV(P5, BUS_UTILIZATION_DUE_TO_PROCESSOR_ACTIVITY) \
+__PMC_EV(P5, WRITES_TO_NONCACHEABLE_MEMORY) \
+__PMC_EV(P5, SATURATING_MMX_INSTRUCTIONS_EXECUTED) \
+__PMC_EV(P5, SATURATIONS_PERFORMED) \
+__PMC_EV(P5, NUMBER_OF_CYCLES_NOT_IN_HALT_STATE) \
+__PMC_EV(P5, DATA_CACHE_TLB_MISS_STALL_DURATION) \
+__PMC_EV(P5, MMX_INSTRUCTION_DATA_READS) \
+__PMC_EV(P5, MMX_INSTRUCTION_DATA_READ_MISSES) \
+__PMC_EV(P5, FLOATING_POINT_STALLS_DURATION) \
+__PMC_EV(P5, TAKEN_BRANCHES) \
+__PMC_EV(P5, D1_STARVATION_AND_FIFO_IS_EMPTY) \
+__PMC_EV(P5, D1_STARVATION_AND_ONLY_ONE_INSTRUCTION_IN_FIFO) \
+__PMC_EV(P5, MMX_INSTRUCTION_DATA_WRITES) \
+__PMC_EV(P5, MMX_INSTRUCTION_DATA_WRITE_MISSES) \
+__PMC_EV(P5, PIPELINE_FLUSHES_DUE_TO_WRONG_BRANCH_PREDICTIONS) \
__PMC_EV(P5, \
- PIPELINE_FLUSHES_DUE_TO_WRONG_BRANCH_PREDICTIONS_RESOLVED_IN_WB_STAGE, \
- p5-pipeline-flushes-due-to-wrong-branch-predictions-resolved-in-wb-stage) \
-__PMC_EV(P5, MISALIGNED_DATA_MEMORY_REFERENCE_ON_MMX_INSTRUCTIONS, \
- p5-misaligned-data-memory-reference-on-mmx-instructions) \
-__PMC_EV(P5, PIPELINE_STALL_FOR_MMX_INSTRUCTION_DATA_MEMORY_READS, \
- p5-pipeline-stall-for-mmx-instruction-data-memory-reads) \
-__PMC_EV(P5, MISPREDICTED_OR_UNPREDICTED_RETURNS, \
- p5-mispredicted-or-unpredicted-returns) \
-__PMC_EV(P5, PREDICTED_RETURNS, p5-predicted-returns) \
-__PMC_EV(P5, MMX_MULTIPLY_UNIT_INTERLOCK, \
- p5-mmx-multiply-unit-interlock) \
-__PMC_EV(P5, MOVD_MOVQ_STORE_STALL_DUE_TO_PREVIOUS_MMX_OPERATION, \
- p5-movd-movq-store-stall-due-to-previous-mmx-operation) \
-__PMC_EV(P5, RETURNS, p5-returns) \
-__PMC_EV(P5, BTB_FALSE_ENTRIES, p5-btb-false-entries) \
-__PMC_EV(P5, BTB_MISS_PREDICTION_ON_NOT_TAKEN_BRANCH, \
- p5-btb-miss-prediction-on-not-taken-branch) \
+ PIPELINE_FLUSHES_DUE_TO_WRONG_BRANCH_PREDICTIONS_RESOLVED_IN_WB_STAGE) \
+__PMC_EV(P5, MISALIGNED_DATA_MEMORY_REFERENCE_ON_MMX_INSTRUCTIONS) \
+__PMC_EV(P5, PIPELINE_STALL_FOR_MMX_INSTRUCTION_DATA_MEMORY_READS) \
+__PMC_EV(P5, MISPREDICTED_OR_UNPREDICTED_RETURNS) \
+__PMC_EV(P5, PREDICTED_RETURNS) \
+__PMC_EV(P5, MMX_MULTIPLY_UNIT_INTERLOCK) \
+__PMC_EV(P5, MOVD_MOVQ_STORE_STALL_DUE_TO_PREVIOUS_MMX_OPERATION) \
+__PMC_EV(P5, RETURNS) \
+__PMC_EV(P5, BTB_FALSE_ENTRIES) \
+__PMC_EV(P5, BTB_MISS_PREDICTION_ON_NOT_TAKEN_BRANCH) \
__PMC_EV(P5, \
- FULL_WRITE_BUFFER_STALL_DURATION_WHILE_EXECUTING_MMX_INSTRUCTIONS, \
- p5-full-write-buffer-stall-duration-while-executing-mmx-instructions) \
-__PMC_EV(P5, STALL_ON_MMX_INSTRUCTION_WRITE_TO_E_OR_M_STATE_LINE, \
- p5-stall-on-mmx-instruction-write-to-e-o-m-state-line)
+ FULL_WRITE_BUFFER_STALL_DURATION_WHILE_EXECUTING_MMX_INSTRUCTIONS) \
+__PMC_EV(P5, STALL_ON_MMX_INSTRUCTION_WRITE_TO_E_OR_M_STATE_LINE)
#define PMC_EV_P5_FIRST PMC_EV_P5_DATA_READ
#define PMC_EV_P5_LAST \
PMC_EV_P5_STALL_ON_MMX_INSTRUCTION_WRITE_TO_E_OR_M_STATE_LINE
+/*
+ * Events supported by Intel architectural fixed function counters,
+ * from the "Intel 64 and IA-32 Architectures Software Developer's
+ * Manual Volume 3B: System Programming Guide, Part 2", July 2008.
+ */
+#define __PMC_EV_IAF() \
+__PMC_EV(IAF, INSTR_RETIRED_ANY) \
+__PMC_EV(IAF, CPU_CLK_UNHALTED_CORE) \
+__PMC_EV(IAF, CPU_CLK_UNHALTED_REF)
+
+#define PMC_EV_IAF_FIRST PMC_EV_IAF_INSTR_RETIRED_ANY
+#define PMC_EV_IAF_LAST PMC_EV_IAF_CPU_CLK_UNHALTED_REF
+
+#define __PMC_EV_ALIAS_IAF() \
+__PMC_EV_ALIAS("instruction-retired", IAF_INSTR_RETIRED_ANY) \
+__PMC_EV_ALIAS("unhalted-core-cycles", IAF_CPU_CLK_UNHALTED_CORE) \
+__PMC_EV_ALIAS("unhalted-reference-cycles", IAF_CPU_CLK_UNHALTED_REF)
+
+/*
+ * Events supported by programmable function counters present in
+ * Intel Atom, Core and Core2 CPUs, from the "Intel 64 and IA-32
+ * Architectures Software Developer's Manual Volume 3B: System Programming
+ * Guide, Part 2", July 2008.
+ *
+ * These PMCs select events with a combination of an event code and
+ * unit mask. Quirks that need to be taken care of include:
+ * - The set of (event code, umask) combinations supported by a processor
+ * varies according to the processor model.
+ * - A given (event code, umask) combination need not measure the same
+ * hardware event in all processor models.
+ * - Event names in vendor documentation for an (event code, umask) pair
+ * may vary according to the CPU model.
+ * - Identically named events can map to different (event code, umask)
+ * pairs on different CPUs.
+ * - New (event code, umask) combinations continue to be added as CPUs
+ * evolve. The interface between hwpmc(4) and libpmc(3) needs to be
+ * robust with respect to ABI changes.
+ *
+ * The IAP_EVENT_* symbols below define the ABI between userland and kernel.
+ * New (event code, * umask) combinations used in new CPUs would be added
+ * to the end of the list. Vendor names for events are mapped to IAP_EVENT_*
+ * symbols using aliases. The final disambiguation of semantics based on
+ * the CPU model happens inside hwpmc(4).
+ */
+#define __PMC_EV_IAP() \
+__PMC_EV(IAP, EVENT_02H_81H) \
+__PMC_EV(IAP, EVENT_03H_00H) \
+__PMC_EV(IAP, EVENT_03H_02H) \
+__PMC_EV(IAP, EVENT_03H_04H) \
+__PMC_EV(IAP, EVENT_03H_08H) \
+__PMC_EV(IAP, EVENT_03H_10H) \
+__PMC_EV(IAP, EVENT_03H_20H) \
+__PMC_EV(IAP, EVENT_04H_00H) \
+__PMC_EV(IAP, EVENT_04H_01H) \
+__PMC_EV(IAP, EVENT_04H_02H) \
+__PMC_EV(IAP, EVENT_04H_08H) \
+__PMC_EV(IAP, EVENT_05H_00H) \
+__PMC_EV(IAP, EVENT_06H_00H) \
+__PMC_EV(IAP, EVENT_07H_00H) \
+__PMC_EV(IAP, EVENT_07H_01H) \
+__PMC_EV(IAP, EVENT_07H_02H) \
+__PMC_EV(IAP, EVENT_07H_03H) \
+__PMC_EV(IAP, EVENT_07H_06H) \
+__PMC_EV(IAP, EVENT_07H_08H) \
+__PMC_EV(IAP, EVENT_08H_01H) \
+__PMC_EV(IAP, EVENT_08H_02H) \
+__PMC_EV(IAP, EVENT_08H_04H) \
+__PMC_EV(IAP, EVENT_08H_05H) \
+__PMC_EV(IAP, EVENT_08H_06H) \
+__PMC_EV(IAP, EVENT_08H_07H) \
+__PMC_EV(IAP, EVENT_08H_08H) \
+__PMC_EV(IAP, EVENT_08H_09H) \
+__PMC_EV(IAP, EVENT_09H_01H) \
+__PMC_EV(IAP, EVENT_09H_02H) \
+__PMC_EV(IAP, EVENT_0CH_01H) \
+__PMC_EV(IAP, EVENT_0CH_02H) \
+__PMC_EV(IAP, EVENT_0CH_03H) \
+__PMC_EV(IAP, EVENT_10H_00H) \
+__PMC_EV(IAP, EVENT_10H_01H) \
+__PMC_EV(IAP, EVENT_10H_81H) \
+__PMC_EV(IAP, EVENT_11H_00H) \
+__PMC_EV(IAP, EVENT_11H_01H) \
+__PMC_EV(IAP, EVENT_11H_81H) \
+__PMC_EV(IAP, EVENT_12H_00H) \
+__PMC_EV(IAP, EVENT_12H_01H) \
+__PMC_EV(IAP, EVENT_12H_81H) \
+__PMC_EV(IAP, EVENT_13H_00H) \
+__PMC_EV(IAP, EVENT_13H_01H) \
+__PMC_EV(IAP, EVENT_13H_81H) \
+__PMC_EV(IAP, EVENT_14H_00H) \
+__PMC_EV(IAP, EVENT_14H_01H) \
+__PMC_EV(IAP, EVENT_18H_00H) \
+__PMC_EV(IAP, EVENT_19H_00H) \
+__PMC_EV(IAP, EVENT_19H_01H) \
+__PMC_EV(IAP, EVENT_19H_02H) \
+__PMC_EV(IAP, EVENT_21H) \
+__PMC_EV(IAP, EVENT_22H) \
+__PMC_EV(IAP, EVENT_23H) \
+__PMC_EV(IAP, EVENT_24H) \
+__PMC_EV(IAP, EVENT_25H) \
+__PMC_EV(IAP, EVENT_26H) \
+__PMC_EV(IAP, EVENT_27H) \
+__PMC_EV(IAP, EVENT_28H) \
+__PMC_EV(IAP, EVENT_29H) \
+__PMC_EV(IAP, EVENT_2AH) \
+__PMC_EV(IAP, EVENT_2BH) \
+__PMC_EV(IAP, EVENT_2EH) \
+__PMC_EV(IAP, EVENT_2EH_41H) \
+__PMC_EV(IAP, EVENT_2EH_4FH) \
+__PMC_EV(IAP, EVENT_30H) \
+__PMC_EV(IAP, EVENT_32H) \
+__PMC_EV(IAP, EVENT_3AH) \
+__PMC_EV(IAP, EVENT_3AH_00H) \
+__PMC_EV(IAP, EVENT_3BH_C0H) \
+__PMC_EV(IAP, EVENT_3CH_00H) \
+__PMC_EV(IAP, EVENT_3CH_01H) \
+__PMC_EV(IAP, EVENT_3CH_02H) \
+__PMC_EV(IAP, EVENT_40H) \
+__PMC_EV(IAP, EVENT_40H_21H) \
+__PMC_EV(IAP, EVENT_41H) \
+__PMC_EV(IAP, EVENT_41H_22H) \
+__PMC_EV(IAP, EVENT_42H) \
+__PMC_EV(IAP, EVENT_42H_10H) \
+__PMC_EV(IAP, EVENT_43H_01H) \
+__PMC_EV(IAP, EVENT_43H_02H) \
+__PMC_EV(IAP, EVENT_44H_02H) \
+__PMC_EV(IAP, EVENT_45H_0FH) \
+__PMC_EV(IAP, EVENT_46H_00H) \
+__PMC_EV(IAP, EVENT_47H_00H) \
+__PMC_EV(IAP, EVENT_48H_00H) \
+__PMC_EV(IAP, EVENT_49H_00H) \
+__PMC_EV(IAP, EVENT_49H_01H) \
+__PMC_EV(IAP, EVENT_49H_02H) \
+__PMC_EV(IAP, EVENT_4BH_00H) \
+__PMC_EV(IAP, EVENT_4BH_01H) \
+__PMC_EV(IAP, EVENT_4BH_02H) \
+__PMC_EV(IAP, EVENT_4BH_03H) \
+__PMC_EV(IAP, EVENT_4CH_00H) \
+__PMC_EV(IAP, EVENT_4EH_10H) \
+__PMC_EV(IAP, EVENT_4FH_00H) \
+__PMC_EV(IAP, EVENT_60H) \
+__PMC_EV(IAP, EVENT_61H) \
+__PMC_EV(IAP, EVENT_61H_00H) \
+__PMC_EV(IAP, EVENT_62H) \
+__PMC_EV(IAP, EVENT_62H_00H) \
+__PMC_EV(IAP, EVENT_63H) \
+__PMC_EV(IAP, EVENT_64H) \
+__PMC_EV(IAP, EVENT_64H_40H) \
+__PMC_EV(IAP, EVENT_65H) \
+__PMC_EV(IAP, EVENT_66H) \
+__PMC_EV(IAP, EVENT_67H) \
+__PMC_EV(IAP, EVENT_68H) \
+__PMC_EV(IAP, EVENT_69H) \
+__PMC_EV(IAP, EVENT_6AH) \
+__PMC_EV(IAP, EVENT_6BH) \
+__PMC_EV(IAP, EVENT_6CH) \
+__PMC_EV(IAP, EVENT_6DH) \
+__PMC_EV(IAP, EVENT_6EH) \
+__PMC_EV(IAP, EVENT_6FH) \
+__PMC_EV(IAP, EVENT_70H) \
+__PMC_EV(IAP, EVENT_77H) \
+__PMC_EV(IAP, EVENT_78H) \
+__PMC_EV(IAP, EVENT_7AH) \
+__PMC_EV(IAP, EVENT_7BH) \
+__PMC_EV(IAP, EVENT_7DH) \
+__PMC_EV(IAP, EVENT_7EH) \
+__PMC_EV(IAP, EVENT_7EH_00H) \
+__PMC_EV(IAP, EVENT_7FH) \
+__PMC_EV(IAP, EVENT_80H_00H) \
+__PMC_EV(IAP, EVENT_80H_02H) \
+__PMC_EV(IAP, EVENT_80H_03H) \
+__PMC_EV(IAP, EVENT_81H_00H) \
+__PMC_EV(IAP, EVENT_82H_02H) \
+__PMC_EV(IAP, EVENT_82H_04H) \
+__PMC_EV(IAP, EVENT_82H_10H) \
+__PMC_EV(IAP, EVENT_82H_12H) \
+__PMC_EV(IAP, EVENT_82H_40H) \
+__PMC_EV(IAP, EVENT_83H_02H) \
+__PMC_EV(IAP, EVENT_85H_00H) \
+__PMC_EV(IAP, EVENT_86H_00H) \
+__PMC_EV(IAP, EVENT_87H_00H) \
+__PMC_EV(IAP, EVENT_88H_00H) \
+__PMC_EV(IAP, EVENT_89H_00H) \
+__PMC_EV(IAP, EVENT_8AH_00H) \
+__PMC_EV(IAP, EVENT_8BH_00H) \
+__PMC_EV(IAP, EVENT_8CH_00H) \
+__PMC_EV(IAP, EVENT_8DH_00H) \
+__PMC_EV(IAP, EVENT_8EH_00H) \
+__PMC_EV(IAP, EVENT_8FH_00H) \
+__PMC_EV(IAP, EVENT_90H_00H) \
+__PMC_EV(IAP, EVENT_91H_00H) \
+__PMC_EV(IAP, EVENT_92H_00H) \
+__PMC_EV(IAP, EVENT_93H_00H) \
+__PMC_EV(IAP, EVENT_94H_00H) \
+__PMC_EV(IAP, EVENT_97H_00H) \
+__PMC_EV(IAP, EVENT_98H_00H) \
+__PMC_EV(IAP, EVENT_A0H_00H) \
+__PMC_EV(IAP, EVENT_A1H_01H) \
+__PMC_EV(IAP, EVENT_A1H_02H) \
+__PMC_EV(IAP, EVENT_A1H_04H) \
+__PMC_EV(IAP, EVENT_A1H_08H) \
+__PMC_EV(IAP, EVENT_A1H_10H) \
+__PMC_EV(IAP, EVENT_A1H_20H) \
+__PMC_EV(IAP, EVENT_A2H_00H) \
+__PMC_EV(IAP, EVENT_AAH_01H) \
+__PMC_EV(IAP, EVENT_AAH_02H) \
+__PMC_EV(IAP, EVENT_AAH_03H) \
+__PMC_EV(IAP, EVENT_AAH_08H) \
+__PMC_EV(IAP, EVENT_ABH_01H) \
+__PMC_EV(IAP, EVENT_ABH_02H) \
+__PMC_EV(IAP, EVENT_B0H_00H) \
+__PMC_EV(IAP, EVENT_B0H_80H) \
+__PMC_EV(IAP, EVENT_B1H_00H) \
+__PMC_EV(IAP, EVENT_B1H_80H) \
+__PMC_EV(IAP, EVENT_B3H_01H) \
+__PMC_EV(IAP, EVENT_B3H_02H) \
+__PMC_EV(IAP, EVENT_B3H_04H) \
+__PMC_EV(IAP, EVENT_B3H_08H) \
+__PMC_EV(IAP, EVENT_B3H_10H) \
+__PMC_EV(IAP, EVENT_B3H_20H) \
+__PMC_EV(IAP, EVENT_B3H_81H) \
+__PMC_EV(IAP, EVENT_B3H_82H) \
+__PMC_EV(IAP, EVENT_B3H_84H) \
+__PMC_EV(IAP, EVENT_B3H_88H) \
+__PMC_EV(IAP, EVENT_B3H_90H) \
+__PMC_EV(IAP, EVENT_B3H_A0H) \
+__PMC_EV(IAP, EVENT_C0H_00H) \
+__PMC_EV(IAP, EVENT_C0H_01H) \
+__PMC_EV(IAP, EVENT_C0H_02H) \
+__PMC_EV(IAP, EVENT_C0H_04H) \
+__PMC_EV(IAP, EVENT_C0H_08H) \
+__PMC_EV(IAP, EVENT_C1H_00H) \
+__PMC_EV(IAP, EVENT_C1H_01H) \
+__PMC_EV(IAP, EVENT_C1H_FEH) \
+__PMC_EV(IAP, EVENT_C2H_00H) \
+__PMC_EV(IAP, EVENT_C2H_01H) \
+__PMC_EV(IAP, EVENT_C2H_02H) \
+__PMC_EV(IAP, EVENT_C2H_04H) \
+__PMC_EV(IAP, EVENT_C2H_07H) \
+__PMC_EV(IAP, EVENT_C2H_0FH) \
+__PMC_EV(IAP, EVENT_C2H_10H) \
+__PMC_EV(IAP, EVENT_C2H_08H) \
+__PMC_EV(IAP, EVENT_C3H_00H) \
+__PMC_EV(IAP, EVENT_C3H_01H) \
+__PMC_EV(IAP, EVENT_C3H_04H) \
+__PMC_EV(IAP, EVENT_C4H_00H) \
+__PMC_EV(IAP, EVENT_C4H_01H) \
+__PMC_EV(IAP, EVENT_C4H_02H) \
+__PMC_EV(IAP, EVENT_C4H_04H) \
+__PMC_EV(IAP, EVENT_C4H_08H) \
+__PMC_EV(IAP, EVENT_C4H_0CH) \
+__PMC_EV(IAP, EVENT_C4H_0FH) \
+__PMC_EV(IAP, EVENT_C5H_00H) \
+__PMC_EV(IAP, EVENT_C6H_00H) \
+__PMC_EV(IAP, EVENT_C6H_01H) \
+__PMC_EV(IAP, EVENT_C6H_02H) \
+__PMC_EV(IAP, EVENT_C7H_00H) \
+__PMC_EV(IAP, EVENT_C7H_01H) \
+__PMC_EV(IAP, EVENT_C7H_02H) \
+__PMC_EV(IAP, EVENT_C7H_04H) \
+__PMC_EV(IAP, EVENT_C7H_08H) \
+__PMC_EV(IAP, EVENT_C7H_10H) \
+__PMC_EV(IAP, EVENT_C7H_1FH) \
+__PMC_EV(IAP, EVENT_C8H_00H) \
+__PMC_EV(IAP, EVENT_C9H_00H) \
+__PMC_EV(IAP, EVENT_CAH_00H) \
+__PMC_EV(IAP, EVENT_CAH_01H) \
+__PMC_EV(IAP, EVENT_CAH_02H) \
+__PMC_EV(IAP, EVENT_CAH_04H) \
+__PMC_EV(IAP, EVENT_CAH_08H) \
+__PMC_EV(IAP, EVENT_CBH_01H) \
+__PMC_EV(IAP, EVENT_CBH_02H) \
+__PMC_EV(IAP, EVENT_CBH_04H) \
+__PMC_EV(IAP, EVENT_CBH_08H) \
+__PMC_EV(IAP, EVENT_CBH_10H) \
+__PMC_EV(IAP, EVENT_CCH_00H) \
+__PMC_EV(IAP, EVENT_CCH_01H) \
+__PMC_EV(IAP, EVENT_CCH_02H) \
+__PMC_EV(IAP, EVENT_CDH_00H) \
+__PMC_EV(IAP, EVENT_CEH_00H) \
+__PMC_EV(IAP, EVENT_CFH_00H) \
+__PMC_EV(IAP, EVENT_D0H_00H) \
+__PMC_EV(IAP, EVENT_D2H_01H) \
+__PMC_EV(IAP, EVENT_D2H_02H) \
+__PMC_EV(IAP, EVENT_D2H_04H) \
+__PMC_EV(IAP, EVENT_D2H_08H) \
+__PMC_EV(IAP, EVENT_D2H_0FH) \
+__PMC_EV(IAP, EVENT_D2H_10H) \
+__PMC_EV(IAP, EVENT_D4H_01H) \
+__PMC_EV(IAP, EVENT_D4H_02H) \
+__PMC_EV(IAP, EVENT_D4H_04H) \
+__PMC_EV(IAP, EVENT_D4H_08H) \
+__PMC_EV(IAP, EVENT_D4H_0FH) \
+__PMC_EV(IAP, EVENT_D5H_01H) \
+__PMC_EV(IAP, EVENT_D5H_02H) \
+__PMC_EV(IAP, EVENT_D5H_04H) \
+__PMC_EV(IAP, EVENT_D5H_08H) \
+__PMC_EV(IAP, EVENT_D5H_0FH) \
+__PMC_EV(IAP, EVENT_D7H_00H) \
+__PMC_EV(IAP, EVENT_D8H_00H) \
+__PMC_EV(IAP, EVENT_D8H_01H) \
+__PMC_EV(IAP, EVENT_D8H_02H) \
+__PMC_EV(IAP, EVENT_D8H_03H) \
+__PMC_EV(IAP, EVENT_D8H_04H) \
+__PMC_EV(IAP, EVENT_D9H_00H) \
+__PMC_EV(IAP, EVENT_D9H_01H) \
+__PMC_EV(IAP, EVENT_D9H_02H) \
+__PMC_EV(IAP, EVENT_D9H_03H) \
+__PMC_EV(IAP, EVENT_DAH_00H) \
+__PMC_EV(IAP, EVENT_DAH_01H) \
+__PMC_EV(IAP, EVENT_DAH_02H) \
+__PMC_EV(IAP, EVENT_DBH_00H) \
+__PMC_EV(IAP, EVENT_DCH_01H) \
+__PMC_EV(IAP, EVENT_DCH_02H) \
+__PMC_EV(IAP, EVENT_DCH_04H) \
+__PMC_EV(IAP, EVENT_DCH_08H) \
+__PMC_EV(IAP, EVENT_DCH_10H) \
+__PMC_EV(IAP, EVENT_DCH_1FH) \
+__PMC_EV(IAP, EVENT_E0H_00H) \
+__PMC_EV(IAP, EVENT_E0H_01H) \
+__PMC_EV(IAP, EVENT_E2H_00H) \
+__PMC_EV(IAP, EVENT_E4H_00H) \
+__PMC_EV(IAP, EVENT_E6H_00H) \
+__PMC_EV(IAP, EVENT_E6H_01H) \
+__PMC_EV(IAP, EVENT_F0H_00H) \
+__PMC_EV(IAP, EVENT_F8H_00H) \
+__PMC_EV(IAP, EVENT_02H_01H) \
+__PMC_EV(IAP, EVENT_03H_01H) \
+__PMC_EV(IAP, EVENT_05H_01H) \
+__PMC_EV(IAP, EVENT_05H_02H) \
+__PMC_EV(IAP, EVENT_05H_03H) \
+__PMC_EV(IAP, EVENT_06H_01H) \
+__PMC_EV(IAP, EVENT_06H_02H) \
+__PMC_EV(IAP, EVENT_06H_04H) \
+__PMC_EV(IAP, EVENT_06H_08H) \
+__PMC_EV(IAP, EVENT_06H_0FH) \
+__PMC_EV(IAP, EVENT_08H_10H) \
+__PMC_EV(IAP, EVENT_08H_20H) \
+__PMC_EV(IAP, EVENT_08H_40H) \
+__PMC_EV(IAP, EVENT_08H_80H) \
+__PMC_EV(IAP, EVENT_09H_04H) \
+__PMC_EV(IAP, EVENT_09H_08H) \
+__PMC_EV(IAP, EVENT_0BH_01H) \
+__PMC_EV(IAP, EVENT_0BH_02H) \
+__PMC_EV(IAP, EVENT_0EH_01H) \
+__PMC_EV(IAP, EVENT_0EH_02H) \
+__PMC_EV(IAP, EVENT_0FH_02H) \
+__PMC_EV(IAP, EVENT_0FH_08H) \
+__PMC_EV(IAP, EVENT_0FH_10H) \
+__PMC_EV(IAP, EVENT_0FH_20H) \
+__PMC_EV(IAP, EVENT_10H_02H) \
+__PMC_EV(IAP, EVENT_10H_04H) \
+__PMC_EV(IAP, EVENT_10H_08H) \
+__PMC_EV(IAP, EVENT_10H_10H) \
+__PMC_EV(IAP, EVENT_10H_20H) \
+__PMC_EV(IAP, EVENT_10H_40H) \
+__PMC_EV(IAP, EVENT_10H_80H) \
+__PMC_EV(IAP, EVENT_12H_02H) \
+__PMC_EV(IAP, EVENT_12H_04H) \
+__PMC_EV(IAP, EVENT_12H_08H) \
+__PMC_EV(IAP, EVENT_12H_10H) \
+__PMC_EV(IAP, EVENT_12H_20H) \
+__PMC_EV(IAP, EVENT_12H_40H) \
+__PMC_EV(IAP, EVENT_13H_02H) \
+__PMC_EV(IAP, EVENT_13H_04H) \
+__PMC_EV(IAP, EVENT_13H_07H) \
+__PMC_EV(IAP, EVENT_14H_02H) \
+__PMC_EV(IAP, EVENT_17H_01H) \
+__PMC_EV(IAP, EVENT_18H_01H) \
+__PMC_EV(IAP, EVENT_1DH_01H) \
+__PMC_EV(IAP, EVENT_1DH_02H) \
+__PMC_EV(IAP, EVENT_1DH_04H) \
+__PMC_EV(IAP, EVENT_1EH_01H) \
+__PMC_EV(IAP, EVENT_24H_01H) \
+__PMC_EV(IAP, EVENT_24H_02H) \
+__PMC_EV(IAP, EVENT_24H_03H) \
+__PMC_EV(IAP, EVENT_24H_04H) \
+__PMC_EV(IAP, EVENT_24H_08H) \
+__PMC_EV(IAP, EVENT_24H_0CH) \
+__PMC_EV(IAP, EVENT_24H_10H) \
+__PMC_EV(IAP, EVENT_24H_20H) \
+__PMC_EV(IAP, EVENT_24H_30H) \
+__PMC_EV(IAP, EVENT_24H_40H) \
+__PMC_EV(IAP, EVENT_24H_80H) \
+__PMC_EV(IAP, EVENT_24H_AAH) \
+__PMC_EV(IAP, EVENT_24H_C0H) \
+__PMC_EV(IAP, EVENT_24H_FFH) \
+__PMC_EV(IAP, EVENT_26H_01H) \
+__PMC_EV(IAP, EVENT_26H_02H) \
+__PMC_EV(IAP, EVENT_26H_04H) \
+__PMC_EV(IAP, EVENT_26H_08H) \
+__PMC_EV(IAP, EVENT_26H_0FH) \
+__PMC_EV(IAP, EVENT_26H_10H) \
+__PMC_EV(IAP, EVENT_26H_20H) \
+__PMC_EV(IAP, EVENT_26H_40H) \
+__PMC_EV(IAP, EVENT_26H_80H) \
+__PMC_EV(IAP, EVENT_26H_F0H) \
+__PMC_EV(IAP, EVENT_26H_FFH) \
+__PMC_EV(IAP, EVENT_27H_01H) \
+__PMC_EV(IAP, EVENT_27H_02H) \
+__PMC_EV(IAP, EVENT_27H_04H) \
+__PMC_EV(IAP, EVENT_27H_08H) \
+__PMC_EV(IAP, EVENT_27H_0EH) \
+__PMC_EV(IAP, EVENT_27H_0FH) \
+__PMC_EV(IAP, EVENT_27H_10H) \
+__PMC_EV(IAP, EVENT_27H_20H) \
+__PMC_EV(IAP, EVENT_27H_40H) \
+__PMC_EV(IAP, EVENT_27H_80H) \
+__PMC_EV(IAP, EVENT_27H_E0H) \
+__PMC_EV(IAP, EVENT_27H_F0H) \
+__PMC_EV(IAP, EVENT_28H_01H) \
+__PMC_EV(IAP, EVENT_28H_02H) \
+__PMC_EV(IAP, EVENT_28H_04H) \
+__PMC_EV(IAP, EVENT_28H_08H) \
+__PMC_EV(IAP, EVENT_28H_0FH) \
+__PMC_EV(IAP, EVENT_3DH_01H) \
+__PMC_EV(IAP, EVENT_40H_01H) \
+__PMC_EV(IAP, EVENT_40H_02H) \
+__PMC_EV(IAP, EVENT_40H_04H) \
+__PMC_EV(IAP, EVENT_40H_08H) \
+__PMC_EV(IAP, EVENT_40H_0FH) \
+__PMC_EV(IAP, EVENT_41H_01H) \
+__PMC_EV(IAP, EVENT_41H_02H) \
+__PMC_EV(IAP, EVENT_41H_04H) \
+__PMC_EV(IAP, EVENT_41H_08H) \
+__PMC_EV(IAP, EVENT_41H_0FH) \
+__PMC_EV(IAP, EVENT_42H_01H) \
+__PMC_EV(IAP, EVENT_42H_02H) \
+__PMC_EV(IAP, EVENT_42H_04H) \
+__PMC_EV(IAP, EVENT_42H_08H) \
+__PMC_EV(IAP, EVENT_48H_02H) \
+__PMC_EV(IAP, EVENT_49H_10H) \
+__PMC_EV(IAP, EVENT_49H_20H) \
+__PMC_EV(IAP, EVENT_49H_40H) \
+__PMC_EV(IAP, EVENT_49H_80H) \
+__PMC_EV(IAP, EVENT_4BH_08H) \
+__PMC_EV(IAP, EVENT_4CH_01H) \
+__PMC_EV(IAP, EVENT_4DH_01H) \
+__PMC_EV(IAP, EVENT_4EH_01H) \
+__PMC_EV(IAP, EVENT_4EH_02H) \
+__PMC_EV(IAP, EVENT_4EH_04H) \
+__PMC_EV(IAP, EVENT_4FH_02H) \
+__PMC_EV(IAP, EVENT_4FH_04H) \
+__PMC_EV(IAP, EVENT_4FH_08H) \
+__PMC_EV(IAP, EVENT_51H_01H) \
+__PMC_EV(IAP, EVENT_51H_02H) \
+__PMC_EV(IAP, EVENT_51H_04H) \
+__PMC_EV(IAP, EVENT_51H_08H) \
+__PMC_EV(IAP, EVENT_52H_01H) \
+__PMC_EV(IAP, EVENT_53H_01H) \
+__PMC_EV(IAP, EVENT_60H_01H) \
+__PMC_EV(IAP, EVENT_60H_02H) \
+__PMC_EV(IAP, EVENT_60H_04H) \
+__PMC_EV(IAP, EVENT_60H_08H) \
+__PMC_EV(IAP, EVENT_63H_01H) \
+__PMC_EV(IAP, EVENT_63H_02H) \
+__PMC_EV(IAP, EVENT_6CH_01H) \
+__PMC_EV(IAP, EVENT_80H_01H) \
+__PMC_EV(IAP, EVENT_80H_04H) \
+__PMC_EV(IAP, EVENT_80H_10H) \
+__PMC_EV(IAP, EVENT_81H_01H) \
+__PMC_EV(IAP, EVENT_81H_02H) \
+__PMC_EV(IAP, EVENT_82H_01H) \
+__PMC_EV(IAP, EVENT_83H_01H) \
+__PMC_EV(IAP, EVENT_85H_01H) \
+__PMC_EV(IAP, EVENT_85H_02H) \
+__PMC_EV(IAP, EVENT_85H_04H) \
+__PMC_EV(IAP, EVENT_85H_10H) \
+__PMC_EV(IAP, EVENT_85H_20H) \
+__PMC_EV(IAP, EVENT_85H_40H) \
+__PMC_EV(IAP, EVENT_85H_80H) \
+__PMC_EV(IAP, EVENT_87H_01H) \
+__PMC_EV(IAP, EVENT_87H_02H) \
+__PMC_EV(IAP, EVENT_87H_04H) \
+__PMC_EV(IAP, EVENT_87H_08H) \
+__PMC_EV(IAP, EVENT_87H_0FH) \
+__PMC_EV(IAP, EVENT_88H_01H) \
+__PMC_EV(IAP, EVENT_88H_02H) \
+__PMC_EV(IAP, EVENT_88H_04H) \
+__PMC_EV(IAP, EVENT_88H_07H) \
+__PMC_EV(IAP, EVENT_88H_08H) \
+__PMC_EV(IAP, EVENT_88H_10H) \
+__PMC_EV(IAP, EVENT_88H_20H) \
+__PMC_EV(IAP, EVENT_88H_30H) \
+__PMC_EV(IAP, EVENT_88H_40H) \
+__PMC_EV(IAP, EVENT_89H_01H) \
+__PMC_EV(IAP, EVENT_89H_02H) \
+__PMC_EV(IAP, EVENT_89H_04H) \
+__PMC_EV(IAP, EVENT_89H_07H) \
+__PMC_EV(IAP, EVENT_89H_08H) \
+__PMC_EV(IAP, EVENT_89H_10H) \
+__PMC_EV(IAP, EVENT_89H_20H) \
+__PMC_EV(IAP, EVENT_89H_30H) \
+__PMC_EV(IAP, EVENT_89H_40H) \
+__PMC_EV(IAP, EVENT_89H_7FH) \
+__PMC_EV(IAP, EVENT_A2H_01H) \
+__PMC_EV(IAP, EVENT_A2H_02H) \
+__PMC_EV(IAP, EVENT_A2H_04H) \
+__PMC_EV(IAP, EVENT_A2H_08H) \
+__PMC_EV(IAP, EVENT_A2H_10H) \
+__PMC_EV(IAP, EVENT_A2H_20H) \
+__PMC_EV(IAP, EVENT_A2H_40H) \
+__PMC_EV(IAP, EVENT_A2H_80H) \
+__PMC_EV(IAP, EVENT_A6H_01H) \
+__PMC_EV(IAP, EVENT_A7H_01H) \
+__PMC_EV(IAP, EVENT_A8H_01H) \
+__PMC_EV(IAP, EVENT_B0H_01H) \
+__PMC_EV(IAP, EVENT_B0H_02H) \
+__PMC_EV(IAP, EVENT_B0H_04H) \
+__PMC_EV(IAP, EVENT_B0H_08H) \
+__PMC_EV(IAP, EVENT_B0H_20H) \
+__PMC_EV(IAP, EVENT_B0H_40H) \
+__PMC_EV(IAP, EVENT_B1H_01H) \
+__PMC_EV(IAP, EVENT_B1H_02H) \
+__PMC_EV(IAP, EVENT_B1H_04H) \
+__PMC_EV(IAP, EVENT_B1H_08H) \
+__PMC_EV(IAP, EVENT_B1H_10H) \
+__PMC_EV(IAP, EVENT_B1H_20H) \
+__PMC_EV(IAP, EVENT_B1H_40H) \
+__PMC_EV(IAP, EVENT_B2H_01H) \
+__PMC_EV(IAP, EVENT_B7H_01H) \
+__PMC_EV(IAP, EVENT_B8H_01H) \
+__PMC_EV(IAP, EVENT_B8H_02H) \
+__PMC_EV(IAP, EVENT_B8H_04H) \
+__PMC_EV(IAP, EVENT_BAH_01H) \
+__PMC_EV(IAP, EVENT_BAH_02H) \
+__PMC_EV(IAP, EVENT_C3H_02H) \
+__PMC_EV(IAP, EVENT_C3H_10H) \
+__PMC_EV(IAP, EVENT_C5H_02H) \
+__PMC_EV(IAP, EVENT_C8H_20H) \
+__PMC_EV(IAP, EVENT_CBH_40H) \
+__PMC_EV(IAP, EVENT_CBH_80H) \
+__PMC_EV(IAP, EVENT_CCH_03H) \
+__PMC_EV(IAP, EVENT_D0H_01H) \
+__PMC_EV(IAP, EVENT_D1H_02H) \
+__PMC_EV(IAP, EVENT_D1H_04H) \
+__PMC_EV(IAP, EVENT_D1H_08H) \
+__PMC_EV(IAP, EVENT_DBH_01H) \
+__PMC_EV(IAP, EVENT_E4H_01H) \
+__PMC_EV(IAP, EVENT_E5H_01H) \
+__PMC_EV(IAP, EVENT_F3H_04H) \
+__PMC_EV(IAP, EVENT_F3H_08H) \
+__PMC_EV(IAP, EVENT_F3H_10H) \
+__PMC_EV(IAP, EVENT_F3H_20H) \
+__PMC_EV(IAP, EVENT_F4H_01H) \
+__PMC_EV(IAP, EVENT_F4H_02H) \
+__PMC_EV(IAP, EVENT_F4H_04H) \
+__PMC_EV(IAP, EVENT_F4H_08H) \
+__PMC_EV(IAP, EVENT_F4H_10H) \
+__PMC_EV(IAP, EVENT_F6H_01H) \
+__PMC_EV(IAP, EVENT_F7H_01H) \
+__PMC_EV(IAP, EVENT_F7H_02H) \
+__PMC_EV(IAP, EVENT_F7H_04H) \
+__PMC_EV(IAP, EVENT_F8H_01H) \
+__PMC_EV(IAP, EVENT_FDH_01H) \
+__PMC_EV(IAP, EVENT_FDH_02H) \
+__PMC_EV(IAP, EVENT_FDH_04H) \
+__PMC_EV(IAP, EVENT_FDH_08H) \
+__PMC_EV(IAP, EVENT_FDH_10H) \
+__PMC_EV(IAP, EVENT_FDH_20H) \
+__PMC_EV(IAP, EVENT_FDH_40H)
+
+#define PMC_EV_IAP_FIRST PMC_EV_IAP_EVENT_02H_81H
+#define PMC_EV_IAP_LAST PMC_EV_IAP_EVENT_FDH_40H
+
+/*
+ * Map "architectural" event names to event ids.
+ */
+#define __PMC_EV_ALIAS_INTEL_ARCHITECTURAL() \
+__PMC_EV_ALIAS("branch-instruction-retired", IAP_EVENT_C4H_00H) \
+__PMC_EV_ALIAS("branch-misses-retired", IAP_EVENT_C5H_00H) \
+__PMC_EV_ALIAS("instruction-retired", IAP_EVENT_C0H_00H) \
+__PMC_EV_ALIAS("llc-misses", IAP_EVENT_2EH_41H) \
+__PMC_EV_ALIAS("llc-reference", IAP_EVENT_2EH_4FH) \
+__PMC_EV_ALIAS("unhalted-reference-cycles", IAP_EVENT_3CH_01H) \
+__PMC_EV_ALIAS("unhalted-core-cycles", IAP_EVENT_3CH_00H)
+
+/*
+ * Aliases for Atom PMCs.
+ */
+#define __PMC_EV_ALIAS_ATOM() \
+__PMC_EV_ALIAS_INTEL_ARCHITECTURAL() \
+__PMC_EV_ALIAS("BACLEARS", IAP_EVENT_E6H_01H) \
+__PMC_EV_ALIAS("BOGUS_BR", IAP_EVENT_E4H_00H) \
+__PMC_EV_ALIAS("BR_BAC_MISSP_EXEC", IAP_EVENT_8AH_00H) \
+__PMC_EV_ALIAS("BR_CALL_EXEC", IAP_EVENT_92H_00H) \
+__PMC_EV_ALIAS("BR_CALL_MISSP_EXEC", IAP_EVENT_93H_00H) \
+__PMC_EV_ALIAS("BR_CND_EXEC", IAP_EVENT_8BH_00H) \
+__PMC_EV_ALIAS("BR_CND_MISSP_EXEC", IAP_EVENT_8CH_00H) \
+__PMC_EV_ALIAS("BR_IND_CALL_EXEC", IAP_EVENT_94H_00H) \
+__PMC_EV_ALIAS("BR_IND_EXEC", IAP_EVENT_8DH_00H) \
+__PMC_EV_ALIAS("BR_IND_MISSP_EXEC", IAP_EVENT_8EH_00H) \
+__PMC_EV_ALIAS("BR_INST_DECODED", IAP_EVENT_E0H_01H) \
+__PMC_EV_ALIAS("BR_INST_EXEC", IAP_EVENT_88H_00H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.ANY", IAP_EVENT_C4H_00H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.ANY1", IAP_EVENT_C4H_0FH) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.MISPRED", IAP_EVENT_C5H_00H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.MISPRED_NOT_TAKEN", \
+ IAP_EVENT_C4H_02H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.MISPRED_TAKEN", IAP_EVENT_C4H_08H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.PRED_NOT_TAKEN",IAP_EVENT_C4H_01H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.PRED_TAKEN", IAP_EVENT_C4H_04H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.TAKEN", IAP_EVENT_C4H_0CH) \
+__PMC_EV_ALIAS("BR_MISSP_EXEC", IAP_EVENT_89H_00H) \
+__PMC_EV_ALIAS("BR_RET_BAC_MISSP_EXEC", IAP_EVENT_91H_00H) \
+__PMC_EV_ALIAS("BR_RET_EXEC", IAP_EVENT_8FH_00H) \
+__PMC_EV_ALIAS("BR_RET_MISSP_EXEC", IAP_EVENT_90H_00H) \
+__PMC_EV_ALIAS("BR_TKN_BUBBLE_1", IAP_EVENT_97H_00H) \
+__PMC_EV_ALIAS("BR_TKN_BUBBLE_2", IAP_EVENT_98H_00H) \
+__PMC_EV_ALIAS("BUSQ_EMPTY", IAP_EVENT_7DH) \
+__PMC_EV_ALIAS("BUS_BNR_DRV", IAP_EVENT_61H) \
+__PMC_EV_ALIAS("BUS_DATA_RCV", IAP_EVENT_64H) \
+__PMC_EV_ALIAS("BUS_DRDY_CLOCKS", IAP_EVENT_62H) \
+__PMC_EV_ALIAS("BUS_HITM_DRV", IAP_EVENT_7BH) \
+__PMC_EV_ALIAS("BUS_HIT_DRV", IAP_EVENT_7AH) \
+__PMC_EV_ALIAS("BUS_IO_WAIT", IAP_EVENT_7FH) \
+__PMC_EV_ALIAS("BUS_LOCK_CLOCKS", IAP_EVENT_63H) \
+__PMC_EV_ALIAS("BUS_REQUEST_OUTSTANDING", IAP_EVENT_60H) \
+__PMC_EV_ALIAS("BUS_TRANS_ANY", IAP_EVENT_70H) \
+__PMC_EV_ALIAS("BUS_TRANS_BRD", IAP_EVENT_65H) \
+__PMC_EV_ALIAS("BUS_TRANS_BURST", IAP_EVENT_6EH) \
+__PMC_EV_ALIAS("BUS_TRANS_DEF", IAP_EVENT_6DH) \
+__PMC_EV_ALIAS("BUS_TRANS_IFETCH", IAP_EVENT_68H) \
+__PMC_EV_ALIAS("BUS_TRANS_INVAL", IAP_EVENT_69H) \
+__PMC_EV_ALIAS("BUS_TRANS_IO", IAP_EVENT_6CH) \
+__PMC_EV_ALIAS("BUS_TRANS_MEM", IAP_EVENT_6FH) \
+__PMC_EV_ALIAS("BUS_TRANS_P", IAP_EVENT_6BH) \
+__PMC_EV_ALIAS("BUS_TRANS_PWR", IAP_EVENT_6AH) \
+__PMC_EV_ALIAS("BUS_TRANS_RFO", IAP_EVENT_66H) \
+__PMC_EV_ALIAS("BUS_TRANS_WB", IAP_EVENT_67H) \
+__PMC_EV_ALIAS("CMP_SNOOP", IAP_EVENT_78H) \
+__PMC_EV_ALIAS("CPU_CLK_UNHALTED.BUS", IAP_EVENT_3CH_01H) \
+__PMC_EV_ALIAS("CPU_CLK_UNHALTED.CORE_P", IAP_EVENT_3CH_00H) \
+__PMC_EV_ALIAS("CPU_CLK_UNHALTED.NO_OTHER", IAP_EVENT_3CH_02H) \
+__PMC_EV_ALIAS("CYCLES_DIV_BUSY", IAP_EVENT_14H_01H) \
+__PMC_EV_ALIAS("CYCLES_INT_MASKED.CYCLES_INT_MASKED", \
+ IAP_EVENT_C6H_01H) \
+__PMC_EV_ALIAS("CYCLES_INT_MASKED.CYCLES_INT_PENDING_AND_MASKED", \
+ IAP_EVENT_C6H_02H) \
+__PMC_EV_ALIAS("CYCLES_L1I_MEM_STALLED", IAP_EVENT_86H_00H) \
+__PMC_EV_ALIAS("DATA_TLB_MISSES.DTLB_MISS", IAP_EVENT_08H_07H) \
+__PMC_EV_ALIAS("DATA_TLB_MISSES.DTLB_MISS_LD", IAP_EVENT_08H_05H) \
+__PMC_EV_ALIAS("DATA_TLB_MISSES.DTLB_MISS_ST", IAP_EVENT_08H_06H) \
+__PMC_EV_ALIAS("DATA_TLB_MISSES.UTLB_MISS_LD", IAP_EVENT_08H_09H) \
+__PMC_EV_ALIAS("DELAYED_BYPASS.FP", IAP_EVENT_19H_00H) \
+__PMC_EV_ALIAS("DELAYED_BYPASS.LOAD", IAP_EVENT_19H_01H) \
+__PMC_EV_ALIAS("DELAYED_BYPASS.SIMD", IAP_EVENT_19H_02H) \
+__PMC_EV_ALIAS("DIV", IAP_EVENT_13H_00H) \
+__PMC_EV_ALIAS("DIV.AR", IAP_EVENT_13H_81H) \
+__PMC_EV_ALIAS("DIV.S", IAP_EVENT_13H_01H) \
+__PMC_EV_ALIAS("DTLB_MISSES.ANY", IAP_EVENT_08H_01H) \
+__PMC_EV_ALIAS("DTLB_MISSES.L0_MISS_LD", IAP_EVENT_08H_04H) \
+__PMC_EV_ALIAS("DTLB_MISSES.MISS_LD", IAP_EVENT_08H_02H) \
+__PMC_EV_ALIAS("DTLB_MISSES.MISS_ST", IAP_EVENT_08H_08H) \
+__PMC_EV_ALIAS("EIST_TRANS", IAP_EVENT_3AH_00H) \
+__PMC_EV_ALIAS("ESP.ADDITIONS", IAP_EVENT_ABH_02H) \
+__PMC_EV_ALIAS("ESP.SYNCH", IAP_EVENT_ABH_01H) \
+__PMC_EV_ALIAS("EXT_SNOOP", IAP_EVENT_77H) \
+__PMC_EV_ALIAS("FP_ASSIST", IAP_EVENT_11H_01H) \
+__PMC_EV_ALIAS("FP_ASSIST.AR", IAP_EVENT_11H_81H) \
+__PMC_EV_ALIAS("FP_COMP_OPS_EXE", IAP_EVENT_10H_00H) \
+__PMC_EV_ALIAS("FP_MMX_TRANS_TO_FP", IAP_EVENT_CCH_02H) \
+__PMC_EV_ALIAS("FP_MMX_TRANS_TO_MMX", IAP_EVENT_CCH_01H) \
+__PMC_EV_ALIAS("HW_INT_RCV", IAP_EVENT_C8H_00H) \
+__PMC_EV_ALIAS("ICACHE.ACCESSES", IAP_EVENT_80H_03H) \
+__PMC_EV_ALIAS("ICACHE.MISSES", IAP_EVENT_80H_02H) \
+__PMC_EV_ALIAS("IDLE_DURING_DIV", IAP_EVENT_18H_00H) \
+__PMC_EV_ALIAS("ILD_STALL", IAP_EVENT_87H_00H) \
+__PMC_EV_ALIAS("INST_QUEUE.FULL", IAP_EVENT_83H_02H) \
+__PMC_EV_ALIAS("INST_RETIRED.ANY_P", IAP_EVENT_C0H_00H) \
+__PMC_EV_ALIAS("INST_RETIRED.LOADS", IAP_EVENT_C0H_01H) \
+__PMC_EV_ALIAS("INST_RETIRED.OTHER", IAP_EVENT_C0H_04H) \
+__PMC_EV_ALIAS("INST_RETIRED.STORES", IAP_EVENT_C0H_02H) \
+__PMC_EV_ALIAS("ITLB.FLUSH", IAP_EVENT_82H_04H) \
+__PMC_EV_ALIAS("ITLB.LARGE_MISS", IAP_EVENT_82H_10H) \
+__PMC_EV_ALIAS("ITLB.MISSES", IAP_EVENT_82H_02H) \
+__PMC_EV_ALIAS("ITLB.SMALL_MISS", IAP_EVENT_82H_02H) \
+__PMC_EV_ALIAS("ITLB_MISS_RETIRED", IAP_EVENT_C9H_00H) \
+__PMC_EV_ALIAS("L1D_ALL_CACHE_REF", IAP_EVENT_43H_02H) \
+__PMC_EV_ALIAS("L1D_ALL_REF", IAP_EVENT_43H_01H) \
+__PMC_EV_ALIAS("L1D_CACHE.LD", IAP_EVENT_40H_21H) \
+__PMC_EV_ALIAS("L1D_CACHE.ST", IAP_EVENT_41H_22H) \
+__PMC_EV_ALIAS("L1D_CACHE_LOCK", IAP_EVENT_42H) \
+__PMC_EV_ALIAS("L1D_CACHE_LOCK_DURATION", IAP_EVENT_42H_10H) \
+__PMC_EV_ALIAS("L1D_M_EVICT", IAP_EVENT_47H_00H) \
+__PMC_EV_ALIAS("L1D_M_REPL", IAP_EVENT_46H_00H) \
+__PMC_EV_ALIAS("L1D_PEND_MISS", IAP_EVENT_48H_00H) \
+__PMC_EV_ALIAS("L1D_PREFETCH.REQUESTS", IAP_EVENT_4EH_10H) \
+__PMC_EV_ALIAS("L1D_REPL", IAP_EVENT_45H_0FH) \
+__PMC_EV_ALIAS("L1D_SPLIT.LOADS", IAP_EVENT_49H_01H) \
+__PMC_EV_ALIAS("L1D_SPLIT.STORES", IAP_EVENT_49H_02H) \
+__PMC_EV_ALIAS("L1I_MISSES", IAP_EVENT_81H_00H) \
+__PMC_EV_ALIAS("L1I_READS", IAP_EVENT_80H_00H) \
+__PMC_EV_ALIAS("L2_ADS", IAP_EVENT_21H) \
+__PMC_EV_ALIAS("L2_DBUS_BUSY_RD", IAP_EVENT_23H) \
+__PMC_EV_ALIAS("L2_IFETCH", IAP_EVENT_28H) \
+__PMC_EV_ALIAS("L2_LD", IAP_EVENT_29H) \
+__PMC_EV_ALIAS("L2_LINES_IN", IAP_EVENT_24H) \
+__PMC_EV_ALIAS("L2_LINES_OUT", IAP_EVENT_26H) \
+__PMC_EV_ALIAS("L2_LOCK", IAP_EVENT_2BH) \
+__PMC_EV_ALIAS("L2_M_LINES_IN", IAP_EVENT_25H) \
+__PMC_EV_ALIAS("L2_M_LINES_OUT", IAP_EVENT_27H) \
+__PMC_EV_ALIAS("L2_NO_REQ", IAP_EVENT_32H) \
+__PMC_EV_ALIAS("L2_REJECT_BUSQ", IAP_EVENT_30H) \
+__PMC_EV_ALIAS("L2_RQSTS", IAP_EVENT_2EH) \
+__PMC_EV_ALIAS("L2_RQSTS.SELF.DEMAND.I_STATE", IAP_EVENT_2EH_41H) \
+__PMC_EV_ALIAS("L2_RQSTS.SELF.DEMAND.MESI", IAP_EVENT_2EH_4FH) \
+__PMC_EV_ALIAS("L2_ST", IAP_EVENT_2AH) \
+__PMC_EV_ALIAS("LOAD_BLOCK.L1D", IAP_EVENT_03H_20H) \
+__PMC_EV_ALIAS("LOAD_BLOCK.OVERLAP_STORE", IAP_EVENT_03H_08H) \
+__PMC_EV_ALIAS("LOAD_BLOCK.STA", IAP_EVENT_03H_02H) \
+__PMC_EV_ALIAS("LOAD_BLOCK.STD", IAP_EVENT_03H_04H) \
+__PMC_EV_ALIAS("LOAD_BLOCK.UNTIL_RETIRE", IAP_EVENT_03H_10H) \
+__PMC_EV_ALIAS("LOAD_HIT_PRE", IAP_EVENT_4CH_00H) \
+__PMC_EV_ALIAS("MACHINE_CLEARS.SMC", IAP_EVENT_C3H_01H) \
+__PMC_EV_ALIAS("MACHINE_NUKES.MEM_ORDER", IAP_EVENT_C3H_04H) \
+__PMC_EV_ALIAS("MACRO_INSTS.ALL_DECODED", IAP_EVENT_AAH_03H) \
+__PMC_EV_ALIAS("MACRO_INSTS.CISC_DECODED", IAP_EVENT_AAH_02H) \
+__PMC_EV_ALIAS("MEMORY_DISAMBIGUATION.RESET", IAP_EVENT_09H_01H) \
+__PMC_EV_ALIAS("MEMORY_DISAMBIGUATION.SUCCESS", IAP_EVENT_09H_02H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.DTLB_MISS", IAP_EVENT_CBH_04H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.L2_HIT", IAP_EVENT_CBH_01H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.L2_LINE_MISS", IAP_EVENT_CBH_08H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.L2_MISS", IAP_EVENT_CBH_02H) \
+__PMC_EV_ALIAS("MUL", IAP_EVENT_12H_00H) \
+__PMC_EV_ALIAS("MUL.AR", IAP_EVENT_12H_81H) \
+__PMC_EV_ALIAS("MUL.S", IAP_EVENT_12H_01H) \
+__PMC_EV_ALIAS("PAGE_WALKS.CYCLES", IAP_EVENT_0CH_03H) \
+__PMC_EV_ALIAS("PAGE_WALKS.WALKS", IAP_EVENT_0CH_03H) \
+__PMC_EV_ALIAS("PREFETCH.PREFETCHNTA", IAP_EVENT_07H_08H) \
+__PMC_EV_ALIAS("PREFETCH.PREFETCHT0", IAP_EVENT_07H_01H) \
+__PMC_EV_ALIAS("PREFETCH.SW_L2", IAP_EVENT_07H_06H) \
+__PMC_EV_ALIAS("PREF_RQSTS_DN", IAP_EVENT_F8H_00H) \
+__PMC_EV_ALIAS("PREF_RQSTS_UP", IAP_EVENT_F0H_00H) \
+__PMC_EV_ALIAS("RAT_STALLS.ANY", IAP_EVENT_D2H_0FH) \
+__PMC_EV_ALIAS("RAT_STALLS.FLAGS", IAP_EVENT_D2H_04H) \
+__PMC_EV_ALIAS("RAT_STALLS.FPSW", IAP_EVENT_D2H_08H) \
+__PMC_EV_ALIAS("RAT_STALLS.PARTIAL_CYCLES", IAP_EVENT_D2H_02H) \
+__PMC_EV_ALIAS("RAT_STALLS.ROB_READ_PORT", IAP_EVENT_D2H_01H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.ANY", IAP_EVENT_DCH_1FH) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.BR_MISS_CLEAR", IAP_EVENT_DCH_10H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.FPCW", IAP_EVENT_DCH_08H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.LD_ST", IAP_EVENT_DCH_04H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.ROB_FULL", IAP_EVENT_DCH_01H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.RS_FULL", IAP_EVENT_DCH_02H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED", IAP_EVENT_A0H_00H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED.PORT0", IAP_EVENT_A1H_01H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED.PORT1", IAP_EVENT_A1H_02H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED.PORT2", IAP_EVENT_A1H_04H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED.PORT3", IAP_EVENT_A1H_08H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED.PORT4", IAP_EVENT_A1H_10H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED.PORT5", IAP_EVENT_A1H_20H) \
+__PMC_EV_ALIAS("SB_DRAIN_CYCLES", IAP_EVENT_04H_01H) \
+__PMC_EV_ALIAS("SEGMENT_REG_LOADS.ANY", IAP_EVENT_06H_00H) \
+__PMC_EV_ALIAS("SEG_REG_RENAMES.ANY", IAP_EVENT_D5H_0FH) \
+__PMC_EV_ALIAS("SEG_REG_RENAMES.DS", IAP_EVENT_D5H_02H) \
+__PMC_EV_ALIAS("SEG_REG_RENAMES.ES", IAP_EVENT_D5H_01H) \
+__PMC_EV_ALIAS("SEG_REG_RENAMES.FS", IAP_EVENT_D5H_04H) \
+__PMC_EV_ALIAS("SEG_REG_RENAMES.GS", IAP_EVENT_D5H_08H) \
+__PMC_EV_ALIAS("SEG_RENAME_STALLS.ANY", IAP_EVENT_D4H_0FH) \
+__PMC_EV_ALIAS("SEG_RENAME_STALLS.DS", IAP_EVENT_D4H_02H) \
+__PMC_EV_ALIAS("SEG_RENAME_STALLS.ES", IAP_EVENT_D4H_01H) \
+__PMC_EV_ALIAS("SEG_RENAME_STALLS.FS", IAP_EVENT_D4H_04H) \
+__PMC_EV_ALIAS("SEG_RENAME_STALLS.GS", IAP_EVENT_D4H_08H) \
+__PMC_EV_ALIAS("SIMD_ASSIST", IAP_EVENT_CDH_00H) \
+__PMC_EV_ALIAS("SIMD_COMP_INST_RETIRED.PACKED_DOUBLE", \
+ IAP_EVENT_CAH_04H) \
+__PMC_EV_ALIAS("SIMD_COMP_INST_RETIRED.PACKED_SINGLE", \
+ IAP_EVENT_CAH_01H) \
+__PMC_EV_ALIAS("SIMD_COMP_INST_RETIRED.SCALAR_DOUBLE", \
+ IAP_EVENT_CAH_08H) \
+__PMC_EV_ALIAS("SIMD_COMP_INST_RETIRED.SCALAR_SINGLE", \
+ IAP_EVENT_CAH_02H) \
+__PMC_EV_ALIAS("SIMD_INSTR_RETIRED", IAP_EVENT_CEH_00H) \
+__PMC_EV_ALIAS("SIMD_INST_RETIRED.ANY", IAP_EVENT_C7H_1FH) \
+__PMC_EV_ALIAS("SIMD_INST_RETIRED.PACKED_DOUBLE", IAP_EVENT_C7H_04H) \
+__PMC_EV_ALIAS("SIMD_INST_RETIRED.PACKED_SINGLE", IAP_EVENT_C7H_01H) \
+__PMC_EV_ALIAS("SIMD_INST_RETIRED.SCALAR_DOUBLE", IAP_EVENT_C7H_08H) \
+__PMC_EV_ALIAS("SIMD_INST_RETIRED.SCALAR_SINGLE", IAP_EVENT_C7H_02H) \
+__PMC_EV_ALIAS("SIMD_INST_RETIRED.VECTOR", IAP_EVENT_C7H_10H) \
+__PMC_EV_ALIAS("SIMD_SAT_INSTR_RETIRED", IAP_EVENT_CFH_00H) \
+__PMC_EV_ALIAS("SIMD_SAT_UOP_EXEC.AR", IAP_EVENT_B1H_80H) \
+__PMC_EV_ALIAS("SIMD_SAT_UOP_EXEC.S", IAP_EVENT_B1H_00H) \
+__PMC_EV_ALIAS("SIMD_UOPS_EXEC.AR", IAP_EVENT_B0H_80H) \
+__PMC_EV_ALIAS("SIMD_UOPS_EXEC.S", IAP_EVENT_B0H_00H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.ARITHMETIC.AR", IAP_EVENT_B3H_A0H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.ARITHMETIC.S", IAP_EVENT_B3H_20H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.LOGICAL.AR", IAP_EVENT_B3H_90H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.LOGICAL.S", IAP_EVENT_B3H_10H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.MUL.AR", IAP_EVENT_B3H_81H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.MUL.S", IAP_EVENT_B3H_01H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.PACK.AR", IAP_EVENT_B3H_84H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.PACK.S", IAP_EVENT_B3H_04H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.SHIFT.AR", IAP_EVENT_B3H_82H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.SHIFT.S", IAP_EVENT_B3H_02H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.UNPACK.AR", IAP_EVENT_B3H_88H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.UNPACK.S", IAP_EVENT_B3H_08H) \
+__PMC_EV_ALIAS("SNOOP_STALL_DRV", IAP_EVENT_7EH) \
+__PMC_EV_ALIAS("SSE_PRE_EXEC.L2", IAP_EVENT_07H_02H) \
+__PMC_EV_ALIAS("SSE_PRE_EXEC.STORES", IAP_EVENT_07H_03H) \
+__PMC_EV_ALIAS("SSE_PRE_MISS.L1", IAP_EVENT_4BH_01H) \
+__PMC_EV_ALIAS("SSE_PRE_MISS.L2", IAP_EVENT_4BH_02H) \
+__PMC_EV_ALIAS("SSE_PRE_MISS.NTA", IAP_EVENT_4BH_00H) \
+__PMC_EV_ALIAS("STORE_BLOCK.ORDER", IAP_EVENT_04H_02H) \
+__PMC_EV_ALIAS("STORE_BLOCK.SNOOP", IAP_EVENT_04H_08H) \
+__PMC_EV_ALIAS("STORE_FORWARDS.GOOD", IAP_EVENT_02H_81H) \
+__PMC_EV_ALIAS("THERMAL_TRIP", IAP_EVENT_3BH_C0H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.ANY", IAP_EVENT_C2H_10H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.FUSED", IAP_EVENT_C2H_07H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.LD_IND_BR", IAP_EVENT_C2H_01H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.MACRO_FUSION", IAP_EVENT_C2H_04H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.NON_FUSED", IAP_EVENT_C2H_08H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.STD_STA", IAP_EVENT_C2H_02H) \
+__PMC_EV_ALIAS("X87_COMP_OPS_EXE.ANY.AR", IAP_EVENT_10H_81H) \
+__PMC_EV_ALIAS("X87_COMP_OPS_EXE.ANY.S", IAP_EVENT_10H_01H) \
+__PMC_EV_ALIAS("X87_OPS_RETIRED.ANY", IAP_EVENT_C1H_FEH) \
+__PMC_EV_ALIAS("X87_OPS_RETIRED.FXCH", IAP_EVENT_C1H_01H)
+
+/*
+ * Aliases for Core PMC events.
+ */
+#define __PMC_EV_ALIAS_CORE() \
+__PMC_EV_ALIAS_INTEL_ARCHITECTURAL() \
+__PMC_EV_ALIAS("BAClears", IAP_EVENT_E6H_00H) \
+__PMC_EV_ALIAS("BTB_Misses", IAP_EVENT_E2H_00H) \
+__PMC_EV_ALIAS("Br_BAC_Missp_Exec", IAP_EVENT_8AH_00H) \
+__PMC_EV_ALIAS("Br_Bogus", IAP_EVENT_E4H_00H) \
+__PMC_EV_ALIAS("Br_Call_Exec", IAP_EVENT_92H_00H) \
+__PMC_EV_ALIAS("Br_Call_Missp_Exec", IAP_EVENT_93H_00H) \
+__PMC_EV_ALIAS("Br_Cnd_Exec", IAP_EVENT_8BH_00H) \
+__PMC_EV_ALIAS("Br_Cnd_Missp_Exec", IAP_EVENT_8CH_00H) \
+__PMC_EV_ALIAS("Br_Ind_Call_Exec", IAP_EVENT_94H_00H) \
+__PMC_EV_ALIAS("Br_Ind_Exec", IAP_EVENT_8DH_00H) \
+__PMC_EV_ALIAS("Br_Ind_Missp_Exec", IAP_EVENT_8EH_00H) \
+__PMC_EV_ALIAS("Br_Inst_Exec", IAP_EVENT_88H_00H) \
+__PMC_EV_ALIAS("Br_Instr_Decoded", IAP_EVENT_E0H_00H) \
+__PMC_EV_ALIAS("Br_Instr_Ret", IAP_EVENT_C4H_00H) \
+__PMC_EV_ALIAS("Br_MisPred_Ret", IAP_EVENT_C5H_00H) \
+__PMC_EV_ALIAS("Br_MisPred_Taken_Ret", IAP_EVENT_CAH_00H) \
+__PMC_EV_ALIAS("Br_Missp_Exec", IAP_EVENT_89H_00H) \
+__PMC_EV_ALIAS("Br_Ret_BAC_Missp_Exec", IAP_EVENT_91H_00H) \
+__PMC_EV_ALIAS("Br_Ret_Exec", IAP_EVENT_8FH_00H) \
+__PMC_EV_ALIAS("Br_Ret_Missp_Exec", IAP_EVENT_90H_00H) \
+__PMC_EV_ALIAS("Br_Taken_Ret", IAP_EVENT_C9H_00H) \
+__PMC_EV_ALIAS("Bus_BNR_Clocks", IAP_EVENT_61H_00H) \
+__PMC_EV_ALIAS("Bus_DRDY_Clocks", IAP_EVENT_62H_00H) \
+__PMC_EV_ALIAS("Bus_Data_Rcv", IAP_EVENT_64H_40H) \
+__PMC_EV_ALIAS("Bus_Locks_Clocks", IAP_EVENT_63H) \
+__PMC_EV_ALIAS("Bus_Not_In_Use", IAP_EVENT_7DH) \
+__PMC_EV_ALIAS("Bus_Req_Outstanding", IAP_EVENT_60H) \
+__PMC_EV_ALIAS("Bus_Snoop_Stall", IAP_EVENT_7EH_00H) \
+__PMC_EV_ALIAS("Bus_Snoops", IAP_EVENT_77H) \
+__PMC_EV_ALIAS("Bus_Trans_Any", IAP_EVENT_70H) \
+__PMC_EV_ALIAS("Bus_Trans_Brd", IAP_EVENT_65H) \
+__PMC_EV_ALIAS("Bus_Trans_Burst", IAP_EVENT_6EH) \
+__PMC_EV_ALIAS("Bus_Trans_Def", IAP_EVENT_6DH) \
+__PMC_EV_ALIAS("Bus_Trans_IO", IAP_EVENT_6CH) \
+__PMC_EV_ALIAS("Bus_Trans_Ifetch", IAP_EVENT_68H) \
+__PMC_EV_ALIAS("Bus_Trans_Inval", IAP_EVENT_69H) \
+__PMC_EV_ALIAS("Bus_Trans_Mem", IAP_EVENT_6FH) \
+__PMC_EV_ALIAS("Bus_Trans_P", IAP_EVENT_6BH) \
+__PMC_EV_ALIAS("Bus_Trans_Pwr", IAP_EVENT_6AH) \
+__PMC_EV_ALIAS("Bus_Trans_RFO", IAP_EVENT_66H) \
+__PMC_EV_ALIAS("Bus_Trans_WB", IAP_EVENT_67H) \
+__PMC_EV_ALIAS("Cycles_Div_Busy", IAP_EVENT_14H_00H) \
+__PMC_EV_ALIAS("Cycles_Int_Masked", IAP_EVENT_C6H_00H) \
+__PMC_EV_ALIAS("Cycles_Int_Pending_Masked", IAP_EVENT_C7H_00H) \
+__PMC_EV_ALIAS("DCU_Snoop_To_Share", IAP_EVENT_78H) \
+__PMC_EV_ALIAS("DCache_Cache_LD", IAP_EVENT_40H) \
+__PMC_EV_ALIAS("DCache_Cache_Lock", IAP_EVENT_42H) \
+__PMC_EV_ALIAS("DCache_Cache_ST", IAP_EVENT_41H) \
+__PMC_EV_ALIAS("DCache_M_Evict", IAP_EVENT_47H_00H) \
+__PMC_EV_ALIAS("DCache_M_Repl", IAP_EVENT_46H_00H) \
+__PMC_EV_ALIAS("DCache_Pend_Miss", IAP_EVENT_48H_00H) \
+__PMC_EV_ALIAS("DCache_Repl", IAP_EVENT_45H_0FH) \
+__PMC_EV_ALIAS("Data_Mem_Cache_Ref", IAP_EVENT_44H_02H) \
+__PMC_EV_ALIAS("Data_Mem_Ref", IAP_EVENT_43H_01H) \
+__PMC_EV_ALIAS("Dbus_Busy", IAP_EVENT_22H) \
+__PMC_EV_ALIAS("Dbus_Busy_Rd", IAP_EVENT_23H) \
+__PMC_EV_ALIAS("Div", IAP_EVENT_13H_00H) \
+__PMC_EV_ALIAS("Dtlb_Miss", IAP_EVENT_49H_00H) \
+__PMC_EV_ALIAS("ESP_Uops", IAP_EVENT_D7H_00H) \
+__PMC_EV_ALIAS("EST_Trans", IAP_EVENT_3AH) \
+__PMC_EV_ALIAS("FP_Assist", IAP_EVENT_11H_00H) \
+__PMC_EV_ALIAS("FP_Comp_Instr_Ret", IAP_EVENT_C1H_00H) \
+__PMC_EV_ALIAS("FP_Comps_Op_Exe", IAP_EVENT_10H_00H) \
+__PMC_EV_ALIAS("FP_MMX_Trans", IAP_EVENT_CCH_01H) \
+__PMC_EV_ALIAS("Fused_Ld_Uops_Ret", IAP_EVENT_DAH_01H) \
+__PMC_EV_ALIAS("Fused_St_Uops_Ret", IAP_EVENT_DAH_02H) \
+__PMC_EV_ALIAS("Fused_Uops_Ret", IAP_EVENT_DAH_00H) \
+__PMC_EV_ALIAS("HW_Int_Rx", IAP_EVENT_C8H_00H) \
+__PMC_EV_ALIAS("ICache_Misses", IAP_EVENT_81H_00H) \
+__PMC_EV_ALIAS("ICache_Reads", IAP_EVENT_80H_00H) \
+__PMC_EV_ALIAS("IFU_Mem_Stall", IAP_EVENT_86H_00H) \
+__PMC_EV_ALIAS("ILD_Stall", IAP_EVENT_87H_00H) \
+__PMC_EV_ALIAS("ITLB_Misses", IAP_EVENT_85H_00H) \
+__PMC_EV_ALIAS("Instr_Decoded", IAP_EVENT_D0H_00H) \
+__PMC_EV_ALIAS("Instr_Ret", IAP_EVENT_C0H_00H) \
+__PMC_EV_ALIAS("L1_Pref_Req", IAP_EVENT_4FH_00H) \
+__PMC_EV_ALIAS("L2_ADS", IAP_EVENT_21H) \
+__PMC_EV_ALIAS("L2_IFetch", IAP_EVENT_28H) \
+__PMC_EV_ALIAS("L2_LD", IAP_EVENT_29H) \
+__PMC_EV_ALIAS("L2_Lines_In", IAP_EVENT_24H) \
+__PMC_EV_ALIAS("L2_Lines_Out", IAP_EVENT_26H) \
+__PMC_EV_ALIAS("L2_M_Lines_In", IAP_EVENT_25H) \
+__PMC_EV_ALIAS("L2_M_Lines_Out", IAP_EVENT_27H) \
+__PMC_EV_ALIAS("L2_No_Request_Cycles", IAP_EVENT_32H) \
+__PMC_EV_ALIAS("L2_Reject_Cycles", IAP_EVENT_30H) \
+__PMC_EV_ALIAS("L2_Rqsts", IAP_EVENT_2EH) \
+__PMC_EV_ALIAS("L2_ST", IAP_EVENT_2AH) \
+__PMC_EV_ALIAS("LD_Blocks", IAP_EVENT_03H_00H) \
+__PMC_EV_ALIAS("LLC_Misses", IAP_EVENT_2EH_41H) \
+__PMC_EV_ALIAS("LLC_Reference", IAP_EVENT_2EH_4FH) \
+__PMC_EV_ALIAS("MMX_Assist", IAP_EVENT_CDH_00H) \
+__PMC_EV_ALIAS("MMX_FP_Trans", IAP_EVENT_CCH_00H) \
+__PMC_EV_ALIAS("MMX_Instr_Exec", IAP_EVENT_B0H_00H) \
+__PMC_EV_ALIAS("MMX_Instr_Ret", IAP_EVENT_CEH_00H) \
+__PMC_EV_ALIAS("Misalign_Mem_Ref", IAP_EVENT_05H_00H) \
+__PMC_EV_ALIAS("Mul", IAP_EVENT_12H_00H) \
+__PMC_EV_ALIAS("NonHlt_Ref_Cycles", IAP_EVENT_3CH_01H) \
+__PMC_EV_ALIAS("Pref_Rqsts_Dn", IAP_EVENT_F8H_00H) \
+__PMC_EV_ALIAS("Pref_Rqsts_Up", IAP_EVENT_F0H_00H) \
+__PMC_EV_ALIAS("Resource_Stall", IAP_EVENT_A2H_00H) \
+__PMC_EV_ALIAS("SD_Drains", IAP_EVENT_04H_00H) \
+__PMC_EV_ALIAS("SIMD_FP_DP_P_Comp_Ret", IAP_EVENT_D9H_02H) \
+__PMC_EV_ALIAS("SIMD_FP_DP_P_Ret", IAP_EVENT_D8H_02H) \
+__PMC_EV_ALIAS("SIMD_FP_DP_S_Comp_Ret", IAP_EVENT_D9H_03H) \
+__PMC_EV_ALIAS("SIMD_FP_DP_S_Ret", IAP_EVENT_D8H_03H) \
+__PMC_EV_ALIAS("SIMD_FP_SP_P_Comp_Ret", IAP_EVENT_D9H_00H) \
+__PMC_EV_ALIAS("SIMD_FP_SP_Ret", IAP_EVENT_D8H_00H) \
+__PMC_EV_ALIAS("SIMD_FP_SP_S_Comp_Ret", IAP_EVENT_D9H_01H) \
+__PMC_EV_ALIAS("SIMD_FP_SP_S_Ret", IAP_EVENT_D8H_01H) \
+__PMC_EV_ALIAS("SIMD_Int_128_Ret", IAP_EVENT_D8H_04H) \
+__PMC_EV_ALIAS("SIMD_Int_Pari_Exec", IAP_EVENT_B3H_20H) \
+__PMC_EV_ALIAS("SIMD_Int_Pck_Exec", IAP_EVENT_B3H_04H) \
+__PMC_EV_ALIAS("SIMD_Int_Plog_Exec", IAP_EVENT_B3H_10H) \
+__PMC_EV_ALIAS("SIMD_Int_Pmul_Exec", IAP_EVENT_B3H_01H) \
+__PMC_EV_ALIAS("SIMD_Int_Psft_Exec", IAP_EVENT_B3H_02H) \
+__PMC_EV_ALIAS("SIMD_Int_Sat_Exec", IAP_EVENT_B1H_00H) \
+__PMC_EV_ALIAS("SIMD_Int_Upck_Exec", IAP_EVENT_B3H_08H) \
+__PMC_EV_ALIAS("SMC_Detected", IAP_EVENT_C3H_00H) \
+__PMC_EV_ALIAS("SSE_NTStores_Miss", IAP_EVENT_4BH_03H) \
+__PMC_EV_ALIAS("SSE_NTStores_Ret", IAP_EVENT_07H_03H) \
+__PMC_EV_ALIAS("SSE_PrefNta_Miss", IAP_EVENT_4BH_00H) \
+__PMC_EV_ALIAS("SSE_PrefNta_Ret", IAP_EVENT_07H_00H) \
+__PMC_EV_ALIAS("SSE_PrefT1_Miss", IAP_EVENT_4BH_01H) \
+__PMC_EV_ALIAS("SSE_PrefT1_Ret", IAP_EVENT_07H_01H) \
+__PMC_EV_ALIAS("SSE_PrefT2_Miss", IAP_EVENT_4BH_02H) \
+__PMC_EV_ALIAS("SSE_PrefT2_Ret", IAP_EVENT_07H_02H) \
+__PMC_EV_ALIAS("Seg_Reg_Loads", IAP_EVENT_06H_00H) \
+__PMC_EV_ALIAS("Serial_Execution_Cycles", IAP_EVENT_3CH_02H) \
+__PMC_EV_ALIAS("Thermal_Trip", IAP_EVENT_3BH_C0H) \
+__PMC_EV_ALIAS("Unfusion", IAP_EVENT_DBH_00H) \
+__PMC_EV_ALIAS("Unhalted_Core_Cycles", IAP_EVENT_3CH_00H) \
+__PMC_EV_ALIAS("Uops_Ret", IAP_EVENT_C2H_00H)
+
+/*
+ * Aliases for Core2 PMC events.
+ */
+#define __PMC_EV_ALIAS_CORE2() \
+__PMC_EV_ALIAS_INTEL_ARCHITECTURAL() \
+__PMC_EV_ALIAS("BACLEARS", IAP_EVENT_E6H_00H) \
+__PMC_EV_ALIAS("BOGUS_BR", IAP_EVENT_E4H_00H) \
+__PMC_EV_ALIAS("BR_BAC_MISSP_EXEC", IAP_EVENT_8AH_00H) \
+__PMC_EV_ALIAS("BR_CALL_EXEC", IAP_EVENT_92H_00H) \
+__PMC_EV_ALIAS("BR_CALL_MISSP_EXEC", IAP_EVENT_93H_00H) \
+__PMC_EV_ALIAS("BR_CND_EXEC", IAP_EVENT_8BH_00H) \
+__PMC_EV_ALIAS("BR_CND_MISSP_EXEC", IAP_EVENT_8CH_00H) \
+__PMC_EV_ALIAS("BR_IND_CALL_EXEC", IAP_EVENT_94H_00H) \
+__PMC_EV_ALIAS("BR_IND_EXEC", IAP_EVENT_8DH_00H) \
+__PMC_EV_ALIAS("BR_IND_MISSP_EXEC", IAP_EVENT_8EH_00H) \
+__PMC_EV_ALIAS("BR_INST_DECODED", IAP_EVENT_E0H_00H) \
+__PMC_EV_ALIAS("BR_INST_EXEC", IAP_EVENT_88H_00H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.ANY", IAP_EVENT_C4H_00H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.MISPRED", IAP_EVENT_C5H_00H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.MISPRED_NOT_TAKEN", \
+ IAP_EVENT_C4H_02H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.MISPRED_TAKEN", \
+ IAP_EVENT_C4H_08H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.PRED_NOT_TAKEN", \
+ IAP_EVENT_C4H_01H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.PRED_TAKEN", \
+ IAP_EVENT_C4H_04H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.TAKEN", IAP_EVENT_C4H_0CH) \
+__PMC_EV_ALIAS("BR_MISSP_EXEC", IAP_EVENT_89H_00H) \
+__PMC_EV_ALIAS("BR_RET_BAC_MISSP_EXEC", IAP_EVENT_91H_00H) \
+__PMC_EV_ALIAS("BR_RET_EXEC", IAP_EVENT_8FH_00H) \
+__PMC_EV_ALIAS("BR_RET_MISSP_EXEC", IAP_EVENT_90H_00H) \
+__PMC_EV_ALIAS("BR_TKN_BUBBLE_1", IAP_EVENT_97H_00H) \
+__PMC_EV_ALIAS("BR_TKN_BUBBLE_2", IAP_EVENT_98H_00H) \
+__PMC_EV_ALIAS("BUSQ_EMPTY", IAP_EVENT_7DH) \
+__PMC_EV_ALIAS("BUS_BNR_DRV", IAP_EVENT_61H) \
+__PMC_EV_ALIAS("BUS_DATA_RCV", IAP_EVENT_64H) \
+__PMC_EV_ALIAS("BUS_DRDY_CLOCKS", IAP_EVENT_62H) \
+__PMC_EV_ALIAS("BUS_HITM_DRV", IAP_EVENT_7BH) \
+__PMC_EV_ALIAS("BUS_HIT_DRV", IAP_EVENT_7AH) \
+__PMC_EV_ALIAS("BUS_IO_WAIT", IAP_EVENT_7FH) \
+__PMC_EV_ALIAS("BUS_LOCK_CLOCKS", IAP_EVENT_63H) \
+__PMC_EV_ALIAS("BUS_REQUEST_OUTSTANDING", \
+ IAP_EVENT_60H) \
+__PMC_EV_ALIAS("BUS_TRANS_ANY", IAP_EVENT_70H) \
+__PMC_EV_ALIAS("BUS_TRANS_BRD", IAP_EVENT_65H) \
+__PMC_EV_ALIAS("BUS_TRANS_BURST", IAP_EVENT_6EH) \
+__PMC_EV_ALIAS("BUS_TRANS_DEF", IAP_EVENT_6DH) \
+__PMC_EV_ALIAS("BUS_TRANS_IFETCH", IAP_EVENT_68H) \
+__PMC_EV_ALIAS("BUS_TRANS_INVAL", IAP_EVENT_69H) \
+__PMC_EV_ALIAS("BUS_TRANS_IO", IAP_EVENT_6CH) \
+__PMC_EV_ALIAS("BUS_TRANS_MEM", IAP_EVENT_6FH) \
+__PMC_EV_ALIAS("BUS_TRANS_P", IAP_EVENT_6BH) \
+__PMC_EV_ALIAS("BUS_TRANS_PWR", IAP_EVENT_6AH) \
+__PMC_EV_ALIAS("BUS_TRANS_RFO", IAP_EVENT_66H) \
+__PMC_EV_ALIAS("BUS_TRANS_WB", IAP_EVENT_67H) \
+__PMC_EV_ALIAS("CMP_SNOOP", IAP_EVENT_78H) \
+__PMC_EV_ALIAS("CPU_CLK_UNHALTED.BUS", IAP_EVENT_3CH_01H) \
+__PMC_EV_ALIAS("CPU_CLK_UNHALTED.CORE_P", \
+ IAP_EVENT_3CH_00H) \
+__PMC_EV_ALIAS("CPU_CLK_UNHALTED.NO_OTHER", \
+ IAP_EVENT_3CH_02H) \
+__PMC_EV_ALIAS("CYCLES_DIV_BUSY", IAP_EVENT_14H_00H) \
+__PMC_EV_ALIAS("CYCLES_INT_MASKED", IAP_EVENT_C6H_01H) \
+__PMC_EV_ALIAS("CYCLES_INT_PENDING_AND_MASKED", \
+ IAP_EVENT_C6H_02H) \
+__PMC_EV_ALIAS("CYCLES_L1I_MEM_STALLED", IAP_EVENT_86H_00H) \
+__PMC_EV_ALIAS("DELAYED_BYPASS.FP", IAP_EVENT_19H_00H) \
+__PMC_EV_ALIAS("DELAYED_BYPASS.LOAD", IAP_EVENT_19H_01H) \
+__PMC_EV_ALIAS("DELAYED_BYPASS.SIMD", IAP_EVENT_19H_02H) \
+__PMC_EV_ALIAS("DIV", IAP_EVENT_13H_00H) \
+__PMC_EV_ALIAS("DTLB_MISSES.ANY", IAP_EVENT_08H_01H) \
+__PMC_EV_ALIAS("DTLB_MISSES.L0_MISS_LD", IAP_EVENT_08H_04H) \
+__PMC_EV_ALIAS("DTLB_MISSES.MISS_LD", IAP_EVENT_08H_02H) \
+__PMC_EV_ALIAS("DTLB_MISSES.MISS_ST", IAP_EVENT_08H_08H) \
+__PMC_EV_ALIAS("EIST_TRANS", IAP_EVENT_3AH_00H) \
+__PMC_EV_ALIAS("ESP.ADDITIONS", IAP_EVENT_ABH_02H) \
+__PMC_EV_ALIAS("ESP.SYNCH", IAP_EVENT_ABH_01H) \
+__PMC_EV_ALIAS("EXT_SNOOP", IAP_EVENT_77H) \
+__PMC_EV_ALIAS("FP_ASSIST", IAP_EVENT_11H_00H) \
+__PMC_EV_ALIAS("FP_COMP_OPS_EXE", IAP_EVENT_10H_00H) \
+__PMC_EV_ALIAS("FP_MMX_TRANS_TO_FP", IAP_EVENT_CCH_02H) \
+__PMC_EV_ALIAS("FP_MMX_TRANS_TO_MMX", IAP_EVENT_CCH_01H) \
+__PMC_EV_ALIAS("HW_INT_RCV", IAP_EVENT_C8H_00H) \
+__PMC_EV_ALIAS("IDLE_DURING_DIV", IAP_EVENT_18H_00H) \
+__PMC_EV_ALIAS("ILD_STALL", IAP_EVENT_87H_00H) \
+__PMC_EV_ALIAS("INST_QUEUE.FULL", IAP_EVENT_83H_02H) \
+__PMC_EV_ALIAS("INST_RETIRED.ANY_P", IAP_EVENT_C0H_00H) \
+__PMC_EV_ALIAS("INST_RETIRED.LOADS", IAP_EVENT_C0H_01H) \
+__PMC_EV_ALIAS("INST_RETIRED.OTHER", IAP_EVENT_C0H_04H) \
+__PMC_EV_ALIAS("INST_RETIRED.STORES", IAP_EVENT_C0H_02H) \
+__PMC_EV_ALIAS("INST_RETIRED.VM_H", IAP_EVENT_C0H_08H) \
+__PMC_EV_ALIAS("ITLB.FLUSH", IAP_EVENT_82H_40H) \
+__PMC_EV_ALIAS("ITLB.LARGE_MISS", IAP_EVENT_82H_10H) \
+__PMC_EV_ALIAS("ITLB.MISSES", IAP_EVENT_82H_12H) \
+__PMC_EV_ALIAS("ITLB.SMALL_MISS", IAP_EVENT_82H_02H) \
+__PMC_EV_ALIAS("ITLB_MISS_RETIRED", IAP_EVENT_C9H_00H) \
+__PMC_EV_ALIAS("L1D_ALL_CACHE_REF", IAP_EVENT_43H_02H) \
+__PMC_EV_ALIAS("L1D_ALL_REF", IAP_EVENT_43H_01H) \
+__PMC_EV_ALIAS("L1D_CACHE_LD", IAP_EVENT_40H) \
+__PMC_EV_ALIAS("L1D_CACHE_LOCK", IAP_EVENT_42H) \
+__PMC_EV_ALIAS("L1D_CACHE_LOCK_DURATION", IAP_EVENT_42H_10H) \
+__PMC_EV_ALIAS("L1D_CACHE_ST", IAP_EVENT_41H) \
+__PMC_EV_ALIAS("L1D_M_EVICT", IAP_EVENT_47H_00H) \
+__PMC_EV_ALIAS("L1D_M_REPL", IAP_EVENT_46H_00H) \
+__PMC_EV_ALIAS("L1D_PEND_MISS", IAP_EVENT_48H_00H) \
+__PMC_EV_ALIAS("L1D_PREFETCH.REQUESTS", IAP_EVENT_4EH_10H) \
+__PMC_EV_ALIAS("L1D_REPL", IAP_EVENT_45H_0FH) \
+__PMC_EV_ALIAS("L1D_SPLIT.LOADS", IAP_EVENT_49H_01H) \
+__PMC_EV_ALIAS("L1D_SPLIT.STORES", IAP_EVENT_49H_02H) \
+__PMC_EV_ALIAS("L1I_MISSES", IAP_EVENT_81H_00H) \
+__PMC_EV_ALIAS("L1I_READS", IAP_EVENT_80H_00H) \
+__PMC_EV_ALIAS("L2_ADS", IAP_EVENT_21H) \
+__PMC_EV_ALIAS("L2_DBUS_BUSY_RD", IAP_EVENT_23H) \
+__PMC_EV_ALIAS("L2_IFETCH", IAP_EVENT_28H) \
+__PMC_EV_ALIAS("L2_LD", IAP_EVENT_29H) \
+__PMC_EV_ALIAS("L2_LINES_IN", IAP_EVENT_24H) \
+__PMC_EV_ALIAS("L2_LINES_OUT", IAP_EVENT_26H) \
+__PMC_EV_ALIAS("L2_LOCK", IAP_EVENT_2BH) \
+__PMC_EV_ALIAS("L2_M_LINES_IN", IAP_EVENT_25H) \
+__PMC_EV_ALIAS("L2_M_LINES_OUT", IAP_EVENT_27H) \
+__PMC_EV_ALIAS("L2_NO_REQ", IAP_EVENT_32H) \
+__PMC_EV_ALIAS("L2_REJECT_BUSQ", IAP_EVENT_30H) \
+__PMC_EV_ALIAS("L2_RQSTS", IAP_EVENT_2EH) \
+__PMC_EV_ALIAS("L2_RQSTS.SELF.DEMAND.I_STATE", \
+ IAP_EVENT_2EH_41H) \
+__PMC_EV_ALIAS("L2_RQSTS.SELF.DEMAND.MESI", \
+ IAP_EVENT_2EH_4FH) \
+__PMC_EV_ALIAS("L2_ST", IAP_EVENT_2AH) \
+__PMC_EV_ALIAS("LOAD_BLOCK.L1D", IAP_EVENT_03H_20H) \
+__PMC_EV_ALIAS("LOAD_BLOCK.OVERLAP_STORE", \
+ IAP_EVENT_03H_08H) \
+__PMC_EV_ALIAS("LOAD_BLOCK.STA", IAP_EVENT_03H_02H) \
+__PMC_EV_ALIAS("LOAD_BLOCK.STD", IAP_EVENT_03H_04H) \
+__PMC_EV_ALIAS("LOAD_BLOCK.UNTIL_RETIRE", IAP_EVENT_03H_10H) \
+__PMC_EV_ALIAS("LOAD_HIT_PRE", IAP_EVENT_4CH_00H) \
+__PMC_EV_ALIAS("MACHINE_NUKES.MEM_ORDER", IAP_EVENT_C3H_04H) \
+__PMC_EV_ALIAS("MACHINE_NUKES.SMC", IAP_EVENT_C3H_01H) \
+__PMC_EV_ALIAS("MACRO_INSTS.CISC_DECODED", IAP_EVENT_AAH_08H) \
+__PMC_EV_ALIAS("MACRO_INSTS.DECODED", IAP_EVENT_AAH_01H) \
+__PMC_EV_ALIAS("MEMORY_DISAMBIGUATION.RESET", \
+ IAP_EVENT_09H_01H) \
+__PMC_EV_ALIAS("MEMORY_DISAMBIGUATION.SUCCESS", \
+ IAP_EVENT_09H_02H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.DTLB_MISS", \
+ IAP_EVENT_CBH_10H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.L1D_LINE_MISS", \
+ IAP_EVENT_CBH_02H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.L1D_MISS", \
+ IAP_EVENT_CBH_01H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.L2_LINE_MISS", \
+ IAP_EVENT_CBH_08H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.L2_MISS", \
+ IAP_EVENT_CBH_04H) \
+__PMC_EV_ALIAS("MUL", IAP_EVENT_12H_00H) \
+__PMC_EV_ALIAS("PAGE_WALKS.COUNT", IAP_EVENT_0CH_01H) \
+__PMC_EV_ALIAS("PAGE_WALKS.CYCLES", IAP_EVENT_0CH_02H) \
+__PMC_EV_ALIAS("PREF_RQSTS_DN", IAP_EVENT_F8H_00H) \
+__PMC_EV_ALIAS("PREF_RQSTS_UP", IAP_EVENT_F0H_00H) \
+__PMC_EV_ALIAS("RAT_STALLS.ANY", IAP_EVENT_D2H_0FH) \
+__PMC_EV_ALIAS("RAT_STALLS.FLAGS", IAP_EVENT_D2H_04H) \
+__PMC_EV_ALIAS("RAT_STALLS.FPSW", IAP_EVENT_D2H_08H) \
+__PMC_EV_ALIAS("RAT_STALLS.OTHER_SERIALIZATION_STALLS", \
+ IAP_EVENT_D2H_10H) \
+__PMC_EV_ALIAS("RAT_STALLS.PARTIAL_CYCLES", \
+ IAP_EVENT_D2H_02H) \
+__PMC_EV_ALIAS("RAT_STALLS.ROB_READ_PORT", \
+ IAP_EVENT_D2H_01H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.ANY", IAP_EVENT_DCH_1FH) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.BR_MISS_CLEAR", \
+ IAP_EVENT_DCH_10H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.FPCW", IAP_EVENT_DCH_08H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.LD_ST", IAP_EVENT_DCH_04H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.ROB_FULL", \
+ IAP_EVENT_DCH_01H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.RS_FULL", IAP_EVENT_DCH_02H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED", IAP_EVENT_A0H_00H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED.PORT0", IAP_EVENT_A1H_01H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED.PORT1", IAP_EVENT_A1H_02H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED.PORT2", IAP_EVENT_A1H_04H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED.PORT3", IAP_EVENT_A1H_08H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED.PORT4", IAP_EVENT_A1H_10H) \
+__PMC_EV_ALIAS("RS_UOPS_DISPATCHED.PORT5", IAP_EVENT_A1H_20H) \
+__PMC_EV_ALIAS("SB_DRAIN_CYCLES", IAP_EVENT_04H_01H) \
+__PMC_EV_ALIAS("SEGMENT_REG_LOADS", IAP_EVENT_06H_00H) \
+__PMC_EV_ALIAS("SEG_REG_RENAMES.ANY", IAP_EVENT_D5H_0FH) \
+__PMC_EV_ALIAS("SEG_REG_RENAMES.DS", IAP_EVENT_D5H_02H) \
+__PMC_EV_ALIAS("SEG_REG_RENAMES.ES", IAP_EVENT_D5H_01H) \
+__PMC_EV_ALIAS("SEG_REG_RENAMES.FS", IAP_EVENT_D5H_04H) \
+__PMC_EV_ALIAS("SEG_REG_RENAMES.GS", IAP_EVENT_D5H_08H) \
+__PMC_EV_ALIAS("SEG_RENAME_STALLS.ANY", IAP_EVENT_D4H_0FH) \
+__PMC_EV_ALIAS("SEG_RENAME_STALLS.DS", IAP_EVENT_D4H_02H) \
+__PMC_EV_ALIAS("SEG_RENAME_STALLS.ES", IAP_EVENT_D4H_01H) \
+__PMC_EV_ALIAS("SEG_RENAME_STALLS.FS", IAP_EVENT_D4H_04H) \
+__PMC_EV_ALIAS("SEG_RENAME_STALLS.GS", IAP_EVENT_D4H_08H) \
+__PMC_EV_ALIAS("SIMD_ASSIST", IAP_EVENT_CDH_00H) \
+__PMC_EV_ALIAS("SIMD_COMP_INST_RETIRED.PACKED_DOUBLE", \
+ IAP_EVENT_CAH_04H) \
+__PMC_EV_ALIAS("SIMD_COMP_INST_RETIRED.PACKED_SINGLE", \
+ IAP_EVENT_CAH_01H) \
+__PMC_EV_ALIAS("SIMD_COMP_INST_RETIRED.SCALAR_DOUBLE", \
+ IAP_EVENT_CAH_08H) \
+__PMC_EV_ALIAS("SIMD_COMP_INST_RETIRED.SCALAR_SINGLE", \
+ IAP_EVENT_CAH_02H) \
+__PMC_EV_ALIAS("SIMD_INSTR_RETIRED", IAP_EVENT_CEH_00H) \
+__PMC_EV_ALIAS("SIMD_INST_RETIRED.ANY", IAP_EVENT_C7H_1FH) \
+__PMC_EV_ALIAS("SIMD_INST_RETIRED.PACKED_DOUBLE", \
+ IAP_EVENT_C7H_04H) \
+__PMC_EV_ALIAS("SIMD_INST_RETIRED.PACKED_SINGLE", \
+ IAP_EVENT_C7H_01H) \
+__PMC_EV_ALIAS("SIMD_INST_RETIRED.SCALAR_DOUBLE", \
+ IAP_EVENT_C7H_08H) \
+__PMC_EV_ALIAS("SIMD_INST_RETIRED.SCALAR_SINGLE", \
+ IAP_EVENT_C7H_02H) \
+__PMC_EV_ALIAS("SIMD_INST_RETIRED.VECTOR", IAP_EVENT_C7H_10H) \
+__PMC_EV_ALIAS("SIMD_SAT_INSTR_RETIRED", IAP_EVENT_CFH_00H) \
+__PMC_EV_ALIAS("SIMD_SAT_UOP_EXEC", IAP_EVENT_B1H_00H) \
+__PMC_EV_ALIAS("SIMD_UOPS_EXEC", IAP_EVENT_B0H_00H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.ARITHMETIC", IAP_EVENT_B3H_20H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.LOGICAL", IAP_EVENT_B3H_10H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.MUL", IAP_EVENT_B3H_01H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.PACK", IAP_EVENT_B3H_04H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.SHIFT", IAP_EVENT_B3H_02H) \
+__PMC_EV_ALIAS("SIMD_UOP_TYPE_EXEC.UNPACK", IAP_EVENT_B3H_08H) \
+__PMC_EV_ALIAS("SNOOP_STALL_DRV", IAP_EVENT_7EH) \
+__PMC_EV_ALIAS("SSE_PRE_EXEC.L1", IAP_EVENT_07H_01H) \
+__PMC_EV_ALIAS("SSE_PRE_EXEC.L2", IAP_EVENT_07H_02H) \
+__PMC_EV_ALIAS("SSE_PRE_EXEC.NTA", IAP_EVENT_07H_00H) \
+__PMC_EV_ALIAS("SSE_PRE_EXEC.STORES", IAP_EVENT_07H_03H) \
+__PMC_EV_ALIAS("SSE_PRE_MISS.L1", IAP_EVENT_4BH_01H) \
+__PMC_EV_ALIAS("SSE_PRE_MISS.L2", IAP_EVENT_4BH_02H) \
+__PMC_EV_ALIAS("SSE_PRE_MISS.NTA", IAP_EVENT_4BH_00H) \
+__PMC_EV_ALIAS("STORE_BLOCK.ORDER", IAP_EVENT_04H_02H) \
+__PMC_EV_ALIAS("STORE_BLOCK.SNOOP", IAP_EVENT_04H_08H) \
+__PMC_EV_ALIAS("THERMAL_TRIP", IAP_EVENT_3BH_C0H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.ANY", IAP_EVENT_C2H_0FH) \
+__PMC_EV_ALIAS("UOPS_RETIRED.FUSED", IAP_EVENT_C2H_07H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.LD_IND_BR", IAP_EVENT_C2H_01H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.MACRO_FUSION", IAP_EVENT_C2H_04H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.NON_FUSED", IAP_EVENT_C2H_08H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.STD_STA", IAP_EVENT_C2H_02H) \
+__PMC_EV_ALIAS("X87_OPS_RETIRED.ANY", IAP_EVENT_C1H_FEH) \
+__PMC_EV_ALIAS("X87_OPS_RETIRED.FXCH", IAP_EVENT_C1H_01H)
+
+/*
+ * Aliases for Core i7 PMC events.
+ */
+#define __PMC_EV_ALIAS_COREI7() \
+__PMC_EV_ALIAS_INTEL_ARCHITECTURAL() \
+__PMC_EV_ALIAS("SB_FORWARD.ANY", IAP_EVENT_02H_01H) \
+__PMC_EV_ALIAS("LOAD_BLOCK.STD", IAP_EVENT_03H_01H) \
+__PMC_EV_ALIAS("LOAD_BLOCK.ADDRESS_OFFSET", IAP_EVENT_03H_04H) \
+__PMC_EV_ALIAS("SB_DRAIN.CYCLES", IAP_EVENT_04H_01H) \
+__PMC_EV_ALIAS("MISALIGN_MEM_REF.LOAD", IAP_EVENT_05H_01H) \
+__PMC_EV_ALIAS("MISALIGN_MEM_REF.STORE", IAP_EVENT_05H_02H) \
+__PMC_EV_ALIAS("MISALIGN_MEM_REF.ANY", IAP_EVENT_05H_03H) \
+__PMC_EV_ALIAS("STORE_BLOCKS.NOT_STA", IAP_EVENT_06H_01H) \
+__PMC_EV_ALIAS("STORE_BLOCKS.STA", IAP_EVENT_06H_02H) \
+__PMC_EV_ALIAS("STORE_BLOCKS.AT_RET", IAP_EVENT_06H_04H) \
+__PMC_EV_ALIAS("STORE_BLOCKS.L1D_BLOCK", IAP_EVENT_06H_08H) \
+__PMC_EV_ALIAS("STORE_BLOCKS.ANY", IAP_EVENT_06H_0FH) \
+__PMC_EV_ALIAS("PARTIAL_ADDRESS_ALIAS", IAP_EVENT_07H_01H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.ANY", IAP_EVENT_08H_01H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.WALK_COMPLETED", IAP_EVENT_08H_02H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.STLB_HIT", IAP_EVENT_08H_10H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.PDE_MISS", IAP_EVENT_08H_20H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.PDP_MISS", IAP_EVENT_08H_40H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.LARGE_WALK_COMPLETED", IAP_EVENT_08H_80H) \
+__PMC_EV_ALIAS("MEMORY_DISAMBIGURATION.RESET", IAP_EVENT_09H_01H) \
+__PMC_EV_ALIAS("MEMORY_DISAMBIGURATION.SUCCESS", IAP_EVENT_09H_02H) \
+__PMC_EV_ALIAS("MEMORY_DISAMBIGURATION.WATCHDOG", IAP_EVENT_09H_04H) \
+__PMC_EV_ALIAS("MEMORY_DISAMBIGURATION.WATCH_CYCLES", IAP_EVENT_09H_08H) \
+__PMC_EV_ALIAS("MEM_INST_RETIRED.LOADS", IAP_EVENT_0BH_01H) \
+__PMC_EV_ALIAS("MEM_INST_RETIRED.STORES", IAP_EVENT_0BH_02H) \
+__PMC_EV_ALIAS("MEM_STORE_RETIRED.DTLB_MISS", IAP_EVENT_0CH_01H) \
+__PMC_EV_ALIAS("UOPS_ISSUED.ANY", IAP_EVENT_0EH_01H) \
+__PMC_EV_ALIAS("UOPS_ISSUED.FUSED", IAP_EVENT_0EH_02H) \
+__PMC_EV_ALIAS("MEM_UNCORE_RETIRED.OTHER_CORE_L2_HITM", IAP_EVENT_0FH_02H) \
+__PMC_EV_ALIAS("MEM_UNCORE_RETIRED.REMOTE_CACHE_LOCAL_HOME_HIT", IAP_EVENT_0FH_08H) \
+__PMC_EV_ALIAS("MEM_UNCORE_RETIRED.REMOTE_DRAM", IAP_EVENT_0FH_10H) \
+__PMC_EV_ALIAS("MEM_UNCORE_RETIRED.LOCAL_DRAM", IAP_EVENT_0FH_20H) \
+__PMC_EV_ALIAS("FP_COMP_OPS_EXE.X87", IAP_EVENT_10H_01H) \
+__PMC_EV_ALIAS("FP_COMP_OPS_EXE.MMX", IAP_EVENT_10H_02H) \
+__PMC_EV_ALIAS("FP_COMP_OPS_EXE.SSE_FP", IAP_EVENT_10H_04H) \
+__PMC_EV_ALIAS("FP_COMP_OPS_EXE.SSE2_INTEGER", IAP_EVENT_10H_08H) \
+__PMC_EV_ALIAS("FP_COMP_OPS_EXE.SSE_FP_PACKED", IAP_EVENT_10H_10H) \
+__PMC_EV_ALIAS("FP_COMP_OPS_EXE.SSE_FP_SCALAR", IAP_EVENT_10H_20H) \
+__PMC_EV_ALIAS("FP_COMP_OPS_EXE.SSE_SINGLE_PRECISION", IAP_EVENT_10H_40H) \
+__PMC_EV_ALIAS("FP_COMP_OPS_EXE.SSE_DOUBLE_PRECISION", IAP_EVENT_10H_80H) \
+__PMC_EV_ALIAS("SIMD_INT_128.PACKED_MPY", IAP_EVENT_12H_01H) \
+__PMC_EV_ALIAS("SIMD_INT_128.PACKED_SHIFT", IAP_EVENT_12H_02H) \
+__PMC_EV_ALIAS("SIMD_INT_128.PACK", IAP_EVENT_12H_04H) \
+__PMC_EV_ALIAS("SIMD_INT_128.UNPACK", IAP_EVENT_12H_08H) \
+__PMC_EV_ALIAS("SIMD_INT_128.PACKED_LOGICAL", IAP_EVENT_12H_10H) \
+__PMC_EV_ALIAS("SIMD_INT_128.PACKED_ARITH", IAP_EVENT_12H_20H) \
+__PMC_EV_ALIAS("SIMD_INT_128.SHUFFLE_MOVE", IAP_EVENT_12H_40H) \
+__PMC_EV_ALIAS("LOAD_DISPATCH.RS", IAP_EVENT_13H_01H) \
+__PMC_EV_ALIAS("LOAD_DISPATCH.RS_DELAYED", IAP_EVENT_13H_02H) \
+__PMC_EV_ALIAS("LOAD_DISPATCH.MOB", IAP_EVENT_13H_04H) \
+__PMC_EV_ALIAS("LOAD_DISPATCH.ANY", IAP_EVENT_13H_07H) \
+__PMC_EV_ALIAS("ARITH.CYCLES_DIV_BUSY", IAP_EVENT_14H_01H) \
+__PMC_EV_ALIAS("ARITH.MUL", IAP_EVENT_14H_02H) \
+__PMC_EV_ALIAS("INST_QUEUE_WRITES", IAP_EVENT_17H_01H) \
+__PMC_EV_ALIAS("INST_DECODED.DEC0", IAP_EVENT_18H_01H) \
+__PMC_EV_ALIAS("TWO_UOP_INSTS_DECODED", IAP_EVENT_19H_01H) \
+__PMC_EV_ALIAS("HW_INT.RCV", IAP_EVENT_1DH_01H) \
+__PMC_EV_ALIAS("HW_INT.CYCLES_MASKED", IAP_EVENT_1DH_02H) \
+__PMC_EV_ALIAS("HW_INT.CYCLES_PENDING_AND_MASKED", IAP_EVENT_1DH_04H) \
+__PMC_EV_ALIAS("INST_QUEUE_WRITE_CYCLES", IAP_EVENT_1EH_01H) \
+__PMC_EV_ALIAS("L2_RQSTS.LD_HIT", IAP_EVENT_24H_01H) \
+__PMC_EV_ALIAS("L2_RQSTS.LD_MISS", IAP_EVENT_24H_02H) \
+__PMC_EV_ALIAS("L2_RQSTS.LOADS", IAP_EVENT_24H_03H) \
+__PMC_EV_ALIAS("L2_RQSTS.RFO_HIT", IAP_EVENT_24H_04H) \
+__PMC_EV_ALIAS("L2_RQSTS.RFO_MISS", IAP_EVENT_24H_08H) \
+__PMC_EV_ALIAS("L2_RQSTS.RFOS", IAP_EVENT_24H_0CH) \
+__PMC_EV_ALIAS("L2_RQSTS.IFETCH_HIT", IAP_EVENT_24H_10H) \
+__PMC_EV_ALIAS("L2_RQSTS.IFETCH_MISS", IAP_EVENT_24H_20H) \
+__PMC_EV_ALIAS("L2_RQSTS.IFETCHES", IAP_EVENT_24H_30H) \
+__PMC_EV_ALIAS("L2_RQSTS.PREFETCH_HIT", IAP_EVENT_24H_40H) \
+__PMC_EV_ALIAS("L2_RQSTS.PREFETCH_MISS", IAP_EVENT_24H_80H) \
+__PMC_EV_ALIAS("L2_RQSTS.PREFETCHES", IAP_EVENT_24H_C0H) \
+__PMC_EV_ALIAS("L2_RQSTS.MISS", IAP_EVENT_24H_AAH) \
+__PMC_EV_ALIAS("L2_RQSTS.REFERENCES", IAP_EVENT_24H_FFH) \
+__PMC_EV_ALIAS("L2_DATA_RQSTS.DEMAND.I_STATE", IAP_EVENT_26H_01H) \
+__PMC_EV_ALIAS("L2_DATA_RQSTS.DEMAND.S_STATE", IAP_EVENT_26H_02H) \
+__PMC_EV_ALIAS("L2_DATA_RQSTS.DEMAND.E_STATE", IAP_EVENT_26H_04H) \
+__PMC_EV_ALIAS("L2_DATA_RQSTS.DEMAND.M_STATE", IAP_EVENT_26H_08H) \
+__PMC_EV_ALIAS("L2_DATA_RQSTS.DEMAND.MESI", IAP_EVENT_26H_0FH) \
+__PMC_EV_ALIAS("L2_DATA_RQSTS.PREFETCH.I_STATE", IAP_EVENT_26H_10H) \
+__PMC_EV_ALIAS("L2_DATA_RQSTS.PREFETCH.S_STATE", IAP_EVENT_26H_20H) \
+__PMC_EV_ALIAS("L2_DATA_RQSTS.PREFETCH.E_STATE", IAP_EVENT_26H_40H) \
+__PMC_EV_ALIAS("L2_DATA_RQSTS.PREFETCH.M_STATE", IAP_EVENT_26H_80H) \
+__PMC_EV_ALIAS("L2_DATA_RQSTS.PREFETCH.MESI", IAP_EVENT_26H_F0H) \
+__PMC_EV_ALIAS("L2_DATA_RQSTS.ANY", IAP_EVENT_26H_FFH) \
+__PMC_EV_ALIAS("L2_WRITE.RFO.I_STATE", IAP_EVENT_27H_01H) \
+__PMC_EV_ALIAS("L2_WRITE.RFO.S_STATE", IAP_EVENT_27H_02H) \
+__PMC_EV_ALIAS("L2_WRITE.RFO.E_STATE", IAP_EVENT_27H_04H) \
+__PMC_EV_ALIAS("L2_WRITE.RFO.M_STATE", IAP_EVENT_27H_08H) \
+__PMC_EV_ALIAS("L2_WRITE.RFO.HIT", IAP_EVENT_27H_0EH) \
+__PMC_EV_ALIAS("L2_WRITE.RFO.MESI", IAP_EVENT_27H_0FH) \
+__PMC_EV_ALIAS("L2_WRITE.LOCK.I_STATE", IAP_EVENT_27H_10H) \
+__PMC_EV_ALIAS("L2_WRITE.LOCK.S_STATE", IAP_EVENT_27H_20H) \
+__PMC_EV_ALIAS("L2_WRITE.LOCK.E_STATE", IAP_EVENT_27H_40H) \
+__PMC_EV_ALIAS("L2_WRITE.LOCK.M_STATE", IAP_EVENT_27H_80H) \
+__PMC_EV_ALIAS("L2_WRITE.LOCK.HIT", IAP_EVENT_27H_E0H) \
+__PMC_EV_ALIAS("L2_WRITE.LOCK.MESI", IAP_EVENT_27H_F0H) \
+__PMC_EV_ALIAS("L1D_WB_L2.I_STATE", IAP_EVENT_28H_01H) \
+__PMC_EV_ALIAS("L1D_WB_L2.S_STATE", IAP_EVENT_28H_02H) \
+__PMC_EV_ALIAS("L1D_WB_L2.E_STATE", IAP_EVENT_28H_04H) \
+__PMC_EV_ALIAS("L1D_WB_L2.M_STATE", IAP_EVENT_28H_08H) \
+__PMC_EV_ALIAS("L1D_WB_L2.MESI", IAP_EVENT_28H_0FH) \
+__PMC_EV_ALIAS("LONGEST_LAT_CACHE.REFERENCE", IAP_EVENT_2EH_4FH) \
+__PMC_EV_ALIAS("LONGEST_LAT_CACHE.MISS", IAP_EVENT_2EH_41H) \
+__PMC_EV_ALIAS("CPU_CLK_UNHALTED.THREAD_P", IAP_EVENT_3CH_00H) \
+__PMC_EV_ALIAS("CPU_CLK_UNHALTED.REF_P", IAP_EVENT_3CH_01H) \
+__PMC_EV_ALIAS("UOPS_DECODED.DEC0", IAP_EVENT_3DH_01H) \
+__PMC_EV_ALIAS("L1D_CACHE_LD.I_STATE", IAP_EVENT_40H_01H) \
+__PMC_EV_ALIAS("L1D_CACHE_LD.S_STATE", IAP_EVENT_40H_02H) \
+__PMC_EV_ALIAS("L1D_CACHE_LD.E_STATE", IAP_EVENT_40H_04H) \
+__PMC_EV_ALIAS("L1D_CACHE_LD.M_STATE", IAP_EVENT_40H_08H) \
+__PMC_EV_ALIAS("L1D_CACHE_LD.MESI", IAP_EVENT_40H_0FH) \
+__PMC_EV_ALIAS("L1D_CACHE_ST.I_STATE", IAP_EVENT_41H_01H) \
+__PMC_EV_ALIAS("L1D_CACHE_ST.S_STATE", IAP_EVENT_41H_02H) \
+__PMC_EV_ALIAS("L1D_CACHE_ST.E_STATE", IAP_EVENT_41H_04H) \
+__PMC_EV_ALIAS("L1D_CACHE_ST.M_STATE", IAP_EVENT_41H_08H) \
+__PMC_EV_ALIAS("L1D_CACHE_ST.MESI", IAP_EVENT_41H_0FH) \
+__PMC_EV_ALIAS("L1D_CACHE_LOCK.HIT", IAP_EVENT_42H_01H) \
+__PMC_EV_ALIAS("L1D_CACHE_LOCK.S_STATE", IAP_EVENT_42H_02H) \
+__PMC_EV_ALIAS("L1D_CACHE_LOCK.E_STATE", IAP_EVENT_42H_04H) \
+__PMC_EV_ALIAS("L1D_CACHE_LOCK.M_STATE", IAP_EVENT_42H_08H) \
+__PMC_EV_ALIAS("L1D_ALL_REF.ANY", IAP_EVENT_43H_01H) \
+__PMC_EV_ALIAS("L1D_ALL_REF.CACHEABLE", IAP_EVENT_43H_02H) \
+__PMC_EV_ALIAS("L1D_PEND_MISS.LOAD_BUFFERS_FULL", IAP_EVENT_48H_02H) \
+__PMC_EV_ALIAS("DTLB_MISSES.ANY", IAP_EVENT_49H_01H) \
+__PMC_EV_ALIAS("DTLB_MISSES.WALK_COMPLETED", IAP_EVENT_49H_02H) \
+__PMC_EV_ALIAS("DTLB_MISSES.STLB_HIT", IAP_EVENT_49H_10H) \
+__PMC_EV_ALIAS("DTLB_MISSES.PDE_MISS", IAP_EVENT_49H_20H) \
+__PMC_EV_ALIAS("DTLB_MISSES.PDP_MISS", IAP_EVENT_49H_40H) \
+__PMC_EV_ALIAS("DTLB_MISSES.LARGE_WALK_COMPLETED", IAP_EVENT_49H_80H) \
+__PMC_EV_ALIAS("SSE_MEM_EXEC.NTA", IAP_EVENT_4BH_01H) \
+__PMC_EV_ALIAS("SSE_MEM_EXEC.STREAMING_STORES", IAP_EVENT_4BH_08H) \
+__PMC_EV_ALIAS("LOAD_HIT_PRE", IAP_EVENT_4CH_01H) \
+__PMC_EV_ALIAS("SFENCE_CYCLES", IAP_EVENT_4DH_01H) \
+__PMC_EV_ALIAS("L1D_PREFETCH.REQUESTS", IAP_EVENT_4EH_01H) \
+__PMC_EV_ALIAS("L1D_PREFETCH.MISS", IAP_EVENT_4EH_02H) \
+__PMC_EV_ALIAS("L1D_PREFETCH.TRIGGERS", IAP_EVENT_4EH_04H) \
+__PMC_EV_ALIAS("EPT.EPDE_MISS", IAP_EVENT_4FH_02H) \
+__PMC_EV_ALIAS("EPT.EPDPE_HIT", IAP_EVENT_4FH_04H) \
+__PMC_EV_ALIAS("EPT.EPDPE_MISS", IAP_EVENT_4FH_08H) \
+__PMC_EV_ALIAS("L1D.REPL", IAP_EVENT_51H_01H) \
+__PMC_EV_ALIAS("L1D.M_REPL", IAP_EVENT_51H_02H) \
+__PMC_EV_ALIAS("L1D.M_EVICT", IAP_EVENT_51H_04H) \
+__PMC_EV_ALIAS("L1D.M_SNOOP_EVICT", IAP_EVENT_51H_08H) \
+__PMC_EV_ALIAS("L1D_CACHE_PREFETCH_LOCK_FB_HIT", IAP_EVENT_52H_01H) \
+__PMC_EV_ALIAS("L1D_CACHE_LOCK_FB_HIT", IAP_EVENT_53H_01H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_DATA", IAP_EVENT_60H_01H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_OUTSTANDING.DEMAND.READ_CODE", IAP_EVENT_60H_02H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_OUTSTANDING.DEMAND.RFO", IAP_EVENT_60H_04H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_OUTSTANDING.ANY.READ", IAP_EVENT_60H_08H) \
+__PMC_EV_ALIAS("CACHE_LOCK_CYCLES.L1D_L2", IAP_EVENT_63H_01H) \
+__PMC_EV_ALIAS("CACHE_LOCK_CYCLES.L1D", IAP_EVENT_63H_02H) \
+__PMC_EV_ALIAS("IO_TRANSACTIONS", IAP_EVENT_6CH_01H) \
+__PMC_EV_ALIAS("L1I.HITS", IAP_EVENT_80H_01H) \
+__PMC_EV_ALIAS("L1I.MISSES", IAP_EVENT_80H_02H) \
+__PMC_EV_ALIAS("L1I.READS", IAP_EVENT_80H_03H) \
+__PMC_EV_ALIAS("L1I.CYCLES_STALLED", IAP_EVENT_80H_04H) \
+__PMC_EV_ALIAS("IFU_IVC.FULL", IAP_EVENT_81H_01H) \
+__PMC_EV_ALIAS("IFU_IVC.L1I_EVICTION", IAP_EVENT_81H_02H) \
+__PMC_EV_ALIAS("LARGE_ITLB.HIT", IAP_EVENT_82H_01H) \
+__PMC_EV_ALIAS("L1I_OPPORTUNISTIC_HITS", IAP_EVENT_83H_01H) \
+__PMC_EV_ALIAS("ITLB_MISSES.ANY", IAP_EVENT_85H_01H) \
+__PMC_EV_ALIAS("ITLB_MISSES.WALK_COMPLETED", IAP_EVENT_85H_02H) \
+__PMC_EV_ALIAS("ITLB_MISSES.WALK_CYCLES", IAP_EVENT_85H_04H) \
+__PMC_EV_ALIAS("ITLB_MISSES.STLB_HIT", IAP_EVENT_85H_10H) \
+__PMC_EV_ALIAS("ITLB_MISSES.PDE_MISS", IAP_EVENT_85H_20H) \
+__PMC_EV_ALIAS("ITLB_MISSES.PDP_MISS", IAP_EVENT_85H_40H) \
+__PMC_EV_ALIAS("ITLB_MISSES.LARGE_WALK_COMPLETED", IAP_EVENT_85H_80H) \
+__PMC_EV_ALIAS("ILD_STALL.LCP", IAP_EVENT_87H_01H) \
+__PMC_EV_ALIAS("ILD_STALL.MRU", IAP_EVENT_87H_02H) \
+__PMC_EV_ALIAS("ILD_STALL.IQ_FULL", IAP_EVENT_87H_04H) \
+__PMC_EV_ALIAS("ILD_STALL.REGEN", IAP_EVENT_87H_08H) \
+__PMC_EV_ALIAS("ILD_STALL.ANY", IAP_EVENT_87H_0FH) \
+__PMC_EV_ALIAS("BR_INST_EXEC.COND", IAP_EVENT_88H_01H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.DIRECT", IAP_EVENT_88H_02H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.INDIRECT_NON_CALL", IAP_EVENT_88H_04H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.NON_CALLS", IAP_EVENT_88H_07H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.RETURN_NEAR", IAP_EVENT_88H_08H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.DIRECT_NEAR_CALL", IAP_EVENT_88H_10H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.INDIRECT_NEAR_CALL", IAP_EVENT_88H_20H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.NEAR_CALLS", IAP_EVENT_88H_30H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.TAKEN", IAP_EVENT_88H_40H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.ANY", IAP_EVENT_7FH) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.COND", IAP_EVENT_89H_01H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.DIRECT", IAP_EVENT_89H_02H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.INDIRECT_NON_CALL", IAP_EVENT_89H_04H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.NON_CALLS", IAP_EVENT_89H_07H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.RETURN_NEAR", IAP_EVENT_89H_08H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.DIRECT_NEAR_CALL", IAP_EVENT_89H_10H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.INDIRECT_NEAR_CALL", IAP_EVENT_89H_20H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.NEAR_CALLS", IAP_EVENT_89H_30H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.TAKEN", IAP_EVENT_89H_40H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.ANY", IAP_EVENT_89H_7FH) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.ANY", IAP_EVENT_A2H_01H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.LOAD", IAP_EVENT_A2H_02H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.RS_FULL", IAP_EVENT_A2H_04H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.STORE", IAP_EVENT_A2H_08H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.ROB_FULL", IAP_EVENT_A2H_10H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.FPCW", IAP_EVENT_A2H_20H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.MXCSR", IAP_EVENT_A2H_40H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.OTHER", IAP_EVENT_A2H_80H) \
+__PMC_EV_ALIAS("MACRO_INSTS.FUSIONS_DECODED", IAP_EVENT_A6H_01H) \
+__PMC_EV_ALIAS("BACLEAR_FORCE_IQ", IAP_EVENT_A7H_01H) \
+__PMC_EV_ALIAS("LSD.UOPS", IAP_EVENT_A8H_01H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.DEMAND.READ_DATA", IAP_EVENT_B0H_01H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.DEMAND.READ_CODE", IAP_EVENT_B0H_02H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.DEMAND.RFO", IAP_EVENT_B0H_04H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.ANY.READ", IAP_EVENT_B0H_08H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.ANY.RFO", IAP_EVENT_80H_10H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.UNCACHED_MEM", IAP_EVENT_B0H_20H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.L1D_WRITEBACK", IAP_EVENT_B0H_40H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.ANY", IAP_EVENT_B0H_80H) \
+__PMC_EV_ALIAS("UOPS_EXECUTED.PORT0", IAP_EVENT_B1H_01H) \
+__PMC_EV_ALIAS("UOPS_EXECUTED.PORT1", IAP_EVENT_B1H_02H) \
+__PMC_EV_ALIAS("UOPS_EXECUTED.PORT2_CORE", IAP_EVENT_B1H_04H) \
+__PMC_EV_ALIAS("UOPS_EXECUTED.PORT3_CORE", IAP_EVENT_B1H_08H) \
+__PMC_EV_ALIAS("UOPS_EXECUTED.PORT4_CORE", IAP_EVENT_B1H_10H) \
+__PMC_EV_ALIAS("UOPS_EXECUTED.PORT5", IAP_EVENT_B1H_20H) \
+__PMC_EV_ALIAS("UOPS_EXECUTED.PORT015", IAP_EVENT_B1H_40H) \
+__PMC_EV_ALIAS("UOPS_EXECUTED.PORT234", IAP_EVENT_B1H_80H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_SQ_FULL", IAP_EVENT_B2H_01H) \
+__PMC_EV_ALIAS("SNOOPQ_REQUESTS_OUTSTANDING.DATA", IAP_EVENT_B3H_01H) \
+__PMC_EV_ALIAS("SNOOPQ_REQUESTS_OUTSTANDING.INVALIDATE", IAP_EVENT_B3H_02H) \
+__PMC_EV_ALIAS("SNOOPQ_REQUESTS_OUTSTANDING.CODE", IAP_EVENT_B3H_04H) \
+__PMC_EV_ALIAS("OOF_CORE_RESPONSE_0", IAP_EVENT_B7H_01H) \
+__PMC_EV_ALIAS("SNOOP_RESPONSE.HIT", IAP_EVENT_B8H_01H) \
+__PMC_EV_ALIAS("SNOOP_RESPONSE.HITE", IAP_EVENT_B8H_02H) \
+__PMC_EV_ALIAS("SNOOP_RESPONSE.HITM", IAP_EVENT_B8H_04H) \
+__PMC_EV_ALIAS("PIC_ACCESSES.TPR_READS", IAP_EVENT_BAH_01H) \
+__PMC_EV_ALIAS("PIC_ACCESSES.TPR_WRITES", IAP_EVENT_BAH_02H) \
+__PMC_EV_ALIAS("INST_RETIRED.ANY_P", IAP_EVENT_C0H_01H) \
+__PMC_EV_ALIAS("INST_RETIRED.X87", IAP_EVENT_C0H_02H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.ANY", IAP_EVENT_C2H_01H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.RETIRE_SLOTS", IAP_EVENT_C2H_02H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.MACRO_FUSED", IAP_EVENT_C2H_04H) \
+__PMC_EV_ALIAS("MACHINE_CLEARS.CYCLES", IAP_EVENT_C3H_01H) \
+__PMC_EV_ALIAS("MACHINE_CLEARS.MEM_ORDER", IAP_EVENT_C3H_02H) \
+__PMC_EV_ALIAS("MACHINE_CLEARS.SMC", IAP_EVENT_C3H_04H) \
+__PMC_EV_ALIAS("MACHINE_CLEARS.FUSION_ASSIST", IAP_EVENT_C3H_10H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.ALL_BRANCHES", IAP_EVENT_C4H_00H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.CONDITIONAL", IAP_EVENT_C4H_01H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.NEAR_CALL", IAP_EVENT_C4H_02H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.ALL_BRANCHES", IAP_EVENT_C4H_04H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.ALL_BRANCHES", IAP_EVENT_C5H_00H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.NEAR_CALL", IAP_EVENT_C5H_02H) \
+__PMC_EV_ALIAS("SSEX_UOPS_RETIRED.PACKED_SINGLE", IAP_EVENT_C7H_01H) \
+__PMC_EV_ALIAS("SSEX_UOPS_RETIRED.SCALAR_SINGLE", IAP_EVENT_C7H_02H) \
+__PMC_EV_ALIAS("SSEX_UOPS_RETIRED.PACKED_DOUBLE", IAP_EVENT_C7H_04H) \
+__PMC_EV_ALIAS("SSEX_UOPS_RETIRED.SCALAR_DOUBLE", IAP_EVENT_C7H_08H) \
+__PMC_EV_ALIAS("SSEX_UOPS_RETIRED.VECTOR_INTEGER", IAP_EVENT_C7H_10H) \
+__PMC_EV_ALIAS("ITLB_MISS_RETIRED", IAP_EVENT_C8H_20H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.L1D_HIT", IAP_EVENT_CBH_01H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.L2_HIT", IAP_EVENT_CBH_02H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.LLC_UNSHARED_HIT", IAP_EVENT_CBH_04H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.OTHER_CORE_L2_HIT_HITM", IAP_EVENT_CBH_08H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.LLC_MISS", IAP_EVENT_CBH_10H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.HIT_LFB", IAP_EVENT_CBH_40H) \
+__PMC_EV_ALIAS("MEM_LOAD_RETIRED.DTLB_MISS", IAP_EVENT_CBH_80H) \
+__PMC_EV_ALIAS("FP_MMX_TRANS.TO_FP", IAP_EVENT_CCH_01H) \
+__PMC_EV_ALIAS("FP_MMX_TRANS.TO_MMX", IAP_EVENT_CCH_02H) \
+__PMC_EV_ALIAS("FP_MMX_TRANS.ANY", IAP_EVENT_CCH_03H) \
+__PMC_EV_ALIAS("MACRO_INSTS.DECODED", IAP_EVENT_D0H_01H) \
+__PMC_EV_ALIAS("UOPS_DECODED.MS", IAP_EVENT_D1H_02H) \
+__PMC_EV_ALIAS("UOPS_DECODED.ESP_FOLDING", IAP_EVENT_D1H_04H) \
+__PMC_EV_ALIAS("UOPS_DECODED.ESP_SYNC", IAP_EVENT_D1H_08H) \
+__PMC_EV_ALIAS("RAT_STALLS.FLAGS", IAP_EVENT_D2H_01H) \
+__PMC_EV_ALIAS("RAT_STALLS.REGISTERS", IAP_EVENT_D2H_02H) \
+__PMC_EV_ALIAS("RAT_STALLS.ROB_READ_PORT", IAP_EVENT_D2H_04H) \
+__PMC_EV_ALIAS("RAT_STALLS.SCOREBOARD", IAP_EVENT_D2H_08H) \
+__PMC_EV_ALIAS("RAT_STALLS.ANY", IAP_EVENT_D2H_0FH) \
+__PMC_EV_ALIAS("SEG_RENAME_STALLS", IAP_EVENT_D4H_01H) \
+__PMC_EV_ALIAS("ES_REG_RENAMES", IAP_EVENT_D5H_01H) \
+__PMC_EV_ALIAS("UOP_UNFUSION", IAP_EVENT_DBH_01H) \
+__PMC_EV_ALIAS("BR_INST_DECODED", IAP_EVENT_E0H_01H) \
+__PMC_EV_ALIAS("BOGUS_BR", IAP_EVENT_E4H_01H) \
+__PMC_EV_ALIAS("BPU_MISSED_CALL_RET", IAP_EVENT_E5H_01H) \
+__PMC_EV_ALIAS("L2_HW_PREFETCH.DATA_TRIGGER", IAP_EVENT_F3H_04H) \
+__PMC_EV_ALIAS("L2_HW_PREFETCH.CODE_TRIGGER", IAP_EVENT_F3H_08H) \
+__PMC_EV_ALIAS("L2_HW_PREFETCH.DCA_TRIGGER", IAP_EVENT_F3H_10H) \
+__PMC_EV_ALIAS("L2_HW_PREFETCH.KICK_START", IAP_EVENT_F3H_20H) \
+__PMC_EV_ALIAS("SQ_MISC.PROMOTION", IAP_EVENT_F4H_01H) \
+__PMC_EV_ALIAS("SQ_MISC.PROMOTION_POST_GO", IAP_EVENT_F4H_02H) \
+__PMC_EV_ALIAS("SQ_MISC.LRU_HINTS", IAP_EVENT_F4H_04H) \
+__PMC_EV_ALIAS("SQ_MISC.FILL_DROPPED", IAP_EVENT_F4H_08H) \
+__PMC_EV_ALIAS("SQ_MISC.SPLIT_LOCK", IAP_EVENT_F4H_10H) \
+__PMC_EV_ALIAS("SQ_FULL_STALL_CYCLES", IAP_EVENT_F6H_01H) \
+__PMC_EV_ALIAS("FP_ASSIST.ALL", IAP_EVENT_F7H_01H) \
+__PMC_EV_ALIAS("FP_ASSIST.OUTPUT", IAP_EVENT_F7H_02H) \
+__PMC_EV_ALIAS("FP_ASSIST.INPUT", IAP_EVENT_F7H_04H) \
+__PMC_EV_ALIAS("SEGMENT_REG_LOADS", IAP_EVENT_F8H_01H) \
+__PMC_EV_ALIAS("SIMD_INT_64.PACKED_MPY", IAP_EVENT_FDH_01H) \
+__PMC_EV_ALIAS("SIMD_INT_64.PACKED_SHIFT", IAP_EVENT_FDH_02H) \
+__PMC_EV_ALIAS("SIMD_INT_64.PACK", IAP_EVENT_FDH_04H) \
+__PMC_EV_ALIAS("SIMD_INT_64.UNPACK", IAP_EVENT_FDH_08H) \
+__PMC_EV_ALIAS("SIMD_INT_64.PACKED_LOGICAL", IAP_EVENT_FDH_10H) \
+__PMC_EV_ALIAS("SIMD_INT_64.PACKED_ARITH", IAP_EVENT_FDH_20H) \
+__PMC_EV_ALIAS("SIMD_INT_64.SHUFFLE_MOVE", IAP_EVENT_FDH_40H)
+
/* timestamp counters. */
#define __PMC_EV_TSC() \
- __PMC_EV(TSC, TSC, tsc)
+ __PMC_EV(TSC, TSC)
+
+#define PMC_EV_TSC_FIRST PMC_EV_TSC_TSC
+#define PMC_EV_TSC_LAST PMC_EV_TSC_TSC
-/* All known PMC events */
-#define __PMC_EVENTS() \
- __PMC_EV_TSC() \
- __PMC_EV_K7() \
- __PMC_EV_P6() \
- __PMC_EV_P4() \
- __PMC_EV_K8() \
- __PMC_EV_P5() \
+/*
+ * All known PMC events.
+ *
+ * PMC event numbers are allocated sparsely to allow new PMC events to
+ * be added to a PMC class without breaking ABI compatibility. The
+ * current allocation scheme is:
+ *
+ * START #EVENTS DESCRIPTION
+ * 0 0x1000 Reserved
+ * 0x1000 0x0001 TSC
+ * 0x2000 0x0080 AMD K7 events
+ * 0x2080 0x0100 AMD K8 events
+ * 0x10000 0x0080 INTEL architectural fixed-function events
+ * 0x10080 0x0F80 INTEL architectural programmable events
+ * 0x11000 0x0080 INTEL Pentium 4 events
+ * 0x11080 0x0080 INTEL Pentium MMX events
+ * 0x11100 0x0100 INTEL Pentium Pro/P-II/P-III/Pentium-M events
+ */
+#define __PMC_EVENTS() \
+ __PMC_EV_BLOCK(TSC, 0x01000) \
+ __PMC_EV_TSC() \
+ __PMC_EV_BLOCK(K7, 0x2000) \
+ __PMC_EV_K7() \
+ __PMC_EV_BLOCK(K8, 0x2080) \
+ __PMC_EV_K8() \
+ __PMC_EV_BLOCK(IAF, 0x10000) \
+ __PMC_EV_IAF() \
+ __PMC_EV_BLOCK(IAP, 0x10080) \
+ __PMC_EV_IAP() \
+ __PMC_EV_BLOCK(P4, 0x11000) \
+ __PMC_EV_P4() \
+ __PMC_EV_BLOCK(P5, 0x11080) \
+ __PMC_EV_P5() \
+ __PMC_EV_BLOCK(P6, 0x11100) \
+ __PMC_EV_P6()
#define PMC_EVENT_FIRST PMC_EV_TSC_TSC
-#define PMC_EVENT_LAST PMC_EV_P5_LAST
+#define PMC_EVENT_LAST PMC_EV_P6_LAST
#endif /* _DEV_HWPMC_PMC_EVENTS_H_ */