summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjkoshy <jkoshy@FreeBSD.org>2008-11-27 09:00:47 +0000
committerjkoshy <jkoshy@FreeBSD.org>2008-11-27 09:00:47 +0000
commitaa86a7c59edb19ee67bcf28d9465dc88c0b1fd6a (patch)
treeb416bbd4293b5dc3b86cfd87f09039063e60517b
parent272e95193bef3d1cacf8bf5d82b6f7bbe6d500a7 (diff)
downloadFreeBSD-src-aa86a7c59edb19ee67bcf28d9465dc88c0b1fd6a.zip
FreeBSD-src-aa86a7c59edb19ee67bcf28d9465dc88c0b1fd6a.tar.gz
- Add support for PMCs in Intel CPUs of Family 6, model 0xE (Core Solo
and Core Duo), models 0xF (Core2), model 0x17 (Core2Extreme) and model 0x1C (Atom). In these CPUs, the actual numbers, kinds and widths of PMCs present need to queried at run time. Support for specific "architectural" events also needs to be queried at run time. Model 0xE CPUs support programmable PMCs, subsequent CPUs additionally support "fixed-function" counters. - Use event names that are close to vendor documentation, taking in account that: - events with identical semantics on two or more CPUs in this family can have differing names in vendor documentation, - identical vendor event names may map to differing events across CPUs, - each type of CPU supports a different subset of measurable events. Fixed-function and programmable counters both use the same vendor names for events. The use of a class name prefix ("iaf-" or "iap-" respectively) permits these to be distinguished. - In libpmc, refactor pmc_name_of_event() into a public interface and an internal helper function, for use by log handling code. - Minor code tweaks: staticize a global, freshen a few comments. Tested by: gnn
-rw-r--r--lib/libpmc/libpmc.c442
-rw-r--r--lib/libpmc/libpmcinternal.h37
-rw-r--r--lib/libpmc/pmclog.c5
-rw-r--r--sys/amd64/include/pmc_mdep.h9
-rw-r--r--sys/conf/files.amd641
-rw-r--r--sys/conf/files.i3861
-rw-r--r--sys/dev/hwpmc/hwpmc_core.c1747
-rw-r--r--sys/dev/hwpmc/hwpmc_core.h121
-rw-r--r--sys/dev/hwpmc/hwpmc_intel.c42
-rw-r--r--sys/dev/hwpmc/hwpmc_logging.c7
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c11
-rw-r--r--sys/dev/hwpmc/pmc_events.h970
-rw-r--r--sys/i386/include/pmc_mdep.h17
-rw-r--r--sys/modules/hwpmc/Makefile7
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/pmc.h8
-rw-r--r--sys/sys/pmclog.h3
17 files changed, 3356 insertions, 74 deletions
diff --git a/lib/libpmc/libpmc.c b/lib/libpmc/libpmc.c
index b71ef3c..c6e31f6 100644
--- a/lib/libpmc/libpmc.c
+++ b/lib/libpmc/libpmc.c
@@ -42,12 +42,18 @@ __FBSDID("$FreeBSD$");
#include <strings.h>
#include <unistd.h>
+#include "libpmcinternal.h"
+
/* Function prototypes */
#if defined(__i386__)
static int k7_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
struct pmc_op_pmcallocate *_pmc_config);
#endif
#if defined(__amd64__) || defined(__i386__)
+static int iaf_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
+ struct pmc_op_pmcallocate *_pmc_config);
+static int iap_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
+ struct pmc_op_pmcallocate *_pmc_config);
static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
struct pmc_op_pmcallocate *_pmc_config);
static int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
@@ -110,19 +116,55 @@ struct pmc_class_descr {
#define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N },
/*
- * PMC_MDEP_TABLE(NAME, CLASS, ADDITIONAL_CLASSES...)
+ * PMC_CLASSDEP_TABLE(NAME, CLASS)
*
- * Build an event descriptor table and a list of valid PMC classes.
+ * Define a table mapping event names and aliases to HWPMC event IDs.
*/
-#define PMC_MDEP_TABLE(N,C,...) \
+#define PMC_CLASSDEP_TABLE(N, C) \
static const struct pmc_event_descr N##_event_table[] = \
{ \
__PMC_EV_##C() \
- }; \
+ }
+
+PMC_CLASSDEP_TABLE(iaf, IAF);
+PMC_CLASSDEP_TABLE(k7, K7);
+PMC_CLASSDEP_TABLE(k8, K8);
+PMC_CLASSDEP_TABLE(p4, P4);
+PMC_CLASSDEP_TABLE(p5, P5);
+PMC_CLASSDEP_TABLE(p6, P6);
+
+#undef __PMC_EV_ALIAS
+#define __PMC_EV_ALIAS(N,CODE) { N, PMC_EV_##CODE },
+
+static const struct pmc_event_descr atom_event_table[] =
+{
+ __PMC_EV_ALIAS_ATOM()
+};
+
+static const struct pmc_event_descr core_event_table[] =
+{
+ __PMC_EV_ALIAS_CORE()
+};
+
+
+static const struct pmc_event_descr core2_event_table[] =
+{
+ __PMC_EV_ALIAS_CORE2()
+};
+
+/*
+ * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...)
+ *
+ * Map a CPU to the PMC classes it supports.
+ */
+#define PMC_MDEP_TABLE(N,C,...) \
static const enum pmc_class N##_pmc_classes[] = { \
PMC_CLASS_##C, __VA_ARGS__ \
}
+PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
+PMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC);
+PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC);
PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC);
PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC);
@@ -135,39 +177,44 @@ static const struct pmc_event_descr tsc_event_table[] =
};
#undef PMC_CLASS_TABLE_DESC
-#define PMC_CLASS_TABLE_DESC(N, C) { \
- .pm_evc_name = #N "-", \
- .pm_evc_name_size = sizeof(#N "-") - 1, \
- .pm_evc_class = PMC_CLASS_##C , \
- .pm_evc_event_table = N##_event_table , \
+#define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \
+static const struct pmc_class_descr NAME##_class_table_descr = \
+ { \
+ .pm_evc_name = #CLASS "-", \
+ .pm_evc_name_size = sizeof(#CLASS "-") - 1, \
+ .pm_evc_class = PMC_CLASS_##CLASS , \
+ .pm_evc_event_table = EVENTS##_event_table , \
.pm_evc_event_table_size = \
- PMC_EVENT_TABLE_SIZE(N), \
- .pm_evc_allocate_pmc = N##_allocate_pmc \
+ PMC_EVENT_TABLE_SIZE(EVENTS), \
+ .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \
}
-static const struct pmc_class_descr pmc_class_table[] =
-{
+#if defined(__i386__) || defined(__amd64__)
+PMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf);
+PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap);
+PMC_CLASS_TABLE_DESC(core, IAP, core, iap);
+PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap);
+#endif
#if defined(__i386__)
- PMC_CLASS_TABLE_DESC(k7, K7),
+PMC_CLASS_TABLE_DESC(k7, K7, k7, k7);
#endif
#if defined(__i386__) || defined(__amd64__)
- PMC_CLASS_TABLE_DESC(k8, K8),
- PMC_CLASS_TABLE_DESC(p4, P4),
+PMC_CLASS_TABLE_DESC(k8, K8, k8, k8);
+PMC_CLASS_TABLE_DESC(p4, P4, p4, p4);
#endif
#if defined(__i386__)
- PMC_CLASS_TABLE_DESC(p5, P5),
- PMC_CLASS_TABLE_DESC(p6, P6),
+PMC_CLASS_TABLE_DESC(p5, P5, p5, p5);
+PMC_CLASS_TABLE_DESC(p6, P6, p6, p6);
#endif
#if defined(__i386__) || defined(__amd64__)
- PMC_CLASS_TABLE_DESC(tsc, TSC)
+PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc);
#endif
-};
-
-static size_t pmc_event_class_table_size =
- PMC_TABLE_SIZE(pmc_class_table);
#undef PMC_CLASS_TABLE_DESC
+static const struct pmc_class_descr **pmc_class_table;
+#define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass
+
static const enum pmc_class *pmc_mdep_class_list;
static size_t pmc_mdep_class_list_size;
@@ -371,6 +418,237 @@ k7_allocate_pmc(enum pmc_event pe, char *ctrspec,
#if defined(__amd64__) || defined(__i386__)
/*
+ * Intel Core (Family 6, Model E) PMCs.
+ */
+
+static struct pmc_event_alias core_aliases[] = {
+ EV_ALIAS("branches", "iap-br-instr-ret"),
+ EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"),
+ EV_ALIAS("cycles", "tsc-tsc"),
+ EV_ALIAS("ic-misses", "iap-icache-misses"),
+ EV_ALIAS("instructions", "iap-instr-ret"),
+ EV_ALIAS("interrupts", "iap-core-hw-int-rx"),
+ EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"),
+ EV_ALIAS(NULL, NULL)
+};
+
+/*
+ * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H)
+ * and Atom (Family 6, model 1CH) PMCs.
+ */
+
+static struct pmc_event_alias core2_aliases[] = {
+ EV_ALIAS("branches", "iap-br-inst-retired.any"),
+ EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"),
+ EV_ALIAS("cycles", "tsc-tsc"),
+ EV_ALIAS("ic-misses", "iap-l1i-misses"),
+ EV_ALIAS("instructions", "iaf-instr-retired.any"),
+ EV_ALIAS("interrupts", "iap-hw-int-rcv"),
+ EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"),
+ EV_ALIAS(NULL, NULL)
+};
+#define atom_aliases core2_aliases
+
+#define IAF_KW_OS "os"
+#define IAF_KW_USR "usr"
+#define IAF_KW_ANYTHREAD "anythread"
+
+/*
+ * Parse an event specifier for Intel fixed function counters.
+ */
+static int
+iaf_allocate_pmc(enum pmc_event pe, char *ctrspec,
+ struct pmc_op_pmcallocate *pmc_config)
+{
+ char *p;
+
+ (void) pe;
+
+ pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
+ pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0;
+
+ while ((p = strsep(&ctrspec, ",")) != NULL) {
+ if (KWMATCH(p, IAF_KW_OS))
+ pmc_config->pm_caps |= PMC_CAP_SYSTEM;
+ else if (KWMATCH(p, IAF_KW_USR))
+ pmc_config->pm_caps |= PMC_CAP_USER;
+ else if (KWMATCH(p, IAF_KW_ANYTHREAD))
+ pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY;
+ else
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Core/Core2 support.
+ */
+
+#define IAP_KW_AGENT "agent"
+#define IAP_KW_ANYTHREAD "anythread"
+#define IAP_KW_CACHESTATE "cachestate"
+#define IAP_KW_CMASK "cmask"
+#define IAP_KW_CORE "core"
+#define IAP_KW_EDGE "edge"
+#define IAP_KW_INV "inv"
+#define IAP_KW_OS "os"
+#define IAP_KW_PREFETCH "prefetch"
+#define IAP_KW_SNOOPRESPONSE "snoopresponse"
+#define IAP_KW_SNOOPTYPE "snooptype"
+#define IAP_KW_TRANSITION "trans"
+#define IAP_KW_USR "usr"
+
+static struct pmc_masks iap_core_mask[] = {
+ PMCMASK(all, (0x3 << 14)),
+ PMCMASK(this, (0x1 << 14)),
+ NULLMASK
+};
+
+static struct pmc_masks iap_agent_mask[] = {
+ PMCMASK(this, 0),
+ PMCMASK(any, (0x1 << 13)),
+ NULLMASK
+};
+
+static struct pmc_masks iap_prefetch_mask[] = {
+ PMCMASK(both, (0x3 << 12)),
+ PMCMASK(only, (0x1 << 12)),
+ PMCMASK(exclude, 0),
+ NULLMASK
+};
+
+static struct pmc_masks iap_cachestate_mask[] = {
+ PMCMASK(i, (1 << 8)),
+ PMCMASK(s, (1 << 9)),
+ PMCMASK(e, (1 << 10)),
+ PMCMASK(m, (1 << 11)),
+ NULLMASK
+};
+
+static struct pmc_masks iap_snoopresponse_mask[] = {
+ PMCMASK(clean, (1 << 8)),
+ PMCMASK(hit, (1 << 9)),
+ PMCMASK(hitm, (1 << 11)),
+ NULLMASK
+};
+
+static struct pmc_masks iap_snooptype_mask[] = {
+ PMCMASK(cmp2s, (1 << 8)),
+ PMCMASK(cmp2i, (1 << 9)),
+ NULLMASK
+};
+
+static struct pmc_masks iap_transition_mask[] = {
+ PMCMASK(any, 0x00),
+ PMCMASK(frequency, 0x10),
+ NULLMASK
+};
+
+static int
+iap_allocate_pmc(enum pmc_event pe, char *ctrspec,
+ struct pmc_op_pmcallocate *pmc_config)
+{
+ char *e, *p, *q;
+ uint32_t cachestate, evmask;
+ int count, n;
+
+ pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE |
+ PMC_CAP_QUALIFIER);
+ pmc_config->pm_md.pm_iap.pm_iap_config = 0;
+
+ cachestate = evmask = 0;
+
+ /* Parse additional modifiers if present */
+ while ((p = strsep(&ctrspec, ",")) != NULL) {
+
+ n = 0;
+ if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) {
+ q = strchr(p, '=');
+ if (*++q == '\0') /* skip '=' */
+ return (-1);
+ count = strtol(q, &e, 0);
+ if (e == q || *e != '\0')
+ return (-1);
+ pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
+ pmc_config->pm_md.pm_iap.pm_iap_config |=
+ IAP_CMASK(count);
+ } else if (KWMATCH(p, IAP_KW_EDGE)) {
+ pmc_config->pm_caps |= PMC_CAP_EDGE;
+ } else if (KWMATCH(p, IAP_KW_INV)) {
+ pmc_config->pm_caps |= PMC_CAP_INVERT;
+ } else if (KWMATCH(p, IAP_KW_OS)) {
+ pmc_config->pm_caps |= PMC_CAP_SYSTEM;
+ } else if (KWMATCH(p, IAP_KW_USR)) {
+ pmc_config->pm_caps |= PMC_CAP_USER;
+ } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) {
+ pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY;
+ } else if (KWMATCH(p, IAP_KW_CORE)) {
+ n = pmc_parse_mask(iap_core_mask, p, &evmask);
+ if (n != 1)
+ return (-1);
+ } else if (KWMATCH(p, IAP_KW_AGENT)) {
+ n = pmc_parse_mask(iap_agent_mask, p, &evmask);
+ if (n != 1)
+ return (-1);
+ } else if (KWMATCH(p, IAP_KW_PREFETCH)) {
+ n = pmc_parse_mask(iap_prefetch_mask, p, &evmask);
+ if (n != 1)
+ return (-1);
+ } else if (KWMATCH(p, IAP_KW_CACHESTATE)) {
+ n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate);
+ } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE &&
+ KWMATCH(p, IAP_KW_TRANSITION)) {
+ n = pmc_parse_mask(iap_transition_mask, p, &evmask);
+ if (n != 1)
+ return (-1);
+ } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM ||
+ cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2) {
+ if (KWMATCH(p, IAP_KW_SNOOPRESPONSE)) {
+ n = pmc_parse_mask(iap_snoopresponse_mask, p,
+ &evmask);
+ } else if (KWMATCH(p, IAP_KW_SNOOPTYPE)) {
+ n = pmc_parse_mask(iap_snooptype_mask, p,
+ &evmask);
+ } else
+ return (-1);
+ } else
+ return (-1);
+
+ if (n < 0) /* Parsing failed. */
+ return (-1);
+ }
+
+ pmc_config->pm_md.pm_iap.pm_iap_config |= evmask;
+
+ /*
+ * If the event requires a 'cachestate' qualifier but was not
+ * specified by the user, use a sensible default.
+ */
+ switch (pe) {
+ case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */
+ case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */
+ case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */
+ case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */
+ case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */
+ case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */
+ case PMC_EV_IAP_EVENT_32H: /* Core */
+ case PMC_EV_IAP_EVENT_40H: /* Core */
+ case PMC_EV_IAP_EVENT_41H: /* Core */
+ case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */
+ case PMC_EV_IAP_EVENT_77H: /* Core */
+ if (cachestate == 0)
+ cachestate = (0xF << 8);
+ default:
+ break;
+ }
+
+ pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate;
+
+ return (0);
+}
+
+/*
* AMD K8 PMCs.
*
* These are very similar to AMD K7 PMCs, but support more kinds of
@@ -1704,9 +1982,9 @@ tsc_allocate_pmc(enum pmc_event pe, char *ctrspec,
/*
* Match an event name `name' with its canonical form.
- *
- * Matches are case insensitive and spaces, underscores and hyphen
- * characters are considered to match each other.
+ *
+ * Matches are case insensitive and spaces, periods, underscores and
+ * hyphen characters are considered to match each other.
*
* Returns 1 for a match, 0 otherwise.
*/
@@ -1722,13 +2000,14 @@ pmc_match_event_name(const char *name, const char *canonicalname)
for (; (nc = *n) && (cc = *c); n++, c++) {
- if (toupper(nc) == cc)
+ if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') &&
+ (cc == ' ' || cc == '_' || cc == '-' || cc == '.'))
continue;
- if ((nc == ' ' || nc == '_' || nc == '-') &&
- (cc == ' ' || cc == '_' || cc == '-'))
+ if (toupper(nc) == toupper(cc))
continue;
+
return (0);
}
@@ -1750,7 +2029,7 @@ pmc_match_event_class(const char *name,
{
size_t n;
const struct pmc_event_descr *ev;
-
+
ev = pcd->pm_evc_event_table;
for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++)
if (pmc_match_event_name(name, ev->pm_ev_name))
@@ -1815,8 +2094,8 @@ pmc_allocate(const char *ctrspec, enum pmc_mode mode,
* search for the event to the specified PMC class.
*/
ev = NULL;
- for (n = 0; n < pmc_event_class_table_size; n++) {
- pcd = &pmc_class_table[n];
+ for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) {
+ pcd = pmc_class_table[n];
if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) &&
strncasecmp(ctrname, pcd->pm_evc_name,
pcd->pm_evc_name_size) == 0) {
@@ -1833,8 +2112,8 @@ pmc_allocate(const char *ctrspec, enum pmc_mode mode,
* Otherwise, search for this event in all compatible PMC
* classes.
*/
- for (n = 0; ev == NULL && n < pmc_event_class_table_size; n++) {
- pcd = &pmc_class_table[n];
+ for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) {
+ pcd = pmc_class_table[n];
if (pmc_mdep_is_compatible_class(pcd->pm_evc_class))
ev = pmc_match_event_class(ctrname, pcd);
}
@@ -1974,6 +2253,31 @@ pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames,
switch (cl)
{
+ case PMC_CLASS_IAF:
+ ev = iaf_event_table;
+ count = PMC_EVENT_TABLE_SIZE(iaf);
+ break;
+ case PMC_CLASS_IAP:
+ /*
+ * Return the most appropriate set of event name
+ * spellings for the current CPU.
+ */
+ switch (cpu_info.pm_cputype) {
+ default:
+ case PMC_CPU_INTEL_ATOM:
+ ev = atom_event_table;
+ count = PMC_EVENT_TABLE_SIZE(atom);
+ break;
+ case PMC_CPU_INTEL_CORE:
+ ev = core_event_table;
+ count = PMC_EVENT_TABLE_SIZE(core);
+ break;
+ case PMC_CPU_INTEL_CORE2:
+ ev = core2_event_table;
+ count = PMC_EVENT_TABLE_SIZE(core2);
+ break;
+ }
+ break;
case PMC_CLASS_TSC:
ev = tsc_event_table;
count = PMC_EVENT_TABLE_SIZE(tsc);
@@ -2095,6 +2399,21 @@ pmc_init(void)
for (n = 0; n < cpu_info.pm_nclass; n++)
cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n];
+ pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE *
+ sizeof(struct pmc_class_descr *));
+
+ if (pmc_class_table == NULL)
+ return (-1);
+
+
+ /*
+ * Fill in the class table.
+ */
+ n = 0;
+#if defined(__amd64__) || defined(__i386__)
+ pmc_class_table[n++] = &tsc_class_table_descr;
+#endif
+
#define PMC_MDEP_INIT(C) do { \
pmc_mdep_event_aliases = C##_aliases; \
pmc_mdep_class_list = C##_pmc_classes; \
@@ -2107,26 +2426,46 @@ pmc_init(void)
#if defined(__i386__)
case PMC_CPU_AMD_K7:
PMC_MDEP_INIT(k7);
+ pmc_class_table[n] = &k7_class_table_descr;
break;
case PMC_CPU_INTEL_P5:
PMC_MDEP_INIT(p5);
+ pmc_class_table[n] = &p5_class_table_descr;
break;
case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */
case PMC_CPU_INTEL_PII: /* similar PMCs. */
case PMC_CPU_INTEL_PIII:
case PMC_CPU_INTEL_PM:
PMC_MDEP_INIT(p6);
+ pmc_class_table[n] = &p6_class_table_descr;
break;
#endif
#if defined(__amd64__) || defined(__i386__)
case PMC_CPU_AMD_K8:
PMC_MDEP_INIT(k8);
+ pmc_class_table[n] = &k8_class_table_descr;
+ break;
+ case PMC_CPU_INTEL_ATOM:
+ PMC_MDEP_INIT(atom);
+ pmc_class_table[n++] = &iaf_class_table_descr;
+ pmc_class_table[n] = &atom_class_table_descr;
+ break;
+ case PMC_CPU_INTEL_CORE:
+ PMC_MDEP_INIT(core);
+ pmc_class_table[n] = &core_class_table_descr;
+ break;
+ case PMC_CPU_INTEL_CORE2:
+ PMC_MDEP_INIT(core2);
+ pmc_class_table[n++] = &iaf_class_table_descr;
+ pmc_class_table[n] = &core2_class_table_descr;
break;
case PMC_CPU_INTEL_PIV:
PMC_MDEP_INIT(p4);
+ pmc_class_table[n] = &p4_class_table_descr;
break;
#endif
+
default:
/*
* Some kind of CPU this version of the library knows nothing
@@ -2195,12 +2534,32 @@ pmc_name_of_disposition(enum pmc_disp pd)
}
const char *
-pmc_name_of_event(enum pmc_event pe)
+_pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu)
{
const struct pmc_event_descr *ev, *evfence;
ev = evfence = NULL;
- if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) {
+ if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) {
+ ev = iaf_event_table;
+ evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf);
+ } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) {
+ switch (cpu) {
+ case PMC_CPU_INTEL_ATOM:
+ ev = atom_event_table;
+ evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom);
+ break;
+ case PMC_CPU_INTEL_CORE:
+ ev = core_event_table;
+ evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core);
+ break;
+ case PMC_CPU_INTEL_CORE2:
+ ev = core2_event_table;
+ evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2);
+ break;
+ default: /* Unknown CPU type. */
+ break;
+ }
+ } if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) {
ev = k7_event_table;
evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7);
} else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) {
@@ -2224,6 +2583,17 @@ pmc_name_of_event(enum pmc_event pe)
if (pe == ev->pm_ev_code)
return (ev->pm_ev_name);
+ return (NULL);
+}
+
+const char *
+pmc_name_of_event(enum pmc_event pe)
+{
+ const char *n;
+
+ if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL)
+ return (n);
+
errno = EINVAL;
return (NULL);
}
diff --git a/lib/libpmc/libpmcinternal.h b/lib/libpmc/libpmcinternal.h
new file mode 100644
index 0000000..b1c9c86
--- /dev/null
+++ b/lib/libpmc/libpmcinternal.h
@@ -0,0 +1,37 @@
+/*-
+ * 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 LIBPMC_INTERNAL_H
+#define LIBPMC_INTERNAL_H 1
+
+/*
+ * Prototypes.
+ */
+const char *_pmc_name_of_event(enum pmc_event _ev, enum pmc_cputype _cpu);
+
+#endif /* LIBPMC_INTERNAL_H */
diff --git a/lib/libpmc/pmclog.c b/lib/libpmc/pmclog.c
index ab054a5..51695b1 100644
--- a/lib/libpmc/pmclog.c
+++ b/lib/libpmc/pmclog.c
@@ -47,6 +47,8 @@ __FBSDID("$FreeBSD$");
#include <machine/pmc_mdep.h>
+#include "libpmcinternal.h"
+
#define PMCLOG_BUFFER_SIZE 4096
/*
@@ -363,7 +365,8 @@ pmclog_get_event(void *cookie, char **data, ssize_t *len,
PMCLOG_READ32(le,ev->pl_u.pl_a.pl_event);
PMCLOG_READ32(le,ev->pl_u.pl_a.pl_flags);
if ((ev->pl_u.pl_a.pl_evname =
- pmc_name_of_event(ev->pl_u.pl_a.pl_event)) == NULL)
+ _pmc_name_of_event(ev->pl_u.pl_a.pl_event, ps->ps_arch))
+ == NULL)
goto error;
break;
case PMCLOG_TYPE_PMCATTACH:
diff --git a/sys/amd64/include/pmc_mdep.h b/sys/amd64/include/pmc_mdep.h
index d4aea66..f8c26f2 100644
--- a/sys/amd64/include/pmc_mdep.h
+++ b/sys/amd64/include/pmc_mdep.h
@@ -40,6 +40,7 @@ struct pmc_mdep;
#endif
#include <dev/hwpmc/hwpmc_amd.h>
+#include <dev/hwpmc/hwpmc_core.h>
#include <dev/hwpmc/hwpmc_piv.h>
#include <dev/hwpmc/hwpmc_tsc.h>
@@ -51,8 +52,8 @@ struct pmc_mdep;
#define PMC_MDEP_CLASS_INDEX_TSC 0
#define PMC_MDEP_CLASS_INDEX_K8 1
#define PMC_MDEP_CLASS_INDEX_P4 1
-#define PMC_MDEP_CLASS_INDEX_IAF 1
-#define PMC_MDEP_CLASS_INDEX_IAP 2
+#define PMC_MDEP_CLASS_INDEX_IAP 1
+#define PMC_MDEP_CLASS_INDEX_IAF 2
/*
* On the amd64 platform we support the following PMCs.
@@ -66,6 +67,8 @@ struct pmc_mdep;
union pmc_md_op_pmcallocate {
struct pmc_md_amd_op_pmcallocate pm_amd;
+ struct pmc_md_iaf_op_pmcallocate pm_iaf;
+ struct pmc_md_iap_op_pmcallocate pm_iap;
struct pmc_md_p4_op_pmcallocate pm_p4;
uint64_t __pad[4];
};
@@ -78,6 +81,8 @@ union pmc_md_op_pmcallocate {
union pmc_md_pmc {
struct pmc_md_amd_pmc pm_amd;
+ struct pmc_md_iaf_pmc pm_iaf;
+ struct pmc_md_iap_pmc pm_iap;
struct pmc_md_p4_pmc pm_p4;
};
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index e7a1ec7..7910717 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -189,6 +189,7 @@ dev/hptrr/hptrr_osm_bsd.c optional hptrr
dev/hptrr/hptrr_config.c optional hptrr
dev/hwpmc/hwpmc_amd.c optional hwpmc
dev/hwpmc/hwpmc_intel.c optional hwpmc
+dev/hwpmc/hwpmc_core.c optional hwpmc
dev/hwpmc/hwpmc_piv.c optional hwpmc
dev/hwpmc/hwpmc_tsc.c optional hwpmc
dev/hwpmc/hwpmc_x86.c optional hwpmc
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 33da00e..cc4ae69 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -187,6 +187,7 @@ dev/hptrr/hptrr_osm_bsd.c optional hptrr
dev/hptrr/hptrr_config.c optional hptrr
dev/hwpmc/hwpmc_amd.c optional hwpmc
dev/hwpmc/hwpmc_intel.c optional hwpmc
+dev/hwpmc/hwpmc_core.c optional hwpmc
dev/hwpmc/hwpmc_pentium.c optional hwpmc
dev/hwpmc/hwpmc_piv.c optional hwpmc
dev/hwpmc/hwpmc_ppro.c optional hwpmc
diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c
new file mode 100644
index 0000000..f6214f5
--- /dev/null
+++ b/sys/dev/hwpmc/hwpmc_core.c
@@ -0,0 +1,1747 @@
+/*-
+ * 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 */
+#define IAP_F_CC2E (1 << 2) /* CPU: Core2 Extreme */
+#define IAP_F_CA (1 << 3) /* CPU: Atom */
+#define IAP_F_FM (1 << 4) /* Fixed mask */
+
+#define IAP_F_ALLCPUS (IAP_F_CC | IAP_F_CC2 | IAP_F_CC2E | IAP_F_CA)
+
+/* 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),
+ 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),
+ 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),
+ IAPDESCR(08H_02H, 0x08, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ 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),
+ IAPDESCR(09H_02H, 0x09, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ IAPDESCR(0CH_01H, 0x0C, 0x01, IAP_F_FM | IAP_F_CC2),
+ 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),
+ 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),
+ 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),
+ 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),
+
+ 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),
+ 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),
+
+ 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),
+ IAPDESCR(49H_02H, 0x49, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ 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),
+ IAPDESCR(80H_03H, 0x80, 0x03, IAP_F_FM | IAP_F_CA),
+
+ 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),
+
+ IAPDESCR(B1H_00H, 0xB1, 0x00, IAP_F_FM | IAP_F_ALLCPUS),
+ IAPDESCR(B1H_80H, 0xB1, 0x80, IAP_F_FM | IAP_F_CA),
+
+ 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),
+ IAPDESCR(C0H_02H, 0xC0, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ 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),
+ IAPDESCR(C2H_02H, 0xC2, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(C2H_04H, 0xC2, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ 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),
+ IAPDESCR(C3H_04H, 0xC3, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+
+ 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),
+ IAPDESCR(C4H_02H, 0xC4, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(C4H_04H, 0xC4, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ 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),
+ IAPDESCR(C7H_02H, 0xC7, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(C7H_04H, 0xC7, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(C7H_08H, 0xC7, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(C7H_10H, 0xC7, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ 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),
+ IAPDESCR(CBH_02H, 0xCB, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(CBH_04H, 0xCB, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(CBH_08H, 0xCB, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(CBH_10H, 0xCB, 0x10, IAP_F_FM | IAP_F_CC2),
+
+ 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),
+
+ 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),
+ IAPDESCR(D2H_02H, 0xD2, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(D2H_04H, 0xD2, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(D2H_08H, 0xD2, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ IAPDESCR(D2H_0FH, 0xD2, 0x0F, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
+ 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),
+ 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),
+ 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),
+
+ 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)
+};
+
+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_CC2E;
+ 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));
+
+ cc = core_pcpu[cpu];
+
+ for (ri = 0; ri < core_iap_npmc; ri++) {
+
+ if (!iap_pmc_has_overflowed(ri))
+ continue;
+
+ if ((pm = cc->pc_corepmcs[ri].phw_pmc) == NULL ||
+ !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+ 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);
+
+ 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);
+ }
+
+ KASSERT(found_interrupt,
+ ("[core,%d] no interrupting PMCs were found", __LINE__));
+
+ /*
+ * 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 0000000..0c4ee5b
--- /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_intel.c b/sys/dev/hwpmc/hwpmc_intel.c
index 80916c6..7532559 100644
--- a/sys/dev/hwpmc/hwpmc_intel.c
+++ b/sys/dev/hwpmc/hwpmc_intel.c
@@ -88,20 +88,24 @@ pmc_intel_initialize(void)
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 ((cpu_id & 0xF0) >> 4) { /* model number field */
+ 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 0x6: case 0x16:
cputype = PMC_CPU_INTEL_CL;
break;
case 0x7: case 0x8: case 0xA: case 0xB:
@@ -110,12 +114,26 @@ pmc_intel_initialize(void)
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;
}
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;
@@ -144,6 +162,14 @@ pmc_intel_initialize(void)
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:
+ error = pmc_core_initialize(pmc_mdep, ncpus);
+ break;
/*
* Intel Pentium 4 Processors, and P4/EMT64 processors.
@@ -184,7 +210,7 @@ pmc_intel_initialize(void)
KASSERT(pmc_mdep->pmd_npmc == TSC_NPMCS + PENTIUM_NPMCS,
("[intel,%d] incorrect npmc count %d", __LINE__,
- md->pmd_npmc));
+ pmc_mdep->pmd_npmc));
break;
#endif
@@ -209,6 +235,12 @@ pmc_intel_finalize(struct pmc_mdep *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:
+ pmc_core_finalize(md);
+ break;
+
case PMC_CPU_INTEL_PIV:
pmc_p4_finalize(md);
break;
diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c
index 353e333..df43152 100644
--- a/sys/dev/hwpmc/hwpmc_logging.c
+++ b/sys/dev/hwpmc/hwpmc_logging.c
@@ -287,8 +287,9 @@ pmclog_loop(void *arg)
wakeup_one(po->po_kthread);
}
- (void) msleep(po, &pmc_kthread_mtx, PWAIT,
- "pmcloop", 0);
+
+ (void) msleep(po, &pmc_kthread_mtx,
+ PWAIT, "pmcloop", 0);
continue;
}
@@ -543,7 +544,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;
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index d0474df..a38921f 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -128,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.
@@ -2718,7 +2718,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);
@@ -3966,7 +3966,7 @@ static void
pmc_process_samples(int cpu)
{
struct pmc *pm;
- int adjri, n, ri;
+ int adjri, n;
struct thread *td;
struct pmc_owner *po;
struct pmc_sample *ps;
@@ -4066,7 +4066,6 @@ pmc_process_samples(int cpu)
continue;
pm->pm_stalled = 0;
- ri = PMC_TO_ROWINDEX(pm);
(*pcd->pcd_start_pmc)(cpu, adjri);
}
}
@@ -4458,7 +4457,7 @@ pmc_initialize(void)
md->pmd_npmc * sizeof(struct pmc_hw *), M_PMC,
M_WAITOK|M_ZERO);
if (md->pmd_pcpu_init)
- error = md->pmd_pcpu_init(cpu);
+ 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);
}
@@ -4655,7 +4654,7 @@ pmc_cleanup(void)
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(cpu);
+ md->pmd_pcpu_fini(md, cpu);
}
pmc_md_finalize(md);
diff --git a/sys/dev/hwpmc/pmc_events.h b/sys/dev/hwpmc/pmc_events.h
index 78a0c7b..10fcd9e 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)
*
*/
@@ -69,6 +69,7 @@ __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]
@@ -327,9 +328,9 @@ __PMC_EV(K8, NB_HT_BUS2_BANDWIDTH)
/*
- * Intel Pentium and Pentium MMX Events, from the "Intel 64 and IA-32
- * Intel(R) Architectures Software Developer's Manual, Volume 3B:
- * System Programming Guide, Part 2, August 2007".
+ * 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) \
@@ -412,8 +413,965 @@ __PMC_EV(P5, STALL_ON_MMX_INSTRUCTION_WRITE_TO_E_OR_M_STATE_LINE)
#define PMC_EV_P5_LAST \
PMC_EV_P5_STALL_ON_MMX_INSTRUCTION_WRITE_TO_E_OR_M_STATE_LINE
-#define __PMC_EV_IAF() /* Intel architectural fixed function */
-#define __PMC_EV_IAP() /* Intel architectural programmable */
+/*
+ * 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
+
+/*
+ * 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)
+
+#define PMC_EV_IAP_FIRST PMC_EV_IAP_EVENT_02H_81H
+#define PMC_EV_IAP_LAST PMC_EV_IAP_EVENT_F8H_00H
+
+/*
+ * 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)
/* timestamp counters. */
#define __PMC_EV_TSC() \
diff --git a/sys/i386/include/pmc_mdep.h b/sys/i386/include/pmc_mdep.h
index 720f1f3..63d5f8b 100644
--- a/sys/i386/include/pmc_mdep.h
+++ b/sys/i386/include/pmc_mdep.h
@@ -52,6 +52,7 @@ struct pmc_mdep;
*/
#include <dev/hwpmc/hwpmc_amd.h> /* K7 and K8 */
+#include <dev/hwpmc/hwpmc_core.h>
#include <dev/hwpmc/hwpmc_piv.h>
#include <dev/hwpmc/hwpmc_ppro.h>
#include <dev/hwpmc/hwpmc_pentium.h>
@@ -68,8 +69,8 @@ struct pmc_mdep;
#define PMC_MDEP_CLASS_INDEX_P4 1
#define PMC_MDEP_CLASS_INDEX_P5 1
#define PMC_MDEP_CLASS_INDEX_P6 1
-#define PMC_MDEP_CLASS_INDEX_IAF 1
-#define PMC_MDEP_CLASS_INDEX_IAP 2
+#define PMC_MDEP_CLASS_INDEX_IAP 1
+#define PMC_MDEP_CLASS_INDEX_IAF 2
/*
* Architecture specific extensions to <sys/pmc.h> structures.
@@ -77,9 +78,11 @@ struct pmc_mdep;
union pmc_md_op_pmcallocate {
struct pmc_md_amd_op_pmcallocate pm_amd;
- struct pmc_md_ppro_op_pmcallocate pm_ppro;
- struct pmc_md_pentium_op_pmcallocate pm_pentium;
+ struct pmc_md_iaf_op_pmcallocate pm_iaf;
+ struct pmc_md_iap_op_pmcallocate pm_iap;
struct pmc_md_p4_op_pmcallocate pm_p4;
+ struct pmc_md_pentium_op_pmcallocate pm_pentium;
+ struct pmc_md_ppro_op_pmcallocate pm_ppro;
uint64_t __pad[4];
};
@@ -92,9 +95,11 @@ union pmc_md_op_pmcallocate {
/* MD extension for 'struct pmc' */
union pmc_md_pmc {
struct pmc_md_amd_pmc pm_amd;
- struct pmc_md_ppro_pmc pm_ppro;
- struct pmc_md_pentium_pmc pm_pentium;
+ struct pmc_md_iaf_pmc pm_iaf;
+ struct pmc_md_iap_pmc pm_iap;
struct pmc_md_p4_pmc pm_p4;
+ struct pmc_md_pentium_pmc pm_pentium;
+ struct pmc_md_ppro_pmc pm_ppro;
};
struct pmc;
diff --git a/sys/modules/hwpmc/Makefile b/sys/modules/hwpmc/Makefile
index 350d361..0a696a1 100644
--- a/sys/modules/hwpmc/Makefile
+++ b/sys/modules/hwpmc/Makefile
@@ -9,7 +9,8 @@ KMOD= hwpmc
SRCS= hwpmc_mod.c hwpmc_logging.c vnode_if.h
.if ${MACHINE_ARCH} == "amd64"
-SRCS+= hwpmc_amd.c hwpmc_intel.c hwpmc_piv.c hwpmc_tsc.c hwpmc_x86.c
+SRCS+= hwpmc_amd.c hwpmc_core.c hwpmc_intel.c hwpmc_piv.c hwpmc_tsc.c
+SRCS+= hwpmc_x86.c
SRCS+= device_if.h bus_if.h
.endif
@@ -18,8 +19,8 @@ SRCS+= hwpmc_arm.c
.endif
.if ${MACHINE_ARCH} == "i386"
-SRCS+= hwpmc_amd.c hwpmc_intel.c hwpmc_piv.c hwpmc_ppro.c hwpmc_pentium.c
-SRCS+= hwpmc_tsc.c hwpmc_x86.c
+SRCS+= hwpmc_amd.c hwpmc_core.c hwpmc_intel.c hwpmc_piv.c hwpmc_ppro.c
+SRCS+= hwpmc_pentium.c hwpmc_tsc.c hwpmc_x86.c
SRCS+= device_if.h bus_if.h
.endif
diff --git a/sys/sys/param.h b/sys/sys/param.h
index e5721f1..0894051 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -57,7 +57,7 @@
* is created, otherwise 1.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 800054 /* Master, propagated to newvers */
+#define __FreeBSD_version 800055 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>
diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h
index 84c0a13..4afb0ab 100644
--- a/sys/sys/pmc.h
+++ b/sys/sys/pmc.h
@@ -55,7 +55,7 @@
* The patch version is incremented for every bug fix.
*/
#define PMC_VERSION_MAJOR 0x03
-#define PMC_VERSION_MINOR 0x00
+#define PMC_VERSION_MINOR 0x01
#define PMC_VERSION_PATCH 0x0000
#define PMC_VERSION (PMC_VERSION_MAJOR << 24 | \
@@ -82,6 +82,7 @@
__PMC_CPU(INTEL_PIV, 0x86, "Intel Pentium IV") \
__PMC_CPU(INTEL_CORE, 0x87, "Intel Core Solo/Duo") \
__PMC_CPU(INTEL_CORE2, 0x88, "Intel Core2") \
+ __PMC_CPU(INTEL_CORE2EXTREME, 0x89, "Intel Core2 Extreme") \
__PMC_CPU(INTEL_ATOM, 0x8A, "Intel Atom")
enum pmc_cputype {
@@ -920,8 +921,8 @@ struct pmc_mdep {
*/
/* per-cpu initialization and finalization */
- int (*pmd_pcpu_init)(int _cpu); /* initialization */
- int (*pmd_pcpu_fini)(int _cpu); /* finalization */
+ int (*pmd_pcpu_init)(struct pmc_mdep *_md, int _cpu);
+ int (*pmd_pcpu_fini)(struct pmc_mdep *_md, int _cpu);
/* thread context switch in/out */
int (*pmd_switch_in)(struct pmc_cpu *_p, struct pmc_process *_pp);
@@ -942,7 +943,6 @@ struct pmc_mdep {
*/
extern struct pmc_cpu **pmc_pcpu;
-extern struct pmc_mdep *md;
/* driver statistics */
extern struct pmc_op_getdriverstats pmc_stats;
diff --git a/sys/sys/pmclog.h b/sys/sys/pmclog.h
index 6878a59..44c5c6c 100644
--- a/sys/sys/pmclog.h
+++ b/sys/sys/pmclog.h
@@ -239,7 +239,8 @@ union pmclog_entry { /* only used to size scratch areas */
/*
* Prototypes
*/
-int pmclog_configure_log(struct pmc_owner *_po, int _logfd);
+int pmclog_configure_log(struct pmc_mdep *_md, struct pmc_owner *_po,
+ int _logfd);
int pmclog_deconfigure_log(struct pmc_owner *_po);
int pmclog_flush(struct pmc_owner *_po);
void pmclog_initialize(void);
OpenPOWER on IntegriCloud