2 * pfmlib_common.c: set of functions common to all PMU models
4 * Copyright (c) 2009 Google, Inc
5 * Contributed by Stephane Eranian <eranian@gmail.com>
8 * Copyright (c) 2001-2006 Hewlett-Packard Development Company, L.P.
9 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
15 * of the Software, and to permit persons to whom the Software is furnished to do so,
16 * subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included in all
19 * copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
22 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
23 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
25 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
26 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include <sys/types.h>
36 #include <perfmon/pfmlib.h>
38 #include "pfmlib_priv.h"
40 static pfmlib_pmu_t *pfmlib_pmus[]=
43 #ifdef CONFIG_PFMLIB_ARCH_IA64
48 &generic_ia64_support, /* must always be last for IA-64 */
52 #ifdef CONFIG_PFMLIB_ARCH_I386
53 /* 32-bit only processors */
58 &intel_coreduo_support,
61 #ifdef CONFIG_PFMLIB_ARCH_X86
62 /* 32 and 64 bit processors */
66 &amd64_k8_revb_support,
67 &amd64_k8_revc_support,
68 &amd64_k8_revd_support,
69 &amd64_k8_reve_support,
70 &amd64_k8_revf_support,
71 &amd64_k8_revg_support,
72 &amd64_fam10h_barcelona_support,
73 &amd64_fam10h_shanghai_support,
74 &amd64_fam10h_istanbul_support,
75 &amd64_fam11h_turion_support,
76 &amd64_fam12h_llano_support,
77 &amd64_fam14h_bobcat_support,
78 &amd64_fam15h_interlagos_support,
79 &amd64_fam15h_nb_support,
83 &intel_nhm_ex_support,
84 &intel_nhm_unc_support,
85 &intel_wsm_sp_support,
86 &intel_wsm_dp_support,
87 &intel_wsm_unc_support,
89 &intel_snb_unc_cbo0_support,
90 &intel_snb_unc_cbo1_support,
91 &intel_snb_unc_cbo2_support,
92 &intel_snb_unc_cbo3_support,
93 &intel_snb_ep_support,
95 &intel_ivb_unc_cbo0_support,
96 &intel_ivb_unc_cbo1_support,
97 &intel_ivb_unc_cbo2_support,
98 &intel_ivb_unc_cbo3_support,
99 &intel_ivb_ep_support,
101 &intel_hsw_ep_support,
104 &intel_snbep_unc_cb0_support,
105 &intel_snbep_unc_cb1_support,
106 &intel_snbep_unc_cb2_support,
107 &intel_snbep_unc_cb3_support,
108 &intel_snbep_unc_cb4_support,
109 &intel_snbep_unc_cb5_support,
110 &intel_snbep_unc_cb6_support,
111 &intel_snbep_unc_cb7_support,
112 &intel_snbep_unc_ha_support,
113 &intel_snbep_unc_imc0_support,
114 &intel_snbep_unc_imc1_support,
115 &intel_snbep_unc_imc2_support,
116 &intel_snbep_unc_imc3_support,
117 &intel_snbep_unc_pcu_support,
118 &intel_snbep_unc_qpi0_support,
119 &intel_snbep_unc_qpi1_support,
120 &intel_snbep_unc_ubo_support,
121 &intel_snbep_unc_r2pcie_support,
122 &intel_snbep_unc_r3qpi0_support,
123 &intel_snbep_unc_r3qpi1_support,
126 &intel_ivbep_unc_cb0_support,
127 &intel_ivbep_unc_cb1_support,
128 &intel_ivbep_unc_cb2_support,
129 &intel_ivbep_unc_cb3_support,
130 &intel_ivbep_unc_cb4_support,
131 &intel_ivbep_unc_cb5_support,
132 &intel_ivbep_unc_cb6_support,
133 &intel_ivbep_unc_cb7_support,
134 &intel_ivbep_unc_cb8_support,
135 &intel_ivbep_unc_cb9_support,
136 &intel_ivbep_unc_cb10_support,
137 &intel_ivbep_unc_cb11_support,
138 &intel_ivbep_unc_cb12_support,
139 &intel_ivbep_unc_cb13_support,
140 &intel_ivbep_unc_cb14_support,
141 &intel_ivbep_unc_ha0_support,
142 &intel_ivbep_unc_ha1_support,
143 &intel_ivbep_unc_imc0_support,
144 &intel_ivbep_unc_imc1_support,
145 &intel_ivbep_unc_imc2_support,
146 &intel_ivbep_unc_imc3_support,
147 &intel_ivbep_unc_imc4_support,
148 &intel_ivbep_unc_imc5_support,
149 &intel_ivbep_unc_imc6_support,
150 &intel_ivbep_unc_imc7_support,
151 &intel_ivbep_unc_pcu_support,
152 &intel_ivbep_unc_qpi0_support,
153 &intel_ivbep_unc_qpi1_support,
154 &intel_ivbep_unc_qpi2_support,
155 &intel_ivbep_unc_ubo_support,
156 &intel_ivbep_unc_r2pcie_support,
157 &intel_ivbep_unc_r3qpi0_support,
158 &intel_ivbep_unc_r3qpi1_support,
159 &intel_ivbep_unc_r3qpi2_support,
160 &intel_ivbep_unc_irp_support,
161 &intel_x86_arch_support, /* must always be last for x86 */
164 #ifdef CONFIG_PFMLIB_ARCH_MIPS
168 #ifdef CONFIG_PFMLIB_ARCH_SICORTEX
172 #ifdef CONFIG_PFMLIB_ARCH_POWERPC
184 #ifdef CONFIG_PFMLIB_ARCH_SPARC
185 &sparc_ultra12_support,
186 &sparc_ultra3_support,
187 &sparc_ultra3i_support,
188 &sparc_ultra3plus_support,
189 &sparc_ultra4plus_support,
190 &sparc_niagara1_support,
191 &sparc_niagara2_support,
194 #ifdef CONFIG_PFMLIB_CELL
198 #ifdef CONFIG_PFMLIB_ARCH_ARM
199 &arm_cortex_a7_support,
200 &arm_cortex_a8_support,
201 &arm_cortex_a9_support,
202 &arm_cortex_a15_support,
204 &arm_qcom_krait_support,
205 &arm_cortex_a57_support,
206 &arm_cortex_a53_support,
209 #ifdef CONFIG_PFMLIB_ARCH_ARM64
210 &arm_cortex_a57_support,
211 &arm_cortex_a53_support,
215 #ifdef CONFIG_PFMLIB_ARCH_S390X
216 &s390x_cpum_cf_support,
217 &s390x_cpum_sf_support,
221 &perf_event_raw_support,
224 #define PFMLIB_NUM_PMUS (int)(sizeof(pfmlib_pmus)/sizeof(pfmlib_pmu_t *))
226 static pfmlib_os_t pfmlib_os_none;
227 pfmlib_os_t *pfmlib_os = &pfmlib_os_none;
229 static pfmlib_os_t *pfmlib_oses[]={
236 #define PFMLIB_NUM_OSES (int)(sizeof(pfmlib_oses)/sizeof(pfmlib_os_t *))
239 * Mapping table from PMU index to pfmlib_pmu_t
240 * table is populated from pfmlib_pmus[] when the library
243 * Some entries can be NULL if PMU is not implemented on host
244 * architecture or if the initialization failed.
246 static pfmlib_pmu_t *pfmlib_pmus_map[PFM_PMU_MAX];
249 #define pfmlib_for_each_pmu_event(p, e) \
250 for(e=(p)->get_event_first((p)); e != -1; e = (p)->get_event_next((p), e))
252 #define for_each_pmu_event_attr(u, i) \
253 for((u)=0; (u) < (i)->nattrs; (u) = (u)+1)
255 #define pfmlib_for_each_pmu(x) \
256 for((x)= 0 ; (x) < PFMLIB_NUM_PMUS; (x)++)
258 #define pfmlib_for_each_pmu(x) \
259 for((x)= 0 ; (x) < PFMLIB_NUM_PMUS; (x)++)
261 #define pfmlib_for_each_os(x) \
262 for((x)= 0 ; (x) < PFMLIB_NUM_OSES; (x)++)
264 pfmlib_config_t pfm_cfg;
267 __pfm_dbprintf(const char *fmt, ...)
271 if (pfm_cfg.debug == 0)
275 vfprintf(pfm_cfg.fp, fmt, ap);
280 __pfm_vbprintf(const char *fmt, ...)
284 if (pfm_cfg.verbose == 0)
288 vfprintf(pfm_cfg.fp, fmt, ap);
293 * pfmlib_getl: our own equivalent to GNU getline() extension.
294 * This avoids a dependency on having a C library with
295 * support for getline().
298 pfmlib_getl(char **buffer, size_t *len, FILE *fp)
300 #define GETL_DFL_LEN 32
303 size_t maxsz, maxi, d, i = 0;
305 if (!len || !fp || !buffer)
316 while ((c = fgetc(fp)) != EOF) {
317 if (maxsz == 0 || i == maxi) {
319 maxsz = GETL_DFL_LEN;
328 *buffer = realloc(*buffer, maxsz);
333 maxi = maxsz - d - 2;
342 return c != EOF ? 0 : -1;
348 * append fmt+args to str such that the string is no
349 * more than max characters incl. null termination
352 pfmlib_strconcat(char *str, size_t max, const char *fmt, ...)
358 todo = max - strlen(str);
360 vsnprintf(str+len, todo, fmt, ap);
365 * compact all pattrs starting from index i
368 pfmlib_compact_pattrs(pfmlib_event_desc_t *e, int i)
372 for (j = i+1; j < e->npattrs; j++)
373 e->pattrs[j - 1] = e->pattrs[j];
379 pfmlib_compact_attrs(pfmlib_event_desc_t *e, int i)
383 for (j = i+1; j < e->nattrs; j++)
384 e->attrs[j - 1] = e->attrs[j];
390 * 0 : different attribute
391 * 1 : exactly same attribute (duplicate can be removed)
392 * -1 : same attribute but value differ, this is an error
395 pfmlib_same_attr(pfmlib_event_desc_t *d, int i, int j)
397 pfm_event_attr_info_t *a1, *a2;
398 pfmlib_attr_t *b1, *b2;
406 if (a1->idx == a2->idx
407 && a1->type == a2->type
408 && a1->ctrl == a2->ctrl) {
409 if (b1->ival == b2->ival)
418 pfmlib_pmu_active(pfmlib_pmu_t *pmu)
420 return !!(pmu->flags & PFMLIB_PMU_FL_ACTIVE);
424 pfmlib_pmu_initialized(pfmlib_pmu_t *pmu)
426 return !!(pmu->flags & PFMLIB_PMU_FL_INIT);
429 static inline pfm_pmu_t
432 return (pfm_pmu_t)(idx >> PFMLIB_PMU_SHIFT) & PFMLIB_PMU_MASK;
435 static inline pfmlib_pmu_t *
436 pmu2pmuidx(pfm_pmu_t pmu)
438 /* pfm_pmu_t is unsigned int enum, so
439 * just need to check for upper bound
441 if (pmu >= PFM_PMU_MAX)
444 return pfmlib_pmus_map[pmu];
448 * external opaque idx -> PMU + internal idx
450 static pfmlib_pmu_t *
451 pfmlib_idx2pidx(int idx, int *pidx)
456 if (PFMLIB_INITIALIZED() == 0)
462 pmu_id = idx2pmu(idx);
464 pmu = pmu2pmuidx(pmu_id);
468 *pidx = idx & PFMLIB_PMU_PIDX_MASK;
470 if (!pmu->event_is_valid(pmu, *pidx))
477 pfmlib_find_os(pfm_os_t id)
482 pfmlib_for_each_os(o) {
484 if (os->id == id && (os->flags & PFMLIB_OS_FL_ACTIVATED))
491 pfmlib_check_struct(void *st, size_t usz, size_t refsz, size_t sz)
496 * if user size is zero, then use ABI0 size
502 * cannot be smaller than ABI0 size
505 DPRINT("pfmlib_check_struct: user size too small %zu\n", usz);
510 * if bigger than current ABI, then check that none
511 * of the extra bits are set. This is to avoid mistake
512 * by caller assuming the library set those bits.
515 char *addr = (char *)st + sz;
516 char *end = (char *)st + usz;
517 while (addr != end) {
519 DPRINT("pfmlib_check_struct: invalid extra bits\n");
528 * check environment variables for:
529 * LIBPFM_VERBOSE : enable verbose output (must be 1)
530 * LIBPFM_DEBUG : enable debug output (must be 1)
533 pfmlib_init_env(void)
539 str = getenv("LIBPFM_VERBOSE");
540 if (str && isdigit((int)*str))
541 pfm_cfg.verbose = *str - '0';
543 str = getenv("LIBPFM_DEBUG");
544 if (str && isdigit((int)*str))
545 pfm_cfg.debug = *str - '0';
547 str = getenv("LIBPFM_DEBUG_STDOUT");
551 pfm_cfg.forced_pmu = getenv("LIBPFM_FORCE_PMU");
553 str = getenv("LIBPFM_ENCODE_INACTIVE");
555 pfm_cfg.inactive = 1;
557 str = getenv("LIBPFM_DISABLED_PMUS");
559 pfm_cfg.blacklist_pmus = str;
563 pfmlib_pmu_sanity_checks(pfmlib_pmu_t *p)
566 * check event can be encoded
568 if (p->pme_count >= (1<< PFMLIB_PMU_SHIFT)) {
569 DPRINT("too many events for %s\n", p->desc);
570 return PFM_ERR_NOTSUPP;
573 if (p->max_encoding > PFMLIB_MAX_ENCODING) {
574 DPRINT("max encoding too high (%d > %d) for %s\n",
575 p->max_encoding, PFMLIB_MAX_ENCODING, p->desc);
576 return PFM_ERR_NOTSUPP;
583 pfmlib_build_fstr(pfmlib_event_desc_t *e, char **fstr)
589 *fstr = malloc(strlen(e->fstr) + 2 + strlen(e->pmu->name) + 1);
591 sprintf(*fstr, "%s::%s", e->pmu->name, e->fstr);
593 return *fstr ? PFM_SUCCESS : PFM_ERR_NOMEM;
597 pfmlib_pmu_activate(pfmlib_pmu_t *p)
602 ret = p->pmu_init(p);
603 if (ret != PFM_SUCCESS)
607 p->flags |= PFMLIB_PMU_FL_ACTIVE;
609 DPRINT("activated %s\n", p->desc);
615 pfmlib_match_forced_pmu(const char *name)
620 /* skip any lower level specifier */
621 p = strchr(pfm_cfg.forced_pmu, ',');
623 l = p - pfm_cfg.forced_pmu;
625 l = strlen(pfm_cfg.forced_pmu);
627 return !strncasecmp(name, pfm_cfg.forced_pmu, l);
631 pfmlib_is_blacklisted_pmu(pfmlib_pmu_t *p)
633 if (!pfm_cfg.blacklist_pmus)
637 * scan list for matching PMU names, we accept substrings.
638 * for instance: snbep does match snbep*
640 char *q, buffer[strlen(pfm_cfg.blacklist_pmus) + 1];
642 strcpy (buffer, pfm_cfg.blacklist_pmus);
643 for (q = strtok (buffer, ","); q != NULL; q = strtok (NULL, ",")) {
644 if (strstr (p->name, q) != NULL) {
652 pfmlib_init_pmus(void)
659 * activate all detected PMUs
660 * when forced, only the designated PMU
661 * is setup and activated
663 pfmlib_for_each_pmu(i) {
667 DPRINT("trying %s\n", p->desc);
671 if (!pfm_cfg.forced_pmu)
672 ret = p->pmu_detect(p);
673 else if (!pfmlib_match_forced_pmu(p->name))
674 ret = PFM_ERR_NOTSUPP;
678 * failure causes PMU to not be available
680 if (pfmlib_pmu_sanity_checks(p) != PFM_SUCCESS)
683 if (pfmlib_is_blacklisted_pmu(p)) {
684 DPRINT("%d PMU blacklisted, skipping initialization\n");
687 p->flags |= PFMLIB_PMU_FL_INIT;
690 * populate mapping table
692 pfmlib_pmus_map[p->pmu] = p;
694 if (ret != PFM_SUCCESS)
698 * check if exported by OS if needed
700 if (p->os_detect[pfmlib_os->id]) {
701 ret = p->os_detect[pfmlib_os->id](p);
702 if (ret != PFM_SUCCESS) {
703 DPRINT("%s PMU not exported by OS\n", p->name);
708 ret = pfmlib_pmu_activate(p);
709 if (ret == PFM_SUCCESS)
712 if (pfm_cfg.forced_pmu) {
713 __pfm_vbprintf("PMU forced to %s (%s) : %s\n",
716 ret == PFM_SUCCESS ? "success" : "failure");
720 DPRINT("%d PMU detected out of %d supported\n", nsuccess, PFMLIB_NUM_PMUS);
730 pfmlib_for_each_os(o) {
736 if (os->detect(os) != PFM_SUCCESS)
739 if (os != &pfmlib_os_none && pfmlib_os == &pfmlib_os_none)
742 DPRINT("OS layer %s activated\n", os->name);
743 os->flags = PFMLIB_OS_FL_ACTIVATED;
745 DPRINT("default OS layer: %s\n", pfmlib_os->name);
755 if (pfm_cfg.initdone)
759 * generic sanity checks
761 if (PFM_PMU_MAX & (~PFMLIB_PMU_MASK)) {
762 DPRINT("PFM_PMU_MAX exceeds PFMLIB_PMU_MASK\n");
763 return PFM_ERR_NOTSUPP;
768 /* must be done before pfmlib_init_pmus() */
771 ret = pfmlib_init_pmus();
772 if (ret != PFM_SUCCESS)
776 pfm_cfg.initdone = 1;
787 if (PFMLIB_INITIALIZED() == 0)
790 pfmlib_for_each_pmu(i) {
791 pmu = pfmlib_pmus[i];
792 if (!pfmlib_pmu_active(pmu))
794 if (pmu->pmu_terminate)
795 pmu->pmu_terminate(pmu);
797 pfm_cfg.initdone = 0;
801 pfm_find_event(const char *str)
803 pfmlib_event_desc_t e;
806 if (PFMLIB_INITIALIZED() == 0)
807 return PFM_ERR_NOINIT;
810 return PFM_ERR_INVAL;
812 memset(&e, 0, sizeof(e));
814 ret = pfmlib_parse_event(str, &e);
815 if (ret == PFM_SUCCESS)
816 return pfmlib_pidx2idx(e.pmu, e.event);
822 pfmlib_sanitize_event(pfmlib_event_desc_t *d)
827 * fail if duplicate attributes are found
829 for(i=0; i < d->nattrs; i++) {
830 for(j=i+1; j < d->nattrs; j++) {
831 ret = pfmlib_same_attr(d, i, j);
833 pfmlib_compact_attrs(d, j);
835 return PFM_ERR_ATTR_SET;
842 pfmlib_parse_event_attr(char *str, pfmlib_event_desc_t *d)
844 pfm_event_attr_info_t *ainfo;
845 char *s, *p, *q, *endptr;
848 int aidx = 0, has_val, has_raw_um = 0, has_um = 0;
849 int ret = PFM_ERR_INVAL;
854 p = strchr(s, PFMLIB_ATTR_DELIM);
865 * check for raw umasks in hexdecimal only
867 if (*s == '0' && tolower(*(s+1)) == 'x') {
870 /* can only have one raw umask */
871 if (has_raw_um || has_um) {
872 DPRINT("cannot mix raw umask with umask\n");
875 if (!(d->pmu->flags & PFMLIB_PMU_FL_RAW_UMASK)) {
876 DPRINT("PMU %s does not support RAW umasks\n", d->pmu->name);
880 /* we have reserved an entry at the end of pattrs */
882 ainfo = d->pattrs + aidx;
884 ainfo->name = "RAW_UMASK";
885 ainfo->type = PFM_ATTR_RAW_UMASK;
886 ainfo->ctrl = PFM_ATTR_CTRL_PMU;
887 ainfo->idx = strtoul(s, &endptr, 0);
890 DPRINT("raw umask (%s) is not a number\n");
899 for(aidx = 0; aidx < d->npattrs; aidx++) {
900 if (!strcasecmp(d->pattrs[aidx].name, s)) {
901 ainfo = d->pattrs + aidx;
902 /* disambiguate modifier and umask
903 * with the same name : snb::L2_LINES_IN:I:I=1
905 if (has_val && ainfo->type == PFM_ATTR_UMASK)
910 DPRINT("cannot find attribute %s\n", s);
915 if (type == PFM_ATTR_UMASK) {
918 DPRINT("cannot mix raw umask with umask\n");
926 /* cannot have equiv for attributes with value */
928 return PFM_ERR_ATTR_VAL;
930 /* copy because it is const */
931 z = strdup(ainfo->equiv);
933 return PFM_ERR_NOMEM;
935 ret = pfmlib_parse_event_attr(z, d);
939 if (ret != PFM_SUCCESS)
945 * we tolerate missing value for boolean attributes.
946 * Presence of the attribute is equivalent to
947 * attr=1, i.e., attribute is set
949 if (type != PFM_ATTR_UMASK && type != PFM_ATTR_RAW_UMASK && !has_val) {
950 if (type != PFM_ATTR_MOD_BOOL)
951 return PFM_ERR_ATTR_VAL;
952 s = yes; /* no const */
956 d->attrs[d->nattrs].ival = 0;
957 if ((type == PFM_ATTR_UMASK || type == PFM_ATTR_RAW_UMASK) && has_val)
958 return PFM_ERR_ATTR_VAL;
963 ret = PFM_ERR_ATTR_VAL;
966 if (d->nattrs == PFMLIB_MAX_ATTRS) {
967 DPRINT("too many attributes\n");
968 ret = PFM_ERR_TOOMANY;
974 case PFM_ATTR_MOD_BOOL:
978 if (tolower((int)*s) == 'y'
979 || tolower((int)*s) == 't' || *s == '1')
980 d->attrs[d->nattrs].ival = 1;
981 else if (tolower((int)*s) == 'n'
982 || tolower((int)*s) == 'f' || *s == '0')
983 d->attrs[d->nattrs].ival = 0;
987 case PFM_ATTR_MOD_INTEGER:
988 d->attrs[d->nattrs].ival = strtoull(s, &endptr, 0);
996 d->attrs[d->nattrs].id = aidx;
1006 pfmlib_build_event_pattrs(pfmlib_event_desc_t *e)
1010 int i, ret, pmu_nattrs = 0, os_nattrs = 0;
1014 * cannot satisfy request for an OS that was not activated
1016 os = pfmlib_find_os(e->osid);
1018 return PFM_ERR_NOTSUPP;
1022 /* get actual PMU number of attributes for the event */
1023 if (pmu->get_event_nattrs)
1024 pmu_nattrs = pmu->get_event_nattrs(pmu, e->event);
1025 if (os && os->get_os_nattrs)
1026 os_nattrs += os->get_os_nattrs(os, e);
1028 npattrs = pmu_nattrs + os_nattrs;
1031 * add extra entry for raw umask, if supported
1033 if (pmu->flags & PFMLIB_PMU_FL_RAW_UMASK)
1037 e->pattrs = malloc(npattrs * sizeof(*e->pattrs));
1039 return PFM_ERR_NOMEM;
1042 /* collect all actual PMU attrs */
1043 for(i = 0; i < pmu_nattrs; i++) {
1044 ret = pmu->get_event_attr_info(pmu, e->event, i, e->pattrs+i);
1045 if (ret != PFM_SUCCESS)
1048 e->npattrs = pmu_nattrs;
1051 if (e->osid == os->id && os->get_os_attr_info) {
1052 os->get_os_attr_info(os, e);
1054 * check for conflicts between HW and OS attributes
1056 if (pmu->validate_pattrs[e->osid])
1057 pmu->validate_pattrs[e->osid](pmu, e);
1060 for (i = 0; i < e->npattrs; i++)
1061 DPRINT("%d %d %d %d %d %s\n", e->event, i, e->pattrs[i].type, e->pattrs[i].ctrl, e->pattrs[i].idx, e->pattrs[i].name);
1071 pfmlib_release_event(pfmlib_event_desc_t *e)
1078 match_event(void *this, pfmlib_event_desc_t *d, const char *e, const char *s)
1080 return strcasecmp(e, s);
1084 pfmlib_parse_equiv_event(const char *event, pfmlib_event_desc_t *d)
1086 pfmlib_pmu_t *pmu = d->pmu;
1087 pfm_event_info_t einfo;
1088 int (*match)(void *this, pfmlib_event_desc_t *d, const char *e, const char *s);
1094 * create copy because string is const
1096 s = str = strdup(event);
1098 return PFM_ERR_NOMEM;
1100 p = strchr(s, PFMLIB_ATTR_DELIM);
1104 match = pmu->match_event ? pmu->match_event : match_event;
1106 pfmlib_for_each_pmu_event(pmu, i) {
1107 ret = pmu->get_event_info(pmu, i, &einfo);
1108 if (ret != PFM_SUCCESS)
1110 if (!match(pmu, d, einfo.name, s))
1114 return PFM_ERR_NOTFOUND;
1117 d->event = i; /* private index */
1120 * build_event_pattrs and parse_event_attr
1121 * cannot be factorized with pfmlib_parse_event()
1122 * because equivalent event may add its own attributes
1124 ret = pfmlib_build_event_pattrs(d);
1125 if (ret != PFM_SUCCESS)
1128 ret = pfmlib_parse_event_attr(p, d);
1129 if (ret == PFM_SUCCESS)
1130 ret = pfmlib_sanitize_event(d);
1134 if (ret != PFM_SUCCESS)
1135 pfmlib_release_event(d);
1141 pfmlib_parse_event(const char *event, pfmlib_event_desc_t *d)
1143 pfm_event_info_t einfo;
1146 int (*match)(void *this, pfmlib_event_desc_t *d, const char *e, const char *s);
1147 const char *pname = NULL;
1151 * create copy because string is const
1153 s = str = strdup(event);
1155 return PFM_ERR_NOMEM;
1158 * ignore everything passed after a comma
1159 * (simplify dealing with const event list)
1161 * safe to do before pname, because now
1162 * PMU name cannot have commas in them.
1164 p = strchr(s, PFMLIB_EVENT_DELIM);
1168 /* check for optional PMU name */
1169 p = strstr(s, PFMLIB_PMU_DELIM);
1173 s = p + strlen(PFMLIB_PMU_DELIM);
1175 p = strchr(s, PFMLIB_ATTR_DELIM);
1181 pfmlib_for_each_pmu(j) {
1182 pmu = pfmlib_pmus[j];
1184 * if no explicit PMU name is given, then
1185 * only look for active PMU models
1187 if (!pname && !pfmlib_pmu_active(pmu))
1190 * check for requested PMU name,
1192 if (pname && strcasecmp(pname, pmu->name))
1195 * only allow event on inactive PMU if enabled via
1196 * environement variable
1198 if (pname && !pfmlib_pmu_active(pmu) && !pfm_cfg.inactive)
1201 match = pmu->match_event ? pmu->match_event : match_event;
1205 pfmlib_for_each_pmu_event(pmu, i) {
1206 ret = pmu->get_event_info(pmu, i, &einfo);
1207 if (ret != PFM_SUCCESS)
1209 if (!match(pmu, d, einfo.name, s))
1214 return PFM_ERR_NOTFOUND;
1218 * handle equivalence
1221 ret = pfmlib_parse_equiv_event(einfo.equiv, d);
1222 if (ret != PFM_SUCCESS)
1225 d->event = i; /* private index */
1227 ret = pfmlib_build_event_pattrs(d);
1228 if (ret != PFM_SUCCESS)
1232 * parse attributes from original event
1234 ret = pfmlib_parse_event_attr(p, d);
1235 if (ret == PFM_SUCCESS)
1236 ret = pfmlib_sanitize_event(d);
1238 for (i = 0; i < d->nattrs; i++) {
1239 pfm_event_attr_info_t *a = attr(d, i);
1240 if (a->type != PFM_ATTR_RAW_UMASK)
1241 DPRINT("%d %d %d %s\n", d->event, i, a->idx, d->pattrs[d->attrs[i].id].name);
1243 DPRINT("%d %d RAW_UMASK (0x%x)\n", d->event, i, a->idx);
1247 if (ret != PFM_SUCCESS)
1248 pfmlib_release_event(d);
1252 /* sorry, only English supported at this point! */
1253 static const char *pfmlib_err_list[]=
1257 "invalid parameters",
1258 "pfmlib not initialized",
1260 "invalid combination of model specific features",
1261 "invalid or missing unit mask",
1263 "invalid event attribute",
1264 "invalid event attribute value",
1265 "attribute value already set",
1266 "too many parameters",
1267 "parameter is too small",
1269 static int pfmlib_err_count = (int)sizeof(pfmlib_err_list)/sizeof(char *);
1272 pfm_strerror(int code)
1275 if (code <0 || code >= pfmlib_err_count)
1276 return "unknown error code";
1278 return pfmlib_err_list[code];
1282 pfm_get_version(void)
1284 return LIBPFM_VERSION;
1288 pfm_get_event_next(int idx)
1293 pmu = pfmlib_idx2pidx(idx, &pidx);
1297 pidx = pmu->get_event_next(pmu, pidx);
1298 return pidx == -1 ? -1 : pfmlib_pidx2idx(pmu, pidx);
1302 pfm_get_os_event_encoding(const char *str, int dfl_plm, pfm_os_t uos, void *args)
1306 if (PFMLIB_INITIALIZED() == 0)
1307 return PFM_ERR_NOINIT;
1310 return PFM_ERR_INVAL;
1312 if (dfl_plm & ~(PFM_PLM_ALL))
1313 return PFM_ERR_INVAL;
1315 os = pfmlib_find_os(uos);
1317 return PFM_ERR_NOTSUPP;
1319 return os->encode(os, str, dfl_plm, args);
1323 * old API maintained for backward compatibility with existing apps
1324 * prefer pfm_get_os_event_encoding()
1327 pfm_get_event_encoding(const char *str, int dfl_plm, char **fstr, int *idx, uint64_t **codes, int *count)
1329 pfm_pmu_encode_arg_t arg;
1332 if (!(str && codes && count))
1333 return PFM_ERR_INVAL;
1335 if ((*codes && !*count) || (!*codes && *count))
1336 return PFM_ERR_INVAL;
1338 memset(&arg, 0, sizeof(arg));
1343 arg.size = sizeof(arg);
1346 * request RAW PMU encoding
1348 ret = pfm_get_os_event_encoding(str, dfl_plm, PFM_OS_NONE, &arg);
1349 if (ret != PFM_SUCCESS)
1352 /* handle the case where the array was allocated */
1363 pfmlib_check_event_pattrs(pfmlib_pmu_t *pmu, int pidx, pfm_os_t osid, FILE *fp)
1365 pfmlib_event_desc_t e;
1368 memset(&e, 0, sizeof(e));
1373 ret = pfmlib_build_event_pattrs(&e);
1374 if (ret != PFM_SUCCESS) {
1375 fprintf(fp, "invalid pattrs for event %d\n", pidx);
1381 for (i = 0; i < e.npattrs; i++) {
1382 for (j = i+1; j < e.npattrs; j++) {
1383 if (!strcmp(e.pattrs[i].name, e.pattrs[j].name)) {
1384 fprintf(fp, "event %d duplicate pattrs %s\n", pidx, e.pattrs[i].name);
1392 * release resources allocated for event
1394 pfmlib_release_event(&e);
1399 pfmlib_validate_encoding(char *buf, int plm)
1401 uint64_t *codes = NULL;
1404 ret = pfm_get_event_encoding(buf, plm, NULL, NULL, &codes, &count);
1405 if (ret != PFM_SUCCESS) {
1408 for(i=0; i < count; i++)
1409 __pfm_dbprintf(" %#"PRIx64, codes[i]);
1410 __pfm_dbprintf("\n");
1419 pfmlib_pmu_validate_encoding(pfmlib_pmu_t *pmu, FILE *fp)
1421 pfm_event_info_t einfo;
1422 pfm_event_attr_info_t ainfo;
1424 size_t maxlen = 0, len;
1425 int i, u, n = 0, um;
1426 int ret, retval = PFM_SUCCESS;
1428 pfmlib_for_each_pmu_event(pmu, i) {
1429 ret = pmu->get_event_info(pmu, i, &einfo);
1430 if (ret != PFM_SUCCESS)
1433 ret = pfmlib_check_event_pattrs(pmu, i, PFM_OS_NONE, fp);
1434 if (ret != PFM_SUCCESS)
1437 len = strlen(einfo.name);
1441 for_each_pmu_event_attr(u, &einfo) {
1442 ret = pmu->get_event_attr_info(pmu, i, u, &ainfo);
1443 if (ret != PFM_SUCCESS)
1446 if (ainfo.type != PFM_ATTR_UMASK)
1449 len = strlen(einfo.name) + strlen(ainfo.name);
1454 /* 2 = ::, 1=:, 1=eol */
1455 maxlen += strlen(pmu->name) + 2 + 1 + 1;
1456 buf = malloc(maxlen);
1458 return PFM_ERR_NOMEM;
1460 pfmlib_for_each_pmu_event(pmu, i) {
1461 ret = pmu->get_event_info(pmu, i, &einfo);
1462 if (ret != PFM_SUCCESS) {
1468 for_each_pmu_event_attr(u, &einfo) {
1469 ret = pmu->get_event_attr_info(pmu, i, u, &ainfo);
1470 if (ret != PFM_SUCCESS) {
1475 if (ainfo.type != PFM_ATTR_UMASK)
1479 * XXX: some events may require more than one umasks to encode
1481 sprintf(buf, "%s::%s:%s", pmu->name, einfo.name, ainfo.name);
1482 ret = pfmlib_validate_encoding(buf, PFM_PLM3|PFM_PLM0);
1483 if (ret != PFM_SUCCESS) {
1484 if (pmu->can_auto_encode) {
1485 if (!pmu->can_auto_encode(pmu, i, u))
1489 * some PMU may not support raw encoding
1491 if (ret != PFM_ERR_NOTSUPP) {
1492 fprintf(fp, "cannot encode event %s : %s\n", buf, pfm_strerror(ret));
1500 sprintf(buf, "%s::%s", pmu->name, einfo.name);
1501 ret = pfmlib_validate_encoding(buf, PFM_PLM3|PFM_PLM0);
1502 if (ret != PFM_SUCCESS) {
1503 if (pmu->can_auto_encode) {
1504 if (!pmu->can_auto_encode(pmu, i, u))
1507 if (ret != PFM_ERR_NOTSUPP) {
1508 fprintf(fp, "cannot encode event %s : %s\n", buf, pfm_strerror(ret));
1522 pfm_pmu_validate(pfm_pmu_t pmu_id, FILE *fp)
1524 pfmlib_pmu_t *pmu, *pmx;
1529 return PFM_ERR_INVAL;
1531 pmu = pmu2pmuidx(pmu_id);
1533 return PFM_ERR_INVAL;
1536 if (!pfmlib_pmu_initialized(pmu)) {
1537 fprintf(fp, "pmu: %s :: initialization failed\n", pmu->name);
1538 return PFM_ERR_INVAL;
1542 fprintf(fp, "pmu id: %d :: no name\n", pmu->pmu);
1543 return PFM_ERR_INVAL;
1547 fprintf(fp, "pmu: %s :: no description\n", pmu->name);
1548 return PFM_ERR_INVAL;
1551 if (pmu->pmu >= PFM_PMU_MAX) {
1552 fprintf(fp, "pmu: %s :: invalid PMU id\n", pmu->name);
1553 return PFM_ERR_INVAL;
1556 if (pmu->max_encoding >= PFMLIB_MAX_ENCODING) {
1557 fprintf(fp, "pmu: %s :: max encoding too high\n", pmu->name);
1558 return PFM_ERR_INVAL;
1561 if (pfmlib_pmu_active(pmu) && !pmu->pme_count) {
1562 fprintf(fp, "pmu: %s :: no events\n", pmu->name);
1563 return PFM_ERR_INVAL;
1565 if (!pmu->pmu_detect) {
1566 fprintf(fp, "pmu: %s :: missing pmu_detect callback\n", pmu->name);
1567 return PFM_ERR_INVAL;
1569 if (!pmu->get_event_first) {
1570 fprintf(fp, "pmu: %s :: missing get_event_first callback\n", pmu->name);
1571 return PFM_ERR_INVAL;
1573 if (!pmu->get_event_next) {
1574 fprintf(fp, "pmu: %s :: missing get_event_next callback\n", pmu->name);
1575 return PFM_ERR_INVAL;
1577 if (!pmu->get_event_info) {
1578 fprintf(fp, "pmu: %s :: missing get_event_info callback\n", pmu->name);
1579 return PFM_ERR_INVAL;
1581 if (!pmu->get_event_attr_info) {
1582 fprintf(fp, "pmu: %s :: missing get_event_attr_info callback\n", pmu->name);
1583 return PFM_ERR_INVAL;
1585 for (i = PFM_OS_NONE; i < PFM_OS_MAX; i++) {
1586 if (pmu->get_event_encoding[i])
1590 fprintf(fp, "pmu: %s :: no os event encoding callback\n", pmu->name);
1591 return PFM_ERR_INVAL;
1593 if (!pmu->max_encoding) {
1594 fprintf(fp, "pmu: %s :: max_encoding is zero\n", pmu->name);
1595 return PFM_ERR_INVAL;
1598 /* look for duplicate names, id */
1599 pfmlib_for_each_pmu(i) {
1600 pmx = pfmlib_pmus[i];
1601 if (!pfmlib_pmu_active(pmx))
1605 if (!strcasecmp(pmx->name, pmu->name)) {
1606 fprintf(fp, "pmu: %s :: duplicate name\n", pmu->name);
1607 return PFM_ERR_INVAL;
1609 if (pmx->pmu == pmu->pmu) {
1610 fprintf(fp, "pmu: %s :: duplicate id\n", pmu->name);
1611 return PFM_ERR_INVAL;
1615 if (pmu->validate_table) {
1616 ret = pmu->validate_table(pmu, fp);
1617 if (ret != PFM_SUCCESS)
1620 return pfmlib_pmu_validate_encoding(pmu, fp);
1624 pfm_get_event_info(int idx, pfm_os_t os, pfm_event_info_t *uinfo)
1626 pfm_event_info_t info;
1627 pfmlib_event_desc_t e;
1629 size_t sz = sizeof(info);
1632 if (!PFMLIB_INITIALIZED())
1633 return PFM_ERR_NOINIT;
1635 if (os >= PFM_OS_MAX)
1636 return PFM_ERR_INVAL;
1638 pmu = pfmlib_idx2pidx(idx, &pidx);
1640 return PFM_ERR_INVAL;
1643 return PFM_ERR_INVAL;
1645 sz = pfmlib_check_struct(uinfo, uinfo->size, PFM_EVENT_INFO_ABI0, sz);
1647 return PFM_ERR_INVAL;
1649 memset(&info, 0, sizeof(info));
1653 /* default data type is uint64 */
1654 info.dtype = PFM_DTYPE_UINT64;
1657 info.is_precise = 0;
1659 ret = pmu->get_event_info(pmu, pidx, &info);
1660 if (ret != PFM_SUCCESS)
1663 info.pmu = pmu->pmu;
1666 memset(&e, 0, sizeof(e));
1671 ret = pfmlib_build_event_pattrs(&e);
1672 if (ret == PFM_SUCCESS) {
1673 info.nattrs = e.npattrs;
1674 memcpy(uinfo, &info, sz);
1677 pfmlib_release_event(&e);
1682 pfm_get_event_attr_info(int idx, int attr_idx, pfm_os_t os, pfm_event_attr_info_t *uinfo)
1684 pfm_event_attr_info_t info;
1685 pfmlib_event_desc_t e;
1687 size_t sz = sizeof(info);
1690 if (!PFMLIB_INITIALIZED())
1691 return PFM_ERR_NOINIT;
1694 return PFM_ERR_INVAL;
1696 if (os >= PFM_OS_MAX)
1697 return PFM_ERR_INVAL;
1699 pmu = pfmlib_idx2pidx(idx, &pidx);
1701 return PFM_ERR_INVAL;
1704 return PFM_ERR_INVAL;
1706 sz = pfmlib_check_struct(uinfo, uinfo->size, PFM_ATTR_INFO_ABI0, sz);
1708 return PFM_ERR_INVAL;
1710 memset(&e, 0, sizeof(e));
1715 ret = pfmlib_build_event_pattrs(&e);
1716 if (ret != PFM_SUCCESS)
1719 ret = PFM_ERR_INVAL;
1721 if (attr_idx >= e.npattrs)
1725 * copy event_attr_info
1727 info = e.pattrs[attr_idx];
1730 * rewrite size to reflect what we are returning
1734 * info.idx = private, namespace specific index,
1735 * should not be visible externally, so override
1738 info.idx = attr_idx;
1740 memcpy(uinfo, &info, sz);
1744 pfmlib_release_event(&e);
1749 pfm_get_pmu_info(pfm_pmu_t pmuid, pfm_pmu_info_t *uinfo)
1751 pfm_pmu_info_t info;
1753 size_t sz = sizeof(info);
1756 if (!PFMLIB_INITIALIZED())
1757 return PFM_ERR_NOINIT;
1759 if (pmuid >= PFM_PMU_MAX)
1760 return PFM_ERR_INVAL;
1763 return PFM_ERR_INVAL;
1765 sz = pfmlib_check_struct(uinfo, uinfo->size, PFM_PMU_INFO_ABI0, sz);
1767 return PFM_ERR_INVAL;
1769 pmu = pfmlib_pmus_map[pmuid];
1771 return PFM_ERR_NOTSUPP;
1773 info.name = pmu->name;
1774 info.desc = pmu->desc;
1778 info.max_encoding = pmu->max_encoding;
1779 info.num_cntrs = pmu->num_cntrs;
1780 info.num_fixed_cntrs = pmu->num_fixed_cntrs;
1782 pidx = pmu->get_event_first(pmu);
1784 info.first_event = -1;
1786 info.first_event = pfmlib_pidx2idx(pmu, pidx);
1789 * XXX: pme_count only valid when PMU is detected
1791 info.is_present = pfmlib_pmu_active(pmu);
1792 info.is_dfl = !!(pmu->flags & PFMLIB_PMU_FL_ARCH_DFL);
1793 info.type = pmu->type;
1795 if (pmu->get_num_events)
1796 info.nevents = pmu->get_num_events(pmu);
1798 info.nevents = pmu->pme_count;
1800 memcpy(uinfo, &info, sz);
1806 pfmlib_get_pmu_by_type(pfm_pmu_type_t t)
1811 pfmlib_for_each_pmu(i) {
1812 pmu = pfmlib_pmus[i];
1814 if (!pfmlib_pmu_active(pmu))
1827 pfmlib_compare_attr_id(const void *a, const void *b)
1829 const pfmlib_attr_t *t1 = a;
1830 const pfmlib_attr_t *t2 = b;
1832 if (t1->id < t2->id)
1834 return t1->id == t2->id ? 0 : 1;
1838 pfmlib_sort_attr(pfmlib_event_desc_t *e)
1840 qsort(e->attrs, e->nattrs, sizeof(pfmlib_attr_t), pfmlib_compare_attr_id);
1844 pfmlib_raw_pmu_encode(void *this, const char *str, int dfl_plm, void *data)
1846 pfm_pmu_encode_arg_t arg;
1847 pfm_pmu_encode_arg_t *uarg = data;
1850 pfmlib_event_desc_t e;
1851 size_t sz = sizeof(arg);
1854 sz = pfmlib_check_struct(uarg, uarg->size, PFM_RAW_ENCODE_ABI0, sz);
1856 return PFM_ERR_INVAL;
1858 memset(&arg, 0, sizeof(arg));
1863 memcpy(&arg, uarg, sz);
1865 memset(&e, 0, sizeof(e));
1867 e.osid = PFM_OS_NONE;
1868 e.dfl_plm = dfl_plm;
1870 ret = pfmlib_parse_event(str, &e);
1871 if (ret != PFM_SUCCESS)
1876 if (!pmu->get_event_encoding[PFM_OS_NONE]) {
1877 DPRINT("PMU %s does not support PFM_OS_NONE\n", pmu->name);
1878 return PFM_ERR_NOTSUPP;
1881 ret = pmu->get_event_encoding[PFM_OS_NONE](pmu, &e);
1882 if (ret != PFM_SUCCESS)
1885 * return opaque event identifier
1887 arg.idx = pfmlib_pidx2idx(e.pmu, e.event);
1889 if (arg.codes == NULL) {
1890 ret = PFM_ERR_NOMEM;
1891 arg.codes = malloc(sizeof(uint64_t) * e.count);
1894 } else if (arg.count < e.count) {
1895 ret = PFM_ERR_TOOSMALL;
1899 arg.count = e.count;
1901 for (i = 0; i < e.count; i++)
1902 arg.codes[i] = e.codes[i];
1905 ret = pfmlib_build_fstr(&e, arg.fstr);
1906 if (ret != PFM_SUCCESS)
1912 /* copy out results */
1913 memcpy(uarg, &arg, sz);
1916 if (ret != PFM_SUCCESS)
1920 * release resources allocated for event
1922 pfmlib_release_event(&e);
1927 pfmlib_raw_pmu_detect(void *this)
1932 static pfmlib_os_t pfmlib_os_none= {
1933 .name = "No OS (raw PMU)",
1935 .flags = PFMLIB_OS_FL_ACTIVATED,
1936 .encode = pfmlib_raw_pmu_encode,
1937 .detect = pfmlib_raw_pmu_detect,