diff options
| author | Fabien Thomas <fabient@FreeBSD.org> | 2009-06-07 10:00:35 +0000 |
|---|---|---|
| committer | Fabien Thomas <fabient@FreeBSD.org> | 2009-06-07 10:00:35 +0000 |
| commit | 0daa13da2cc92fe2e572359be36c097dbfb15cd5 (patch) | |
| tree | 7a525335db9e18d2198a022a0ba8f51b5dbf3bed /sys/dev/hwpmc | |
| parent | ae96b43bc16761abca4920adc31f3c6e61e99619 (diff) | |
Notes
Diffstat (limited to 'sys/dev/hwpmc')
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_amd.c | 425 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_amd.h | 8 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_arm.c | 26 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_core.c | 1988 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_core.h | 121 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_ia64.c | 26 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_intel.c | 269 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_logging.c | 137 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_mod.c | 827 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_pentium.c | 10 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_pentium.h | 5 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_piv.c | 539 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_piv.h | 7 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_powerpc.c | 26 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_ppro.c | 409 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_ppro.h | 5 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_sparc64.c | 26 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_tsc.c | 388 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_tsc.h | 43 | ||||
| -rw-r--r-- | sys/dev/hwpmc/hwpmc_x86.c | 264 | ||||
| -rw-r--r-- | sys/dev/hwpmc/pmc_events.h | 2325 |
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_ */ |
