| /* |
| * Copyright (c) 2009 Google, Inc |
| * Contributed by Stephane Eranian <eranian@gmail.com> |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy |
| * of this software and associated documentation files (the "Software"), to deal |
| * in the Software without restriction, including without limitation the rights |
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
| * of the Software, and to permit persons to whom the Software is furnished to do so, |
| * subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in all |
| * copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
| * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A |
| * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
| * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
| * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE |
| * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| * |
| * This file is part of libpfm, a performance monitoring support library for |
| * applications on Linux. |
| */ |
| #ifndef __PFMLIB_INTEL_X86_PRIV_H__ |
| #define __PFMLIB_INTEL_X86_PRIV_H__ |
| |
| /* |
| * This file contains the definitions used for all Intel X86 processors |
| */ |
| |
| |
| /* |
| * maximum number of unit masks groups per event |
| */ |
| #define INTEL_X86_NUM_GRP 8 |
| #define INTEL_X86_MAX_FILTERS 3 |
| |
| /* |
| * unit mask description |
| */ |
| typedef struct { |
| const char *uname; /* unit mask name */ |
| const char *udesc; /* unit umask description */ |
| const char *uequiv;/* name of event from which this one is derived, NULL if none */ |
| uint64_t ucntmsk;/* supported counters for umask (if set, supersedes cntmsk) */ |
| uint64_t ucode; /* unit mask code */ |
| uint64_t ufilters[INTEL_X86_MAX_FILTERS]; /* extra encoding for event */ |
| unsigned int uflags; /* unit mask flags */ |
| unsigned int umodel; /* only available on this PMU model */ |
| unsigned int grpid; /* unit mask group id */ |
| unsigned int modhw; /* hardwired modifiers, cannot be changed */ |
| unsigned int umodmsk_req; /* bitmask of required modifiers */ |
| } intel_x86_umask_t; |
| |
| #define INTEL_X86_MAX_GRPID (~0U) |
| |
| /* |
| * event description |
| */ |
| typedef struct { |
| const char *name; /* event name */ |
| const char *desc; /* event description */ |
| const char *equiv; /* name of event from which this one is derived, NULL if none */ |
| uint64_t cntmsk; /* supported counters */ |
| unsigned int code; /* event code */ |
| unsigned int numasks;/* number of umasks */ |
| unsigned int flags; /* flags */ |
| unsigned int modmsk; /* bitmask of modifiers for this event */ |
| unsigned int modmsk_req; /* bitmask of required modifiers */ |
| unsigned int ngrp; /* number of unit masks groups */ |
| const intel_x86_umask_t *umasks; /* umask desc */ |
| } intel_x86_entry_t; |
| |
| /* |
| * pme_flags value (event and unit mask) |
| */ |
| #define INTEL_X86_NCOMBO 0x01 /* unit masks within group cannot be combined */ |
| #define INTEL_X86_FALLBACK_GEN 0x02 /* fallback from fixed to generic counter possible */ |
| #define INTEL_X86_PEBS 0x04 /* event supports PEBS or at least one umask supports PEBS */ |
| #define INTEL_X86_DFL 0x08 /* unit mask is default choice */ |
| #define INTEL_X86_GRP_EXCL 0x10 /* only one unit mask group can be selected */ |
| #define INTEL_X86_NHM_OFFCORE 0x20 /* Nehalem/Westmere offcore_response */ |
| #define INTEL_X86_EXCL_GRP_GT 0x40 /* exclude use of grp with id > own grp */ |
| #define INTEL_X86_FIXED 0x80 /* fixed counter only event */ |
| #define INTEL_X86_NO_AUTOENCODE 0x100 /* does not support auto encoding validation */ |
| #define INTEL_X86_CODE_OVERRIDE 0x200 /* umask overrides event code */ |
| #define INTEL_X86_LDLAT 0x400 /* needs load latency modifier (ldlat) */ |
| #define INTEL_X86_GRP_DFL_NONE 0x800 /* ok if umask group defaults to no umask */ |
| |
| typedef union pfm_intel_x86_reg { |
| unsigned long long val; /* complete register value */ |
| struct { |
| unsigned long sel_event_select:8; /* event mask */ |
| unsigned long sel_unit_mask:8; /* unit mask */ |
| unsigned long sel_usr:1; /* user level */ |
| unsigned long sel_os:1; /* system level */ |
| unsigned long sel_edge:1; /* edge detec */ |
| unsigned long sel_pc:1; /* pin control */ |
| unsigned long sel_int:1; /* enable APIC intr */ |
| unsigned long sel_anythr:1; /* measure any thread */ |
| unsigned long sel_en:1; /* enable */ |
| unsigned long sel_inv:1; /* invert counter mask */ |
| unsigned long sel_cnt_mask:8; /* counter mask */ |
| unsigned long sel_intx:1; /* only in tx region */ |
| unsigned long sel_intxcp:1; /* excl. aborted tx region */ |
| unsigned long sel_res2:30; |
| } perfevtsel; |
| |
| struct { |
| unsigned long usel_event:8; /* event select */ |
| unsigned long usel_umask:8; /* event unit mask */ |
| unsigned long usel_res1:1; /* reserved */ |
| unsigned long usel_occ:1; /* occupancy reset */ |
| unsigned long usel_edge:1; /* edge detection */ |
| unsigned long usel_res2:1; /* reserved */ |
| unsigned long usel_int:1; /* PMI enable */ |
| unsigned long usel_res3:1; /* reserved */ |
| unsigned long usel_en:1; /* enable */ |
| unsigned long usel_inv:1; /* invert */ |
| unsigned long usel_cnt_mask:8; /* counter mask */ |
| unsigned long usel_res4:32; /* reserved */ |
| } nhm_unc; |
| |
| struct { |
| unsigned long usel_en:1; /* enable */ |
| unsigned long usel_res1:1; |
| unsigned long usel_int:1; /* PMI enable */ |
| unsigned long usel_res2:32; |
| unsigned long usel_res3:29; |
| } nhm_unc_fixed; |
| |
| struct { |
| unsigned long cpl_eq0:1; /* filter out branches at pl0 */ |
| unsigned long cpl_neq0:1; /* filter out branches at pl1-pl3 */ |
| unsigned long jcc:1; /* filter out condition branches */ |
| unsigned long near_rel_call:1; /* filter out near relative calls */ |
| unsigned long near_ind_call:1; /* filter out near indirect calls */ |
| unsigned long near_ret:1; /* filter out near returns */ |
| unsigned long near_ind_jmp:1; /* filter out near unconditional jmp/calls */ |
| unsigned long near_rel_jmp:1; /* filter out near uncoditional relative jmp */ |
| unsigned long far_branch:1; /* filter out far branches */ |
| unsigned long reserved1:23; /* reserved */ |
| unsigned long reserved2:32; /* reserved */ |
| } nhm_lbr_select; |
| } pfm_intel_x86_reg_t; |
| |
| #define INTEL_X86_ATTR_K 0 /* kernel (0) */ |
| #define INTEL_X86_ATTR_U 1 /* user (1, 2, 3) */ |
| #define INTEL_X86_ATTR_E 2 /* edge */ |
| #define INTEL_X86_ATTR_I 3 /* invert */ |
| #define INTEL_X86_ATTR_C 4 /* counter mask */ |
| #define INTEL_X86_ATTR_T 5 /* any thread */ |
| #define INTEL_X86_ATTR_LDLAT 6 /* load latency threshold */ |
| #define INTEL_X86_ATTR_INTX 7 /* in transaction */ |
| #define INTEL_X86_ATTR_INTXCP 8 /* not aborted transaction */ |
| |
| #define _INTEL_X86_ATTR_U (1 << INTEL_X86_ATTR_U) |
| #define _INTEL_X86_ATTR_K (1 << INTEL_X86_ATTR_K) |
| #define _INTEL_X86_ATTR_I (1 << INTEL_X86_ATTR_I) |
| #define _INTEL_X86_ATTR_E (1 << INTEL_X86_ATTR_E) |
| #define _INTEL_X86_ATTR_C (1 << INTEL_X86_ATTR_C) |
| #define _INTEL_X86_ATTR_T (1 << INTEL_X86_ATTR_T) |
| #define _INTEL_X86_ATTR_INTX (1 << INTEL_X86_ATTR_INTX) |
| #define _INTEL_X86_ATTR_INTXCP (1 << INTEL_X86_ATTR_INTXCP) |
| #define _INTEL_X86_ATTR_LDLAT (1 << INTEL_X86_ATTR_LDLAT) |
| |
| #define INTEL_X86_ATTRS \ |
| (_INTEL_X86_ATTR_I|_INTEL_X86_ATTR_E|_INTEL_X86_ATTR_C|_INTEL_X86_ATTR_U|_INTEL_X86_ATTR_K) |
| |
| #define INTEL_V1_ATTRS INTEL_X86_ATTRS |
| #define INTEL_V2_ATTRS INTEL_X86_ATTRS |
| #define INTEL_FIXED2_ATTRS (_INTEL_X86_ATTR_U|_INTEL_X86_ATTR_K) |
| #define INTEL_FIXED3_ATTRS (INTEL_FIXED2_ATTRS|_INTEL_X86_ATTR_T) |
| #define INTEL_V3_ATTRS (INTEL_V2_ATTRS|_INTEL_X86_ATTR_T) |
| #define INTEL_V4_ATTRS (INTEL_V3_ATTRS | _INTEL_X86_ATTR_INTX | _INTEL_X86_ATTR_INTXCP) |
| |
| /* let's define some handy shortcuts! */ |
| #define sel_event_select perfevtsel.sel_event_select |
| #define sel_unit_mask perfevtsel.sel_unit_mask |
| #define sel_usr perfevtsel.sel_usr |
| #define sel_os perfevtsel.sel_os |
| #define sel_edge perfevtsel.sel_edge |
| #define sel_pc perfevtsel.sel_pc |
| #define sel_int perfevtsel.sel_int |
| #define sel_en perfevtsel.sel_en |
| #define sel_inv perfevtsel.sel_inv |
| #define sel_cnt_mask perfevtsel.sel_cnt_mask |
| #define sel_anythr perfevtsel.sel_anythr |
| #define sel_intx perfevtsel.sel_intx |
| #define sel_intxcp perfevtsel.sel_intxcp |
| |
| /* |
| * shift relative to start of register |
| */ |
| #define INTEL_X86_EDGE_BIT 18 |
| #define INTEL_X86_ANY_BIT 21 |
| #define INTEL_X86_INV_BIT 23 |
| #define INTEL_X86_CMASK_BIT 24 |
| |
| #define INTEL_X86_MOD_EDGE (1 << INTEL_X86_EDGE_BIT) |
| #define INTEL_X86_MOD_ANY (1 << INTEL_X86_ANY_BIT) |
| #define INTEL_X86_MOD_INV (1 << INTEL_X86_INV_BIT) |
| |
| /* intel x86 core PMU supported plm */ |
| #define INTEL_X86_PLM (PFM_PLM0|PFM_PLM3) |
| |
| /* |
| * Intel x86 specific pmu flags (pmu->flags 16 MSB) |
| */ |
| #define INTEL_X86_PMU_FL_ECMASK 0x10000 /* edge requires cmask >=1 */ |
| |
| /* |
| * default ldlat value for PEBS-LL events. Used when ldlat= is missing |
| */ |
| #define INTEL_X86_LDLAT_DEFAULT 3 /* default ldlat value in core cycles */ |
| |
| typedef struct { |
| unsigned int version:8; |
| unsigned int num_cnt:8; |
| unsigned int cnt_width:8; |
| unsigned int ebx_length:8; |
| } intel_x86_pmu_eax_t; |
| |
| typedef struct { |
| unsigned int num_cnt:6; |
| unsigned int cnt_width:6; |
| unsigned int reserved:20; |
| } intel_x86_pmu_edx_t; |
| |
| typedef struct { |
| unsigned int no_core_cycle:1; |
| unsigned int no_inst_retired:1; |
| unsigned int no_ref_cycle:1; |
| unsigned int no_llc_ref:1; |
| unsigned int no_llc_miss:1; |
| unsigned int no_br_retired:1; |
| unsigned int no_br_mispred_retired:1; |
| unsigned int reserved:25; |
| } intel_x86_pmu_ebx_t; |
| |
| typedef struct { |
| int model; |
| int family; /* 0 means nothing detected yet */ |
| int arch_version; |
| int stepping; |
| } pfm_intel_x86_config_t; |
| |
| extern pfm_intel_x86_config_t pfm_intel_x86_cfg; |
| |
| extern const pfmlib_attr_desc_t intel_x86_mods[]; |
| |
| static inline int |
| intel_x86_eflag(void *this, int idx, int flag) |
| { |
| const intel_x86_entry_t *pe = this_pe(this); |
| return !!(pe[idx].flags & flag); |
| } |
| |
| static inline int |
| is_model_umask(void *this, int pidx, int attr) |
| { |
| pfmlib_pmu_t *pmu = this; |
| const intel_x86_entry_t *pe = this_pe(this); |
| const intel_x86_entry_t *ent; |
| unsigned int model; |
| |
| ent = pe + pidx; |
| model = ent->umasks[attr].umodel; |
| |
| return model == 0 || model == pmu->pmu; |
| } |
| |
| static inline int |
| intel_x86_uflag(void *this, int idx, int attr, int flag) |
| { |
| const intel_x86_entry_t *pe = this_pe(this); |
| return !!(pe[idx].umasks[attr].uflags & flag); |
| } |
| |
| static inline unsigned int |
| intel_x86_num_umasks(void *this, int pidx) |
| { |
| pfmlib_pmu_t *pmu = this; |
| const intel_x86_entry_t *pe = this_pe(this); |
| unsigned int i, n = 0, model; |
| |
| /* |
| * some umasks may be model specific |
| */ |
| for (i = 0; i < pe[pidx].numasks; i++) { |
| model = pe[pidx].umasks[i].umodel; |
| if (model && model != pmu->pmu) |
| continue; |
| n++; |
| } |
| return n; |
| } |
| |
| /* |
| * find actual index of umask based on attr_idx |
| */ |
| static inline int |
| intel_x86_attr2umask(void *this, int pidx, int attr_idx) |
| { |
| const intel_x86_entry_t *pe = this_pe(this); |
| unsigned int i; |
| |
| for (i = 0; i < pe[pidx].numasks; i++) { |
| |
| if (!is_model_umask(this, pidx, i)) |
| continue; |
| |
| if (attr_idx == 0) |
| break; |
| attr_idx--; |
| } |
| return i; |
| } |
| |
| extern int pfm_intel_x86_detect(void); |
| extern int pfm_intel_x86_add_defaults(void *this, pfmlib_event_desc_t *e, unsigned int msk, uint64_t *umask, unsigned int max_grpid); |
| |
| extern int pfm_intel_x86_event_is_valid(void *this, int pidx); |
| extern int pfm_intel_x86_get_encoding(void *this, pfmlib_event_desc_t *e); |
| extern int pfm_intel_x86_get_event_first(void *this); |
| extern int pfm_intel_x86_get_event_next(void *this, int idx); |
| extern int pfm_intel_x86_get_event_umask_first(void *this, int idx); |
| extern int pfm_intel_x86_get_event_umask_next(void *this, int idx, int attr); |
| extern int pfm_intel_x86_validate_table(void *this, FILE *fp); |
| extern int pfm_intel_x86_get_event_attr_info(void *this, int idx, int attr_idx, pfm_event_attr_info_t *info); |
| extern int pfm_intel_x86_get_event_info(void *this, int idx, pfm_event_info_t *info); |
| extern int pfm_intel_x86_valid_pebs(pfmlib_event_desc_t *e); |
| extern int pfm_intel_x86_perf_event_encoding(pfmlib_event_desc_t *e, void *data); |
| extern int pfm_intel_x86_perf_detect(void *this); |
| extern unsigned int pfm_intel_x86_get_event_nattrs(void *this, int pidx); |
| extern int intel_x86_attr2mod(void *this, int pidx, int attr_idx); |
| |
| extern int pfm_intel_x86_get_perf_encoding(void *this, pfmlib_event_desc_t *e); |
| extern int pfm_intel_nhm_unc_get_perf_encoding(void *this, pfmlib_event_desc_t *e); |
| extern void pfm_intel_x86_perf_validate_pattrs(void *this, pfmlib_event_desc_t *e); |
| extern int pfm_intel_x86_can_auto_encode(void *this, int pidx, int uidx); |
| extern int pfm_intel_x86_model_detect(void *this); |
| |
| #endif /* __PFMLIB_INTEL_X86_PRIV_H__ */ |