/* * Copyright (c) 2001-2007 Hewlett-Packard Development Company, L.P. * Contributed by Stephane Eranian * * 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. */ #ifndef __PFMLIB_H__ #define __PFMLIB_H__ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #define PFMLIB_VERSION (3 << 16 | 9) #define PFMLIB_MAJ_VERSION(v) ((v)>>16) #define PFMLIB_MIN_VERSION(v) ((v) & 0xffff) /* * Maximum number of PMCs/PMDs supported by the library (especially bitmasks) */ #define PFMLIB_MAX_PMCS 512 /* maximum number of PMCS supported by the library */ #define PFMLIB_MAX_PMDS 512 /* maximum number of PMDS supported by the library */ /* * privilege level mask (mask can be combined) * The interpretation of the level is specific to each * architecture. Checkout the architecture specific header * file for more details. */ #define PFM_PLM0 0x1 /* priv level 0 */ #define PFM_PLM1 0x2 /* priv level 1 */ #define PFM_PLM2 0x4 /* priv level 2 */ #define PFM_PLM3 0x8 /* priv level 3 */ /* * type used to describe a set of bits in the mask (container type) */ typedef unsigned long pfmlib_regmask_bits_t; /* * how many elements do we need to represent all the PMCs and PMDs (rounded up) */ #if PFMLIB_MAX_PMCS > PFMLIB_MAX_PMDS #define PFMLIB_REG_MAX PFMLIB_MAX_PMCS #else #define PFMLIB_REG_MAX PFMLIB_MAX_PMDS #endif #ifndef SWIG #define __PFMLIB_REG_BV_BITS (sizeof(pfmlib_regmask_bits_t)<<3) #define PFMLIB_BVSIZE(x) (((x)+(__PFMLIB_REG_BV_BITS)-1) / __PFMLIB_REG_BV_BITS) #define PFMLIB_REG_BV PFMLIB_BVSIZE(PFMLIB_REG_MAX) #endif typedef struct { pfmlib_regmask_bits_t bits[PFMLIB_REG_BV]; } pfmlib_regmask_t; #define PFMLIB_MAX_MASKS_PER_EVENT 48 /* maximum number of unit masks per event */ /* * event definition for pfmlib_input_param_t */ typedef struct { unsigned int event; /* event descriptor */ unsigned int plm; /* event privilege level mask */ unsigned long flags; /* per-event flag */ unsigned int unit_masks[PFMLIB_MAX_MASKS_PER_EVENT]; /* unit-mask identifiers */ unsigned int num_masks; /* number of masks specified in 'unit_masks' */ unsigned long reserved[2]; /* for future use */ } pfmlib_event_t; /* * generic register definition */ typedef struct { unsigned long long reg_value; /* register value */ unsigned long long reg_addr; /* hardware register addr or index */ unsigned int reg_num; /* logical register index (perfmon2) */ unsigned int reg_reserved1; /* for future use */ unsigned long reg_alt_addr; /* alternate hw register addr of index */ } pfmlib_reg_t; /* * library generic input parameters for pfm_dispatch_event() */ typedef struct { unsigned int pfp_event_count; /* how many events specified (input) */ unsigned int pfp_dfl_plm; /* default priv level : used when event.plm==0 */ unsigned int pfp_flags; /* set of flags for all events used when event.flags==0*/ unsigned int reserved1; /* for future use */ pfmlib_event_t pfp_events[PFMLIB_MAX_PMCS]; /* event descriptions */ pfmlib_regmask_t pfp_unavail_pmcs; /* bitmask of unavailable PMC registers */ unsigned long reserved[6]; /* for future use */ } pfmlib_input_param_t; /* * pfp_flags possible values (apply to all events) */ #define PFMLIB_PFP_SYSTEMWIDE 0x1 /* indicate monitors will be used in a system-wide session */ /* * library generic output parameters for pfm_dispatch_event() */ typedef struct { unsigned int pfp_pmc_count; /* number of entries in pfp_pmcs */ unsigned int pfp_pmd_count; /* number of entries in pfp_pmds */ pfmlib_reg_t pfp_pmcs[PFMLIB_MAX_PMCS]; /* PMC registers number and values */ pfmlib_reg_t pfp_pmds[PFMLIB_MAX_PMDS]; /* PMD registers numbers */ unsigned long reserved[7]; /* for future use */ } pfmlib_output_param_t; /* * library configuration options */ typedef struct { unsigned int pfm_debug:1; /* set in debug mode */ unsigned int pfm_verbose:1; /* set in verbose mode */ unsigned int pfm_reserved:30;/* for future use */ } pfmlib_options_t; /* * special data type for libpfm error value used to help * with Python support and in particular for SWIG. By using * a specific type we can detect library calls and trap errors * in one SWIG statement as opposed to having to keep track of * each call individually. Programs can use 'int' safely for * the return value. */ typedef int pfm_err_t; /* error if !PFMLIB_SUCCESS */ extern pfm_err_t pfm_set_options(pfmlib_options_t *opt); extern pfm_err_t pfm_initialize(void); extern pfm_err_t pfm_list_supported_pmus(int (*pf)(const char *fmt,...)); extern pfm_err_t pfm_get_pmu_name(char *name, int maxlen); extern pfm_err_t pfm_get_pmu_type(int *type); extern pfm_err_t pfm_get_pmu_name_bytype(int type, char *name, size_t maxlen); extern pfm_err_t pfm_is_pmu_supported(int type); extern pfm_err_t pfm_force_pmu(int type); /* * pfm_find_event_byname() is obsolete, use pfm_find_event */ extern pfm_err_t pfm_find_event(const char *str, unsigned int *idx); extern pfm_err_t pfm_find_event_byname(const char *name, unsigned int *idx); extern pfm_err_t pfm_find_event_bycode(int code, unsigned int *idx); extern pfm_err_t pfm_find_event_bycode_next(int code, unsigned int start, unsigned int *next); extern pfm_err_t pfm_find_event_mask(unsigned int event_idx, const char *str, unsigned int *mask_idx); extern pfm_err_t pfm_find_full_event(const char *str, pfmlib_event_t *e); extern pfm_err_t pfm_get_max_event_name_len(size_t *len); extern pfm_err_t pfm_get_num_events(unsigned int *count); extern pfm_err_t pfm_get_num_event_masks(unsigned int event_idx, unsigned int *count); extern pfm_err_t pfm_get_event_name(unsigned int idx, char *name, size_t maxlen); extern pfm_err_t pfm_get_full_event_name(pfmlib_event_t *e, char *name, size_t maxlen); extern pfm_err_t pfm_get_event_code(unsigned int idx, int *code); extern pfm_err_t pfm_get_event_mask_code(unsigned int idx, unsigned int mask_idx, unsigned int *code); extern pfm_err_t pfm_get_event_counters(unsigned int idx, pfmlib_regmask_t *counters); extern pfm_err_t pfm_get_event_description(unsigned int idx, char **str); extern pfm_err_t pfm_get_event_code_counter(unsigned int idx, unsigned int cnt, int *code); extern pfm_err_t pfm_get_event_mask_name(unsigned int event_idx, unsigned int mask_idx, char *name, size_t maxlen); extern pfm_err_t pfm_get_event_mask_description(unsigned int event_idx, unsigned int mask_idx, char **desc); extern pfm_err_t pfm_dispatch_events(pfmlib_input_param_t *p, void *model_in, pfmlib_output_param_t *q, void *model_out); extern pfm_err_t pfm_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs); extern pfm_err_t pfm_get_impl_pmds(pfmlib_regmask_t *impl_pmds); extern pfm_err_t pfm_get_impl_counters(pfmlib_regmask_t *impl_counters); extern pfm_err_t pfm_get_num_pmds(unsigned int *num); extern pfm_err_t pfm_get_num_pmcs(unsigned int *num); extern pfm_err_t pfm_get_num_counters(unsigned int *num); extern pfm_err_t pfm_get_hw_counter_width(unsigned int *width); extern pfm_err_t pfm_get_version(unsigned int *version); extern char *pfm_strerror(int code); extern pfm_err_t pfm_get_cycle_event(pfmlib_event_t *e); extern pfm_err_t pfm_get_inst_retired_event(pfmlib_event_t *e); /* * Supported PMU family */ #define PFMLIB_NO_PMU -1 /* PMU unused (forced) */ #define PFMLIB_UNKNOWN_PMU 0 /* type not yet known (dynamic) */ #define PFMLIB_GEN_IA64_PMU 1 /* Intel IA-64 architected PMU */ #define PFMLIB_ITANIUM_PMU 2 /* Intel Itanium */ #define PFMLIB_ITANIUM2_PMU 3 /* Intel Itanium 2 */ #define PFMLIB_MONTECITO_PMU 4 /* Intel Dual-Core Itanium 2 9000 */ #define PFMLIB_AMD64_PMU 16 /* AMD AMD64 (K7, K8, Fam 10h) */ #define PFMLIB_GEN_IA32_PMU 63 /* Intel architectural PMU for X86 */ #define PFMLIB_I386_P6_PMU 32 /* Intel PIII (P6 core) */ #define PFMLIB_PENTIUM4_PMU 33 /* Intel Pentium4/Xeon/EM64T */ #define PFMLIB_COREDUO_PMU 34 /* Intel Core Duo/Core Solo */ #define PFMLIB_I386_PM_PMU 35 /* Intel Pentium M */ #define PFMLIB_CORE_PMU 36 /* obsolete, use PFMLIB_INTEL_CORE_PMU */ #define PFMLIB_INTEL_CORE_PMU 36 /* Intel Core */ #define PFMLIB_INTEL_PPRO_PMU 37 /* Intel Pentium Pro */ #define PFMLIB_INTEL_PII_PMU 38 /* Intel Pentium II */ #define PFMLIB_INTEL_ATOM_PMU 39 /* Intel Atom */ #define PFMLIB_INTEL_NHM_PMU 40 /* Intel Nehalem */ #define PFMLIB_INTEL_WSM_PMU 41 /* Intel Westmere */ #define PFMLIB_MIPS_20KC_PMU 64 /* MIPS 20KC */ #define PFMLIB_MIPS_24K_PMU 65 /* MIPS 24K */ #define PFMLIB_MIPS_25KF_PMU 66 /* MIPS 25KF */ #define PFMLIB_MIPS_34K_PMU 67 /* MIPS 34K */ #define PFMLIB_MIPS_5KC_PMU 68 /* MIPS 5KC */ #define PFMLIB_MIPS_74K_PMU 69 /* MIPS 74K */ #define PFMLIB_MIPS_R10000_PMU 70 /* MIPS R10000 */ #define PFMLIB_MIPS_R12000_PMU 71 /* MIPS R12000 */ #define PFMLIB_MIPS_RM7000_PMU 72 /* MIPS RM7000 */ #define PFMLIB_MIPS_RM9000_PMU 73 /* MIPS RM9000 */ #define PFMLIB_MIPS_SB1_PMU 74 /* MIPS SB1/SB1A */ #define PFMLIB_MIPS_VR5432_PMU 75 /* MIPS VR5432 */ #define PFMLIB_MIPS_VR5500_PMU 76 /* MIPS VR5500 */ #define PFMLIB_MIPS_ICE9A_PMU 77 /* SiCortex ICE9A */ #define PFMLIB_MIPS_ICE9B_PMU 78 /* SiCortex ICE9B */ #define PFMLIB_POWERPC_PMU 90 /* POWERPC */ #define PFMLIB_CRAYX2_PMU 96 /* Cray X2 */ #define PFMLIB_CELL_PMU 100 /* CELL */ #define PFMLIB_PPC970_PMU 110 /* IBM PowerPC 970(FX,GX) */ #define PFMLIB_PPC970MP_PMU 111 /* IBM PowerPC 970MP */ #define PFMLIB_POWER3_PMU 112 /* IBM POWER3 */ #define PFMLIB_POWER4_PMU 113 /* IBM POWER4 */ #define PFMLIB_POWER5_PMU 114 /* IBM POWER5 */ #define PFMLIB_POWER5p_PMU 115 /* IBM POWER5+ */ #define PFMLIB_POWER6_PMU 116 /* IBM POWER6 */ #define PFMLIB_POWER7_PMU 117 /* IBM POWER7 */ #define PFMLIB_SPARC_ULTRA12_PMU 130 /* UltraSPARC I, II, IIi, and IIe */ #define PFMLIB_SPARC_ULTRA3_PMU 131 /* UltraSPARC III */ #define PFMLIB_SPARC_ULTRA3I_PMU 132 /* UltraSPARC IIIi and IIIi+ */ #define PFMLIB_SPARC_ULTRA3PLUS_PMU 133 /* UltraSPARC III+ and IV */ #define PFMLIB_SPARC_ULTRA4PLUS_PMU 134 /* UltraSPARC IV+ */ #define PFMLIB_SPARC_NIAGARA1_PMU 135 /* Niagara-1 */ #define PFMLIB_SPARC_NIAGARA2_PMU 136 /* Niagara-2 */ /* * pfmlib error codes */ #define PFMLIB_SUCCESS 0 /* success */ #define PFMLIB_ERR_NOTSUPP -1 /* function not supported */ #define PFMLIB_ERR_INVAL -2 /* invalid parameters */ #define PFMLIB_ERR_NOINIT -3 /* library was not initialized */ #define PFMLIB_ERR_NOTFOUND -4 /* event not found */ #define PFMLIB_ERR_NOASSIGN -5 /* cannot assign events to counters */ #define PFMLIB_ERR_FULL -6 /* buffer is full or too small */ #define PFMLIB_ERR_EVTMANY -7 /* event used more than once */ #define PFMLIB_ERR_MAGIC -8 /* invalid library magic number */ #define PFMLIB_ERR_FEATCOMB -9 /* invalid combination of features */ #define PFMLIB_ERR_EVTSET -10 /* incompatible event sets */ #define PFMLIB_ERR_EVTINCOMP -11 /* incompatible event combination */ #define PFMLIB_ERR_TOOMANY -12 /* too many events or unit masks */ #define PFMLIB_ERR_IRRTOOBIG -13 /* code range too big */ #define PFMLIB_ERR_IRREMPTY -14 /* empty code range */ #define PFMLIB_ERR_IRRINVAL -15 /* invalid code range */ #define PFMLIB_ERR_IRRTOOMANY -16 /* too many code ranges */ #define PFMLIB_ERR_DRRINVAL -17 /* invalid data range */ #define PFMLIB_ERR_DRRTOOMANY -18 /* too many data ranges */ #define PFMLIB_ERR_BADHOST -19 /* not supported by host CPU */ #define PFMLIB_ERR_IRRALIGN -20 /* bad alignment for code range */ #define PFMLIB_ERR_IRRFLAGS -21 /* code range missing flags */ #define PFMLIB_ERR_UMASK -22 /* invalid or missing unit mask */ #define PFMLIB_ERR_NOMEM -23 /* out of memory */ #define __PFMLIB_REGMASK_EL(g) ((g)/__PFMLIB_REG_BV_BITS) #define __PFMLIB_REGMASK_MASK(g) (((pfmlib_regmask_bits_t)1) << ((g) % __PFMLIB_REG_BV_BITS)) static inline int pfm_regmask_isset(pfmlib_regmask_t *h, unsigned int b) { if (b >= PFMLIB_REG_MAX) return 0; return (h->bits[__PFMLIB_REGMASK_EL(b)] & __PFMLIB_REGMASK_MASK(b)) != 0; } static inline int pfm_regmask_set(pfmlib_regmask_t *h, unsigned int b) { if (b >= PFMLIB_REG_MAX) return PFMLIB_ERR_INVAL; h->bits[__PFMLIB_REGMASK_EL(b)] |= __PFMLIB_REGMASK_MASK(b); return PFMLIB_SUCCESS; } static inline int pfm_regmask_clr(pfmlib_regmask_t *h, unsigned int b) { if (h == NULL || b >= PFMLIB_REG_MAX) return PFMLIB_ERR_INVAL; h->bits[__PFMLIB_REGMASK_EL(b)] &= ~ __PFMLIB_REGMASK_MASK(b); return PFMLIB_SUCCESS; } static inline int pfm_regmask_weight(pfmlib_regmask_t *h, unsigned int *w) { unsigned int pos; unsigned int weight = 0; if (h == NULL || w == NULL) return PFMLIB_ERR_INVAL; for (pos = 0; pos < PFMLIB_REG_BV; pos++) { weight += (unsigned int)pfmlib_popcnt(h->bits[pos]); } *w = weight; return PFMLIB_SUCCESS; } static inline int pfm_regmask_eq(pfmlib_regmask_t *h1, pfmlib_regmask_t *h2) { unsigned int pos; if (h1 == NULL || h2 == NULL) return 0; for (pos = 0; pos < PFMLIB_REG_BV; pos++) { if (h1->bits[pos] != h2->bits[pos]) return 0; } return 1; } static inline int pfm_regmask_and(pfmlib_regmask_t *dst, pfmlib_regmask_t *h1, pfmlib_regmask_t *h2) { unsigned int pos; if (dst == NULL || h1 == NULL || h2 == NULL) return PFMLIB_ERR_INVAL; for (pos = 0; pos < PFMLIB_REG_BV; pos++) { dst->bits[pos] = h1->bits[pos] & h2->bits[pos]; } return PFMLIB_SUCCESS; } static inline int pfm_regmask_andnot(pfmlib_regmask_t *dst, pfmlib_regmask_t *h1, pfmlib_regmask_t *h2) { unsigned int pos; if (dst == NULL || h1 == NULL || h2 == NULL) return PFMLIB_ERR_INVAL; for (pos = 0; pos < PFMLIB_REG_BV; pos++) { dst->bits[pos] = h1->bits[pos] & ~h2->bits[pos]; } return PFMLIB_SUCCESS; } static inline int pfm_regmask_or(pfmlib_regmask_t *dst, pfmlib_regmask_t *h1, pfmlib_regmask_t *h2) { unsigned int pos; if (dst == NULL || h1 == NULL || h2 == NULL) return PFMLIB_ERR_INVAL; for (pos = 0; pos < PFMLIB_REG_BV; pos++) { dst->bits[pos] = h1->bits[pos] | h2->bits[pos]; } return PFMLIB_SUCCESS; } static inline int pfm_regmask_copy(pfmlib_regmask_t *dst, pfmlib_regmask_t *src) { unsigned int pos; if (dst == NULL || src == NULL) return PFMLIB_ERR_INVAL; for (pos = 0; pos < PFMLIB_REG_BV; pos++) { dst->bits[pos] = src->bits[pos]; } return PFMLIB_SUCCESS; } static inline int pfm_regmask_not(pfmlib_regmask_t *dst) { unsigned int pos; if (dst == NULL) return PFMLIB_ERR_INVAL; for (pos = 0; pos < PFMLIB_REG_BV; pos++) { dst->bits[pos] = ~dst->bits[pos]; } return PFMLIB_SUCCESS; } #ifdef __cplusplus /* extern C */ } #endif #endif /* __PFMLIB_H__ */