vmm: Fix use-after-free in load_elf()
[akaros.git] / user / perfmon / pfmlib_common.c
1 /*
2  * pfmlib_common.c: set of functions common to all PMU models
3  *
4  * Copyright (c) 2009 Google, Inc
5  * Contributed by Stephane Eranian <eranian@gmail.com>
6  *
7  * Based on:
8  * Copyright (c) 2001-2006 Hewlett-Packard Development Company, L.P.
9  * Contributed by Stephane Eranian <eranian@hpl.hp.com>
10  *
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:
17  *
18  * The above copyright notice and this permission notice shall be included in all
19  * copies or substantial portions of the Software.
20  *
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.
27  */
28 #include <sys/types.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdarg.h>
34 #include <limits.h>
35
36 #include <perfmon/pfmlib.h>
37
38 #include "pfmlib_priv.h"
39
40 static pfmlib_pmu_t *pfmlib_pmus[]=
41 {
42
43 #ifdef CONFIG_PFMLIB_ARCH_IA64
44 #if 0
45         &montecito_support,
46         &itanium2_support,
47         &itanium_support,
48         &generic_ia64_support,  /* must always be last for IA-64 */
49 #endif
50 #endif
51
52 #ifdef CONFIG_PFMLIB_ARCH_I386
53         /* 32-bit only processors */
54         &intel_pii_support,
55         &intel_ppro_support,
56         &intel_p6_support,
57         &intel_pm_support,
58         &intel_coreduo_support,
59 #endif
60
61 #ifdef CONFIG_PFMLIB_ARCH_X86
62         /* 32 and 64 bit processors */
63         &netburst_support,
64         &netburst_p_support,
65         &amd64_k7_support,
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,
80         &intel_core_support,
81         &intel_atom_support,
82         &intel_nhm_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,
88         &intel_snb_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,
94         &intel_ivb_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,
100         &intel_hsw_support,
101         &intel_hsw_ep_support,
102         &intel_bdw_support,
103         &intel_rapl_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,
124         &intel_knc_support,
125         &intel_slm_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 */
162 #endif
163
164 #ifdef CONFIG_PFMLIB_ARCH_MIPS
165         &mips_74k_support,
166 #endif
167
168 #ifdef CONFIG_PFMLIB_ARCH_SICORTEX
169         &sicortex_support,
170 #endif
171
172 #ifdef CONFIG_PFMLIB_ARCH_POWERPC
173         &power4_support,
174         &ppc970_support,
175         &ppc970mp_support,
176         &power5_support,
177         &power5p_support,
178         &power6_support,
179         &power7_support,
180         &power8_support,
181         &torrent_support,
182 #endif
183
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,
192 #endif
193
194 #ifdef CONFIG_PFMLIB_CELL
195         &cell_support,
196 #endif
197
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,
203         &arm_1176_support,
204         &arm_qcom_krait_support,
205         &arm_cortex_a57_support,
206         &arm_cortex_a53_support,
207         &arm_xgene_support,
208 #endif
209 #ifdef CONFIG_PFMLIB_ARCH_ARM64
210         &arm_cortex_a57_support,
211         &arm_cortex_a53_support,
212         &arm_xgene_support,
213 #endif
214
215 #ifdef CONFIG_PFMLIB_ARCH_S390X
216         &s390x_cpum_cf_support,
217         &s390x_cpum_sf_support,
218 #endif
219 #ifdef __linux__
220         &perf_event_support,
221         &perf_event_raw_support,
222 #endif
223 };
224 #define PFMLIB_NUM_PMUS (int)(sizeof(pfmlib_pmus)/sizeof(pfmlib_pmu_t *))
225
226 static pfmlib_os_t pfmlib_os_none;
227 pfmlib_os_t *pfmlib_os = &pfmlib_os_none;
228
229 static pfmlib_os_t *pfmlib_oses[]={
230         &pfmlib_os_none,
231 #ifdef __linux__
232         &pfmlib_os_perf,
233         &pfmlib_os_perf_ext,
234 #endif
235 };
236 #define PFMLIB_NUM_OSES (int)(sizeof(pfmlib_oses)/sizeof(pfmlib_os_t *))
237
238 /*
239  * Mapping table from PMU index to pfmlib_pmu_t
240  * table is populated from pfmlib_pmus[] when the library
241  * is initialized.
242  *
243  * Some entries can be NULL if PMU is not implemented on host
244  * architecture or if the initialization failed.
245  */
246 static pfmlib_pmu_t *pfmlib_pmus_map[PFM_PMU_MAX];
247
248
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))
251
252 #define for_each_pmu_event_attr(u, i) \
253         for((u)=0; (u) < (i)->nattrs; (u) = (u)+1)
254
255 #define pfmlib_for_each_pmu(x) \
256         for((x)= 0 ; (x) < PFMLIB_NUM_PMUS; (x)++)
257
258 #define pfmlib_for_each_pmu(x) \
259         for((x)= 0 ; (x) < PFMLIB_NUM_PMUS; (x)++)
260
261 #define pfmlib_for_each_os(x) \
262         for((x)= 0 ; (x) < PFMLIB_NUM_OSES; (x)++)
263
264 pfmlib_config_t pfm_cfg;
265
266 void
267 __pfm_dbprintf(const char *fmt, ...)
268 {
269         va_list ap;
270
271         if (pfm_cfg.debug == 0)
272                 return;
273
274         va_start(ap, fmt);
275         vfprintf(pfm_cfg.fp, fmt, ap);
276         va_end(ap);
277 }
278
279 void
280 __pfm_vbprintf(const char *fmt, ...)
281 {
282         va_list ap;
283
284         if (pfm_cfg.verbose == 0)
285                 return;
286
287         va_start(ap, fmt);
288         vfprintf(pfm_cfg.fp, fmt, ap);
289         va_end(ap);
290 }
291
292 /*
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().
296  */
297 int
298 pfmlib_getl(char **buffer, size_t *len, FILE *fp)
299 {
300 #define GETL_DFL_LEN    32
301         char *b;
302         int c;
303         size_t maxsz, maxi, d, i = 0;
304
305         if (!len || !fp || !buffer)
306                 return -1;
307
308         b = *buffer;
309
310         if (!b)
311                 *len = 0;
312
313         maxsz = *len;
314         maxi = maxsz - 2;
315
316         while ((c = fgetc(fp)) != EOF) {
317                 if (maxsz == 0 || i == maxi) {
318                         if (maxsz == 0)
319                                 maxsz = GETL_DFL_LEN;
320                         else
321                                 maxsz <<= 1;
322
323                         if (*buffer)
324                                 d = &b[i] - *buffer;
325                         else
326                                 d = 0;
327
328                         *buffer = realloc(*buffer, maxsz);
329                         if (!*buffer)
330                                 return -1;
331
332                         b = *buffer + d;
333                         maxi = maxsz - d - 2;
334                         i = 0;
335                         *len = maxsz;
336                 }
337                 b[i++] = c;
338                 if (c == '\n')
339                         break;
340         }
341         b[i] = '\0';
342         return c != EOF ? 0 : -1;
343 }
344
345
346
347 /*
348  * append fmt+args to str such that the string is no
349  * more than max characters incl. null termination
350  */
351 void
352 pfmlib_strconcat(char *str, size_t max, const char *fmt, ...)
353 {
354         va_list ap;
355         size_t len, todo;
356
357         len = strlen(str);
358         todo = max - strlen(str);
359         va_start(ap, fmt);
360         vsnprintf(str+len, todo, fmt, ap);
361         va_end(ap);
362 }
363
364 /*
365  * compact all pattrs starting from index i
366  */
367 void
368 pfmlib_compact_pattrs(pfmlib_event_desc_t *e, int i)
369 {
370         int j;
371
372         for (j = i+1; j < e->npattrs; j++)
373                 e->pattrs[j - 1] = e->pattrs[j];
374
375         e->npattrs--;
376 }
377
378 static void
379 pfmlib_compact_attrs(pfmlib_event_desc_t *e, int i)
380 {
381         int j;
382
383         for (j = i+1; j < e->nattrs; j++)
384                 e->attrs[j - 1] = e->attrs[j];
385
386         e->nattrs--;
387 }
388
389 /*
390  *  0 : different attribute
391  *  1 : exactly same attribute (duplicate can be removed)
392  * -1 : same attribute but value differ, this is an error
393  */
394 static inline int
395 pfmlib_same_attr(pfmlib_event_desc_t *d, int i, int j)
396 {
397         pfm_event_attr_info_t *a1, *a2;
398         pfmlib_attr_t *b1, *b2;
399
400         a1 = attr(d, i);
401         a2 = attr(d, j);
402
403         b1 = d->attrs+i;
404         b2 = d->attrs+j;
405
406         if (a1->idx == a2->idx
407             && a1->type == a2->type
408             && a1->ctrl == a2->ctrl) {
409                 if (b1->ival == b2->ival)
410                         return 1;
411                 return -1;
412
413         }
414         return 0;
415 }
416
417 static inline int
418 pfmlib_pmu_active(pfmlib_pmu_t *pmu)
419 {
420         return !!(pmu->flags & PFMLIB_PMU_FL_ACTIVE);
421 }
422
423 static inline int
424 pfmlib_pmu_initialized(pfmlib_pmu_t *pmu)
425 {
426         return !!(pmu->flags & PFMLIB_PMU_FL_INIT);
427 }
428
429 static inline pfm_pmu_t
430 idx2pmu(int idx)
431 {
432         return (pfm_pmu_t)(idx >> PFMLIB_PMU_SHIFT) & PFMLIB_PMU_MASK;
433 }
434
435 static inline pfmlib_pmu_t *
436 pmu2pmuidx(pfm_pmu_t pmu)
437 {
438         /* pfm_pmu_t is unsigned int enum, so
439          * just need to check for upper bound
440          */
441         if (pmu >= PFM_PMU_MAX)
442                 return NULL;
443
444         return pfmlib_pmus_map[pmu];
445 }
446
447 /*
448  * external opaque idx -> PMU + internal idx
449  */
450 static pfmlib_pmu_t *
451 pfmlib_idx2pidx(int idx, int *pidx)
452 {
453         pfmlib_pmu_t *pmu;
454         pfm_pmu_t pmu_id;
455
456         if (PFMLIB_INITIALIZED() == 0)
457                 return NULL;
458
459         if (idx < 0)
460                 return NULL;
461
462         pmu_id = idx2pmu(idx);
463
464         pmu = pmu2pmuidx(pmu_id);
465         if (!pmu)
466                 return NULL;
467
468         *pidx = idx & PFMLIB_PMU_PIDX_MASK;
469
470         if (!pmu->event_is_valid(pmu, *pidx))
471                 return NULL;
472
473         return pmu;
474 }
475
476 static pfmlib_os_t *
477 pfmlib_find_os(pfm_os_t id)
478 {
479         int o;
480         pfmlib_os_t *os;
481
482         pfmlib_for_each_os(o) {
483                 os = pfmlib_oses[o];
484                 if (os->id == id && (os->flags & PFMLIB_OS_FL_ACTIVATED))
485                         return os;
486         }
487         return NULL;
488 }
489
490 size_t
491 pfmlib_check_struct(void *st, size_t usz, size_t refsz, size_t sz)
492 {
493         size_t rsz = sz;
494
495         /*
496          * if user size is zero, then use ABI0 size
497          */
498         if (usz == 0)
499                 usz = refsz;
500
501         /*
502          * cannot be smaller than ABI0 size
503          */
504         if (usz < refsz) {
505                 DPRINT("pfmlib_check_struct: user size too small %zu\n", usz);
506                 return 0;
507         }
508
509         /*
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.
513          */
514         if (usz > sz) {
515                 char *addr = (char *)st + sz;
516                 char *end = (char *)st + usz;
517                 while (addr != end) {
518                         if (*addr++) {
519                                 DPRINT("pfmlib_check_struct: invalid extra bits\n");
520                                 return 0;
521                         }
522                 }
523         }
524         return rsz;
525 }
526
527 /*
528  * check environment variables for:
529  *  LIBPFM_VERBOSE : enable verbose output (must be 1)
530  *  LIBPFM_DEBUG   : enable debug output (must be 1)
531  */
532 static void
533 pfmlib_init_env(void)
534 {
535         char *str;
536
537         pfm_cfg.fp = stderr;
538
539         str = getenv("LIBPFM_VERBOSE");
540         if (str && isdigit((int)*str))
541                 pfm_cfg.verbose = *str - '0';
542
543         str = getenv("LIBPFM_DEBUG");
544         if (str && isdigit((int)*str))
545                 pfm_cfg.debug = *str - '0';
546
547         str = getenv("LIBPFM_DEBUG_STDOUT");
548         if (str)
549                 pfm_cfg.fp = stdout;
550
551         pfm_cfg.forced_pmu = getenv("LIBPFM_FORCE_PMU");
552
553         str = getenv("LIBPFM_ENCODE_INACTIVE");
554         if (str)
555                 pfm_cfg.inactive = 1;
556
557         str = getenv("LIBPFM_DISABLED_PMUS");
558         if (str)
559                 pfm_cfg.blacklist_pmus = str;
560 }
561
562 static int
563 pfmlib_pmu_sanity_checks(pfmlib_pmu_t *p)
564 {
565         /*
566          * check event can be encoded
567          */
568         if (p->pme_count >= (1<< PFMLIB_PMU_SHIFT)) {
569                 DPRINT("too many events for %s\n", p->desc);
570                 return PFM_ERR_NOTSUPP;
571         }
572
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;
577         }
578
579         return PFM_SUCCESS;
580 }
581
582 int
583 pfmlib_build_fstr(pfmlib_event_desc_t *e, char **fstr)
584 {
585         /* nothing to do */
586         if (!fstr)
587                 return PFM_SUCCESS;
588
589         *fstr = malloc(strlen(e->fstr) + 2 + strlen(e->pmu->name) + 1);
590         if (*fstr)
591                 sprintf(*fstr, "%s::%s", e->pmu->name, e->fstr);
592
593         return *fstr ? PFM_SUCCESS : PFM_ERR_NOMEM;
594 }
595
596 static int
597 pfmlib_pmu_activate(pfmlib_pmu_t *p)
598 {
599         int ret;
600
601         if (p->pmu_init) {
602                 ret = p->pmu_init(p);
603                 if (ret != PFM_SUCCESS)
604                         return ret;
605         }
606
607         p->flags |= PFMLIB_PMU_FL_ACTIVE;
608
609         DPRINT("activated %s\n", p->desc);
610
611         return PFM_SUCCESS;     
612 }
613
614 static inline int
615 pfmlib_match_forced_pmu(const char *name)
616 {
617         const char *p;
618         size_t l;
619
620         /* skip any lower level specifier */
621         p = strchr(pfm_cfg.forced_pmu, ',');
622         if (p)
623                 l = p - pfm_cfg.forced_pmu;
624         else
625                 l = strlen(pfm_cfg.forced_pmu);
626
627         return !strncasecmp(name, pfm_cfg.forced_pmu, l);
628 }
629
630 static int
631 pfmlib_is_blacklisted_pmu(pfmlib_pmu_t *p)
632 {
633         if (!pfm_cfg.blacklist_pmus)
634                 return 0;
635
636         /*
637          * scan list for matching PMU names, we accept substrings.
638          * for instance: snbep does match snbep*
639          */
640         char *q, buffer[strlen(pfm_cfg.blacklist_pmus) + 1];
641
642         strcpy (buffer, pfm_cfg.blacklist_pmus);
643         for (q = strtok (buffer, ","); q != NULL; q = strtok (NULL, ",")) {
644                 if (strstr (p->name, q) != NULL) {
645                         return 1;
646                 }
647         }
648         return 0;
649 }
650
651 static int
652 pfmlib_init_pmus(void)
653 {
654         pfmlib_pmu_t *p;
655         int i, ret;
656         int nsuccess = 0;
657         
658         /*
659          * activate all detected PMUs
660          * when forced, only the designated PMU
661          * is setup and activated
662          */
663         pfmlib_for_each_pmu(i) {
664
665                 p = pfmlib_pmus[i];
666
667                 DPRINT("trying %s\n", p->desc);
668
669                 ret = PFM_SUCCESS;
670
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;
675
676                 /*
677                  * basic checks
678                  * failure causes PMU to not be available
679                  */
680                 if (pfmlib_pmu_sanity_checks(p) != PFM_SUCCESS)
681                         continue;
682
683                 if (pfmlib_is_blacklisted_pmu(p)) {
684                         DPRINT("%d PMU blacklisted, skipping initialization\n");
685                         continue;
686                 }
687                 p->flags |= PFMLIB_PMU_FL_INIT;
688
689                 /*
690                  * populate mapping table
691                  */
692                 pfmlib_pmus_map[p->pmu] = p;
693
694                 if (ret != PFM_SUCCESS)
695                         continue;
696
697                 /*
698                  * check if exported by OS if needed
699                  */
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);
704                                 continue;
705                         }
706                 }
707
708                 ret = pfmlib_pmu_activate(p);
709                 if (ret == PFM_SUCCESS)
710                         nsuccess++;
711
712                 if (pfm_cfg.forced_pmu) {
713                         __pfm_vbprintf("PMU forced to %s (%s) : %s\n",
714                                         p->name,
715                                         p->desc,
716                                         ret == PFM_SUCCESS ? "success" : "failure");
717                         return ret;
718                 }
719         }
720         DPRINT("%d PMU detected out of %d supported\n", nsuccess, PFMLIB_NUM_PMUS);
721         return PFM_SUCCESS;
722 }
723
724 static void
725 pfmlib_init_os(void)
726 {
727         int o;
728         pfmlib_os_t *os;
729
730         pfmlib_for_each_os(o) {
731                 os = pfmlib_oses[o];
732
733                 if (!os->detect)
734                         continue;
735
736                 if (os->detect(os) != PFM_SUCCESS)
737                         continue;
738
739                 if (os != &pfmlib_os_none && pfmlib_os == &pfmlib_os_none)
740                         pfmlib_os = os;
741
742                 DPRINT("OS layer %s activated\n", os->name);
743                 os->flags = PFMLIB_OS_FL_ACTIVATED;
744         }
745         DPRINT("default OS layer: %s\n", pfmlib_os->name);
746 }
747
748 int
749 pfm_initialize(void)
750 {
751         int ret;
752         /*
753          * not atomic
754          */
755         if (pfm_cfg.initdone)
756                 return PFM_SUCCESS;
757
758         /*
759          * generic sanity checks
760          */
761         if (PFM_PMU_MAX & (~PFMLIB_PMU_MASK)) {
762                 DPRINT("PFM_PMU_MAX exceeds PFMLIB_PMU_MASK\n");        
763                 return PFM_ERR_NOTSUPP;
764         }
765
766         pfmlib_init_env();
767
768         /* must be done before pfmlib_init_pmus() */
769         pfmlib_init_os();
770
771         ret = pfmlib_init_pmus();
772         if (ret != PFM_SUCCESS)
773                 return ret;
774
775
776         pfm_cfg.initdone = 1;
777
778         return ret;
779 }
780
781 void
782 pfm_terminate(void)
783 {
784         pfmlib_pmu_t *pmu;
785         int i;
786
787         if (PFMLIB_INITIALIZED() == 0)
788                 return;
789
790         pfmlib_for_each_pmu(i) {
791                 pmu = pfmlib_pmus[i];
792                 if (!pfmlib_pmu_active(pmu))
793                         continue;
794                 if (pmu->pmu_terminate)
795                         pmu->pmu_terminate(pmu);
796         }
797         pfm_cfg.initdone = 0;
798 }
799
800 int
801 pfm_find_event(const char *str)
802 {
803         pfmlib_event_desc_t e;
804         int ret;
805
806         if (PFMLIB_INITIALIZED() == 0)
807                 return PFM_ERR_NOINIT;
808
809         if (!str)
810                 return PFM_ERR_INVAL;
811
812         memset(&e, 0, sizeof(e));
813
814         ret = pfmlib_parse_event(str, &e);
815         if (ret == PFM_SUCCESS)
816                 return pfmlib_pidx2idx(e.pmu, e.event);
817
818         return ret;
819 }
820
821 static int
822 pfmlib_sanitize_event(pfmlib_event_desc_t *d)
823 {
824         int i, j, ret;
825
826         /*
827          * fail if duplicate attributes are found
828          */
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);
832                         if (ret == 1)
833                                 pfmlib_compact_attrs(d, j);
834                         else if (ret == -1)
835                                 return PFM_ERR_ATTR_SET;
836                 }
837         }
838         return PFM_SUCCESS;
839 }
840
841 static int
842 pfmlib_parse_event_attr(char *str, pfmlib_event_desc_t *d)
843 {
844         pfm_event_attr_info_t *ainfo;
845         char *s, *p, *q, *endptr;
846         char yes[2] = "y";
847         pfm_attr_t type;
848         int aidx = 0, has_val, has_raw_um = 0, has_um = 0;
849         int ret = PFM_ERR_INVAL;
850
851         s = str;
852
853         while(s) {
854                 p = strchr(s, PFMLIB_ATTR_DELIM);
855                 if (p)
856                         *p++ = '\0';
857
858                 q = strchr(s, '=');
859                 if (q)
860                         *q++ = '\0';
861
862                 has_val = !!q;
863
864                 /*
865                  * check for raw umasks in hexdecimal only
866                  */
867                 if (*s == '0' && tolower(*(s+1)) == 'x') {
868                         char *endptr = NULL;
869
870                         /* can only have one raw umask */
871                         if (has_raw_um || has_um) {
872                                 DPRINT("cannot mix raw umask with umask\n");
873                                 return PFM_ERR_ATTR;
874                         }
875                         if (!(d->pmu->flags & PFMLIB_PMU_FL_RAW_UMASK)) {
876                                 DPRINT("PMU %s does not support RAW umasks\n", d->pmu->name);
877                                 return PFM_ERR_ATTR;
878                         }
879
880                         /* we have reserved an entry at the end of pattrs */
881                         aidx = d->npattrs;
882                         ainfo = d->pattrs + aidx;
883
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);
888                         ainfo->equiv= NULL;
889                         if (*endptr) {
890                                 DPRINT("raw umask (%s) is not a number\n");
891                                 return PFM_ERR_ATTR;
892                         }
893
894                         has_raw_um = 1;
895
896                         goto found_attr;
897                 }
898
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
904                                  */
905                                 if (has_val && ainfo->type == PFM_ATTR_UMASK)
906                                         continue;
907                                 goto found_attr;
908                         }
909                 }
910                 DPRINT("cannot find attribute %s\n", s);
911                 return PFM_ERR_ATTR;
912 found_attr:
913                 type = ainfo->type;
914
915                 if (type == PFM_ATTR_UMASK) {
916                         has_um = 1;
917                         if (has_raw_um) {
918                                 DPRINT("cannot mix raw umask with umask\n");
919                                 return PFM_ERR_ATTR;
920                         }
921                 }
922
923                 if (ainfo->equiv) {
924                         char *z;
925
926                         /* cannot have equiv for attributes with value */
927                         if (has_val)
928                                 return PFM_ERR_ATTR_VAL;
929
930                         /* copy because it is const */
931                         z = strdup(ainfo->equiv);
932                         if (!z)
933                                 return PFM_ERR_NOMEM;
934
935                         ret = pfmlib_parse_event_attr(z, d);
936
937                         free(z);
938
939                         if (ret != PFM_SUCCESS)
940                                 return ret;
941                         s = p;
942                         continue;
943                 }
944                 /*
945                  * we tolerate missing value for boolean attributes.
946                  * Presence of the attribute is equivalent to
947                  * attr=1, i.e., attribute is set
948                  */
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 */
953                         goto handle_bool;
954                 }
955
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;
959
960                 if (has_val) {
961                         s = q;
962 handle_bool:
963                         ret = PFM_ERR_ATTR_VAL;
964                         if (!strlen(s))
965                                 goto error;
966                         if (d->nattrs == PFMLIB_MAX_ATTRS) {
967                                 DPRINT("too many attributes\n");
968                                 ret = PFM_ERR_TOOMANY;
969                                 goto error;
970                         }
971
972                         endptr = NULL;
973                         switch(type) {
974                         case PFM_ATTR_MOD_BOOL:
975                                 if (strlen(s) > 1)
976                                         goto error;
977
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;
984                                 else
985                                         goto error;
986                                 break;
987                         case PFM_ATTR_MOD_INTEGER:
988                                 d->attrs[d->nattrs].ival = strtoull(s, &endptr, 0);
989                                 if (*endptr != '\0')
990                                         goto error;
991                                 break;
992                         default:
993                                 goto error;
994                         }
995                 }
996                 d->attrs[d->nattrs].id = aidx;
997                 d->nattrs++;
998                 s = p;
999         }
1000         ret = PFM_SUCCESS;
1001 error:
1002         return ret;
1003 }
1004
1005 static int
1006 pfmlib_build_event_pattrs(pfmlib_event_desc_t  *e)
1007 {
1008         pfmlib_pmu_t *pmu;
1009         pfmlib_os_t *os;
1010         int i, ret, pmu_nattrs = 0, os_nattrs = 0;
1011         int npattrs;
1012
1013         /*
1014          * cannot satisfy request for an OS that was not activated
1015          */
1016         os = pfmlib_find_os(e->osid);
1017         if (!os)
1018                 return PFM_ERR_NOTSUPP;
1019
1020         pmu = e->pmu;
1021
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);
1027
1028         npattrs = pmu_nattrs + os_nattrs;
1029
1030         /*
1031          * add extra entry for raw umask, if supported
1032          */
1033         if (pmu->flags & PFMLIB_PMU_FL_RAW_UMASK)
1034                 npattrs++;
1035
1036         if (npattrs) {
1037                 e->pattrs = malloc(npattrs * sizeof(*e->pattrs));
1038                 if (!e->pattrs)
1039                         return PFM_ERR_NOMEM;
1040         }
1041
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)
1046                         goto error;
1047         }
1048         e->npattrs = pmu_nattrs;
1049
1050         if (os_nattrs) {
1051                 if (e->osid == os->id && os->get_os_attr_info) {
1052                         os->get_os_attr_info(os, e);
1053                         /*
1054                          * check for conflicts between HW and OS attributes
1055                          */
1056                         if (pmu->validate_pattrs[e->osid])
1057                                 pmu->validate_pattrs[e->osid](pmu, e);
1058                 }
1059         }
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);
1062
1063         return PFM_SUCCESS;
1064 error:
1065         free(e->pattrs);
1066         e->pattrs = NULL;
1067         return ret;
1068 }
1069
1070 void
1071 pfmlib_release_event(pfmlib_event_desc_t *e)
1072 {
1073         free(e->pattrs);
1074         e->pattrs = NULL;
1075 }
1076
1077 static int
1078 match_event(void *this, pfmlib_event_desc_t *d, const char *e, const char *s)
1079 {
1080         return strcasecmp(e, s);
1081 }
1082
1083 static int
1084 pfmlib_parse_equiv_event(const char *event, pfmlib_event_desc_t *d)
1085 {
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);
1089         char *str, *s, *p;
1090         int i;
1091         int ret;
1092
1093         /*
1094          * create copy because string is const
1095          */
1096         s = str = strdup(event);
1097         if (!str)
1098                 return PFM_ERR_NOMEM;
1099
1100         p = strchr(s, PFMLIB_ATTR_DELIM);
1101         if (p)
1102                 *p++ = '\0';
1103
1104         match = pmu->match_event ? pmu->match_event : match_event;
1105
1106         pfmlib_for_each_pmu_event(pmu, i) {
1107                 ret = pmu->get_event_info(pmu, i, &einfo);
1108                 if (ret != PFM_SUCCESS)
1109                         goto error;
1110                 if (!match(pmu, d, einfo.name, s))
1111                         goto found;
1112         }
1113         free(str);
1114         return PFM_ERR_NOTFOUND;
1115 found:
1116         d->pmu = pmu;
1117         d->event = i; /* private index */
1118
1119         /*
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
1123          */
1124         ret = pfmlib_build_event_pattrs(d);
1125         if (ret != PFM_SUCCESS)
1126                 goto error;
1127
1128         ret = pfmlib_parse_event_attr(p, d);
1129         if (ret == PFM_SUCCESS)
1130                 ret = pfmlib_sanitize_event(d);
1131 error:
1132         free(str);
1133
1134         if (ret != PFM_SUCCESS)
1135                 pfmlib_release_event(d);
1136
1137         return ret;
1138 }
1139
1140 int
1141 pfmlib_parse_event(const char *event, pfmlib_event_desc_t *d)
1142 {
1143         pfm_event_info_t einfo;
1144         char *str, *s, *p;
1145         pfmlib_pmu_t *pmu;
1146         int (*match)(void *this, pfmlib_event_desc_t *d, const char *e, const char *s);
1147         const char *pname = NULL;
1148         int i, j, ret;
1149
1150         /*
1151          * create copy because string is const
1152          */
1153         s = str = strdup(event);
1154         if (!str)
1155                 return PFM_ERR_NOMEM;
1156
1157         /*
1158          * ignore everything passed after a comma
1159          * (simplify dealing with const event list)
1160          *
1161          * safe to do before pname, because now
1162          * PMU name cannot have commas in them.
1163          */
1164         p = strchr(s, PFMLIB_EVENT_DELIM);
1165         if (p)
1166                 *p = '\0';
1167
1168         /* check for optional PMU name */
1169         p = strstr(s, PFMLIB_PMU_DELIM);
1170         if (p) {
1171                 *p = '\0';
1172                 pname = s;
1173                 s = p + strlen(PFMLIB_PMU_DELIM);
1174         }
1175         p = strchr(s, PFMLIB_ATTR_DELIM);
1176         if (p)
1177                 *p++ = '\0';
1178         /*
1179          * for each pmu
1180          */
1181         pfmlib_for_each_pmu(j) {
1182                 pmu = pfmlib_pmus[j];
1183                 /*
1184                  * if no explicit PMU name is given, then
1185                  * only look for active PMU models
1186                  */
1187                 if (!pname && !pfmlib_pmu_active(pmu))
1188                         continue;
1189                 /*
1190                  * check for requested PMU name,
1191                  */
1192                 if (pname && strcasecmp(pname, pmu->name))
1193                         continue;
1194                 /*
1195                  * only allow event on inactive PMU if enabled via
1196                  * environement variable
1197                  */
1198                 if (pname && !pfmlib_pmu_active(pmu) && !pfm_cfg.inactive)
1199                         continue;
1200
1201                 match = pmu->match_event ? pmu->match_event : match_event;
1202                 /*
1203                  * for each event
1204                  */
1205                 pfmlib_for_each_pmu_event(pmu, i) {
1206                         ret = pmu->get_event_info(pmu, i, &einfo);
1207                         if (ret != PFM_SUCCESS)
1208                                 goto error;
1209                         if (!match(pmu, d, einfo.name, s))
1210                                 goto found;
1211                 }
1212         }
1213         free(str);
1214         return PFM_ERR_NOTFOUND;
1215 found:
1216         d->pmu = pmu;
1217         /*
1218          * handle equivalence
1219          */
1220         if (einfo.equiv) {
1221                 ret = pfmlib_parse_equiv_event(einfo.equiv, d);
1222                 if (ret != PFM_SUCCESS)
1223                         goto error;
1224         } else {
1225                 d->event = i; /* private index */
1226
1227                 ret = pfmlib_build_event_pattrs(d);
1228                 if (ret != PFM_SUCCESS)
1229                         goto error;
1230         }
1231         /*
1232          * parse attributes from original event
1233          */
1234         ret = pfmlib_parse_event_attr(p, d);
1235         if (ret == PFM_SUCCESS)
1236                 ret = pfmlib_sanitize_event(d);
1237
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);
1242                 else
1243                         DPRINT("%d %d RAW_UMASK (0x%x)\n", d->event, i, a->idx);
1244         }
1245 error:
1246         free(str);
1247         if (ret != PFM_SUCCESS)
1248                 pfmlib_release_event(d);
1249         return ret;
1250 }
1251
1252 /* sorry, only English supported at this point! */
1253 static const char *pfmlib_err_list[]=
1254 {
1255         "success",
1256         "not supported",
1257         "invalid parameters",
1258         "pfmlib not initialized",
1259         "event not found",
1260         "invalid combination of model specific features",
1261         "invalid or missing unit mask",
1262         "out of memory",
1263         "invalid event attribute",
1264         "invalid event attribute value",
1265         "attribute value already set",
1266         "too many parameters",
1267         "parameter is too small",
1268 };
1269 static int pfmlib_err_count = (int)sizeof(pfmlib_err_list)/sizeof(char *);
1270
1271 const char *
1272 pfm_strerror(int code)
1273 {
1274         code = -code;
1275         if (code <0 || code >= pfmlib_err_count)
1276                 return "unknown error code";
1277
1278         return pfmlib_err_list[code];
1279 }
1280
1281 int
1282 pfm_get_version(void)
1283 {
1284         return LIBPFM_VERSION;
1285 }
1286
1287 int
1288 pfm_get_event_next(int idx)
1289 {
1290         pfmlib_pmu_t *pmu;
1291         int pidx;
1292
1293         pmu = pfmlib_idx2pidx(idx, &pidx);
1294         if (!pmu)
1295                 return -1;
1296
1297         pidx = pmu->get_event_next(pmu, pidx);
1298         return pidx == -1 ? -1 : pfmlib_pidx2idx(pmu, pidx);
1299 }
1300
1301 int
1302 pfm_get_os_event_encoding(const char *str, int dfl_plm, pfm_os_t uos, void *args)
1303 {
1304         pfmlib_os_t *os;
1305
1306         if (PFMLIB_INITIALIZED() == 0)
1307                 return PFM_ERR_NOINIT;
1308
1309         if (!(args && str))
1310                 return PFM_ERR_INVAL;
1311
1312         if (dfl_plm & ~(PFM_PLM_ALL))
1313                 return PFM_ERR_INVAL;
1314
1315         os = pfmlib_find_os(uos);
1316         if (!os)
1317                 return PFM_ERR_NOTSUPP;
1318
1319         return os->encode(os, str, dfl_plm, args);
1320 }
1321
1322 /*
1323  * old API maintained for backward compatibility with existing apps
1324  * prefer pfm_get_os_event_encoding()
1325  */
1326 int
1327 pfm_get_event_encoding(const char *str, int dfl_plm, char **fstr, int *idx, uint64_t **codes, int *count)
1328 {
1329         pfm_pmu_encode_arg_t arg;
1330         int ret;
1331
1332         if (!(str && codes && count))
1333                 return PFM_ERR_INVAL;
1334
1335         if ((*codes && !*count) || (!*codes && *count))
1336                 return PFM_ERR_INVAL;
1337
1338         memset(&arg, 0, sizeof(arg));
1339
1340         arg.fstr = fstr;
1341         arg.codes = *codes;
1342         arg.count = *count;
1343         arg.size  = sizeof(arg);
1344
1345         /*
1346          * request RAW PMU encoding
1347          */
1348         ret = pfm_get_os_event_encoding(str, dfl_plm, PFM_OS_NONE, &arg);
1349         if (ret != PFM_SUCCESS)
1350                 return ret;
1351
1352         /* handle the case where the array was allocated */
1353         *codes = arg.codes;
1354         *count = arg.count;
1355
1356         if (idx)
1357                 *idx = arg.idx;
1358
1359         return PFM_SUCCESS;
1360 }
1361
1362 static int
1363 pfmlib_check_event_pattrs(pfmlib_pmu_t *pmu, int pidx, pfm_os_t osid, FILE *fp)
1364 {
1365         pfmlib_event_desc_t e;
1366         int i, j, ret;
1367
1368         memset(&e, 0, sizeof(e));
1369         e.event = pidx;
1370         e.osid  = osid;
1371         e.pmu   = pmu;
1372
1373         ret = pfmlib_build_event_pattrs(&e);
1374         if (ret != PFM_SUCCESS) {
1375                 fprintf(fp, "invalid pattrs for event %d\n", pidx);
1376                 return ret;
1377         }
1378
1379         ret = PFM_ERR_ATTR;
1380
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);
1385                                 goto error;
1386                         }
1387                 }
1388         }
1389         ret = PFM_SUCCESS;
1390 error:
1391         /*
1392          * release resources allocated for event
1393          */
1394         pfmlib_release_event(&e);
1395         return ret;
1396 }
1397
1398 static int
1399 pfmlib_validate_encoding(char *buf, int plm)
1400 {
1401         uint64_t *codes = NULL;
1402         int count = 0, ret;
1403
1404         ret = pfm_get_event_encoding(buf, plm, NULL, NULL, &codes, &count);
1405         if (ret != PFM_SUCCESS) {
1406                 int i;
1407                 DPRINT("%s ", buf);
1408                 for(i=0; i < count; i++)
1409                         __pfm_dbprintf(" %#"PRIx64, codes[i]);
1410                 __pfm_dbprintf("\n");
1411         }
1412         if (codes)
1413                 free(codes);
1414
1415         return ret;
1416 }
1417
1418 static int
1419 pfmlib_pmu_validate_encoding(pfmlib_pmu_t *pmu, FILE *fp)
1420 {
1421         pfm_event_info_t einfo;
1422         pfm_event_attr_info_t ainfo;
1423         char *buf;
1424         size_t maxlen = 0, len;
1425         int i, u, n = 0, um;
1426         int ret, retval = PFM_SUCCESS;
1427
1428         pfmlib_for_each_pmu_event(pmu, i) {
1429                 ret = pmu->get_event_info(pmu, i, &einfo);
1430                 if (ret != PFM_SUCCESS)
1431                         return ret;
1432
1433                 ret = pfmlib_check_event_pattrs(pmu, i, PFM_OS_NONE, fp);
1434                 if (ret != PFM_SUCCESS)
1435                         return ret;
1436
1437                 len = strlen(einfo.name);
1438                 if (len > maxlen)
1439                         maxlen = len;
1440
1441                 for_each_pmu_event_attr(u, &einfo) {
1442                         ret = pmu->get_event_attr_info(pmu, i, u, &ainfo);
1443                         if (ret != PFM_SUCCESS)
1444                                 return ret;
1445
1446                         if (ainfo.type != PFM_ATTR_UMASK)
1447                                 continue;
1448
1449                         len = strlen(einfo.name) + strlen(ainfo.name);
1450                         if (len > maxlen)
1451                                 maxlen = len;
1452                 }
1453         }
1454         /* 2 = ::, 1=:, 1=eol */
1455         maxlen += strlen(pmu->name) + 2 + 1 + 1;
1456         buf = malloc(maxlen);
1457         if (!buf)
1458                 return PFM_ERR_NOMEM;
1459
1460         pfmlib_for_each_pmu_event(pmu, i) {
1461                 ret = pmu->get_event_info(pmu, i, &einfo);
1462                 if (ret != PFM_SUCCESS) {
1463                         retval = ret;
1464                         continue;
1465                 }
1466
1467                 um = 0;
1468                 for_each_pmu_event_attr(u, &einfo) {
1469                         ret = pmu->get_event_attr_info(pmu, i, u, &ainfo);
1470                         if (ret != PFM_SUCCESS) {
1471                                 retval = ret;
1472                                 continue;
1473                         }
1474
1475                         if (ainfo.type != PFM_ATTR_UMASK)
1476                                 continue;
1477
1478                         /*
1479                          * XXX: some events may require more than one umasks to encode
1480                          */
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))
1486                                                 continue;
1487                                 }
1488                                 /*
1489                                  * some PMU may not support raw encoding
1490                                  */
1491                                 if (ret != PFM_ERR_NOTSUPP) {
1492                                         fprintf(fp, "cannot encode event %s : %s\n", buf, pfm_strerror(ret));
1493                                         retval = ret;
1494                                 }
1495                                 continue;
1496                         }
1497                         um++;
1498                 }
1499                 if (um == 0) {
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))
1505                                                 continue;
1506                                 }
1507                                 if (ret != PFM_ERR_NOTSUPP) {
1508                                         fprintf(fp, "cannot encode event %s : %s\n", buf, pfm_strerror(ret));
1509                                         retval = ret;
1510                                 }
1511                                 continue;
1512                         }
1513                 }
1514                 n++;
1515         }
1516         free(buf);
1517
1518         return retval;
1519 }
1520
1521 int
1522 pfm_pmu_validate(pfm_pmu_t pmu_id, FILE *fp)
1523 {
1524         pfmlib_pmu_t *pmu, *pmx;
1525         int nos = 0;
1526         int i, ret;
1527
1528         if (fp == NULL)
1529                 return PFM_ERR_INVAL;
1530
1531         pmu = pmu2pmuidx(pmu_id);
1532         if (!pmu)
1533                 return PFM_ERR_INVAL;
1534
1535
1536         if (!pfmlib_pmu_initialized(pmu)) {
1537                 fprintf(fp, "pmu: %s :: initialization failed\n", pmu->name);
1538                 return PFM_ERR_INVAL;
1539         }
1540
1541         if (!pmu->name) {
1542                 fprintf(fp, "pmu id: %d :: no name\n", pmu->pmu);
1543                 return PFM_ERR_INVAL;
1544         }
1545
1546         if (!pmu->desc) {
1547                 fprintf(fp, "pmu: %s :: no description\n", pmu->name);
1548                 return PFM_ERR_INVAL;
1549         }
1550
1551         if (pmu->pmu >= PFM_PMU_MAX) {
1552                 fprintf(fp, "pmu: %s :: invalid PMU id\n", pmu->name);
1553                 return PFM_ERR_INVAL;
1554         }
1555
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;
1559         }
1560
1561         if (pfmlib_pmu_active(pmu)  && !pmu->pme_count) {
1562                 fprintf(fp, "pmu: %s :: no events\n", pmu->name);
1563                 return PFM_ERR_INVAL;
1564         }
1565         if (!pmu->pmu_detect) {
1566                 fprintf(fp, "pmu: %s :: missing pmu_detect callback\n", pmu->name);
1567                 return PFM_ERR_INVAL;
1568         }
1569         if (!pmu->get_event_first) {
1570                 fprintf(fp, "pmu: %s :: missing get_event_first callback\n", pmu->name);
1571                 return PFM_ERR_INVAL;
1572         }
1573         if (!pmu->get_event_next) {
1574                 fprintf(fp, "pmu: %s :: missing get_event_next callback\n", pmu->name);
1575                 return PFM_ERR_INVAL;
1576         }
1577         if (!pmu->get_event_info) {
1578                 fprintf(fp, "pmu: %s :: missing get_event_info callback\n", pmu->name);
1579                 return PFM_ERR_INVAL;
1580         }
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;
1584         }
1585         for (i = PFM_OS_NONE; i < PFM_OS_MAX; i++) {
1586                 if (pmu->get_event_encoding[i])
1587                         nos++;
1588         }
1589         if (!nos) {
1590                 fprintf(fp, "pmu: %s :: no os event encoding callback\n", pmu->name);
1591                 return PFM_ERR_INVAL;
1592         }
1593         if (!pmu->max_encoding) {
1594                 fprintf(fp, "pmu: %s :: max_encoding is zero\n", pmu->name);
1595                 return PFM_ERR_INVAL;
1596         }
1597
1598         /* look for duplicate names, id */
1599         pfmlib_for_each_pmu(i) {
1600                 pmx = pfmlib_pmus[i];
1601                 if (!pfmlib_pmu_active(pmx))
1602                         continue;
1603                 if (pmx == pmu)
1604                         continue;
1605                 if (!strcasecmp(pmx->name, pmu->name)) {
1606                         fprintf(fp, "pmu: %s :: duplicate name\n", pmu->name);
1607                         return PFM_ERR_INVAL;
1608                 }
1609                 if (pmx->pmu == pmu->pmu) {
1610                         fprintf(fp, "pmu: %s :: duplicate id\n", pmu->name);
1611                         return PFM_ERR_INVAL;
1612                 }
1613         }
1614
1615         if (pmu->validate_table) {
1616                 ret = pmu->validate_table(pmu, fp);
1617                 if (ret != PFM_SUCCESS)
1618                         return ret;
1619         }
1620         return pfmlib_pmu_validate_encoding(pmu, fp);
1621 }
1622
1623 int
1624 pfm_get_event_info(int idx, pfm_os_t os, pfm_event_info_t *uinfo)
1625 {
1626         pfm_event_info_t info;
1627         pfmlib_event_desc_t e;
1628         pfmlib_pmu_t *pmu;
1629         size_t sz = sizeof(info);
1630         int pidx, ret;
1631
1632         if (!PFMLIB_INITIALIZED())
1633                 return PFM_ERR_NOINIT;
1634
1635         if (os >= PFM_OS_MAX)
1636                 return PFM_ERR_INVAL;
1637
1638         pmu = pfmlib_idx2pidx(idx, &pidx);
1639         if (!pmu)
1640                 return PFM_ERR_INVAL;
1641
1642         if (!uinfo)
1643                 return PFM_ERR_INVAL;
1644
1645         sz = pfmlib_check_struct(uinfo, uinfo->size, PFM_EVENT_INFO_ABI0, sz);
1646         if (!sz)
1647                 return PFM_ERR_INVAL;
1648
1649         memset(&info, 0, sizeof(info));
1650
1651         info.size = sz;
1652
1653         /* default data type is uint64 */
1654         info.dtype = PFM_DTYPE_UINT64;
1655
1656         /* reset flags */
1657         info.is_precise = 0;
1658
1659         ret = pmu->get_event_info(pmu, pidx, &info);
1660         if (ret != PFM_SUCCESS)
1661                 return ret;
1662
1663         info.pmu = pmu->pmu;
1664         info.idx = idx;
1665
1666         memset(&e, 0, sizeof(e));
1667         e.event = pidx;
1668         e.osid  = os;
1669         e.pmu   = pmu;
1670
1671         ret = pfmlib_build_event_pattrs(&e);
1672         if (ret == PFM_SUCCESS) {
1673                 info.nattrs = e.npattrs;
1674                 memcpy(uinfo, &info, sz);
1675         }
1676
1677         pfmlib_release_event(&e);
1678         return ret;
1679 }
1680
1681 int
1682 pfm_get_event_attr_info(int idx, int attr_idx, pfm_os_t os, pfm_event_attr_info_t *uinfo)
1683 {
1684         pfm_event_attr_info_t info;
1685         pfmlib_event_desc_t e;
1686         pfmlib_pmu_t *pmu;
1687         size_t sz = sizeof(info);
1688         int pidx, ret;
1689
1690         if (!PFMLIB_INITIALIZED())
1691                 return PFM_ERR_NOINIT;
1692
1693         if (attr_idx < 0)
1694                 return PFM_ERR_INVAL;
1695
1696         if (os >= PFM_OS_MAX)
1697                 return PFM_ERR_INVAL;
1698
1699         pmu = pfmlib_idx2pidx(idx, &pidx);
1700         if (!pmu)
1701                 return PFM_ERR_INVAL;
1702
1703         if (!uinfo)
1704                 return PFM_ERR_INVAL;
1705
1706         sz = pfmlib_check_struct(uinfo, uinfo->size, PFM_ATTR_INFO_ABI0, sz);
1707         if (!sz)
1708                 return PFM_ERR_INVAL;
1709
1710         memset(&e, 0, sizeof(e));
1711         e.event = pidx;
1712         e.osid  = os;
1713         e.pmu   = pmu;
1714
1715         ret = pfmlib_build_event_pattrs(&e);
1716         if (ret != PFM_SUCCESS)
1717                 return ret;
1718
1719         ret = PFM_ERR_INVAL;
1720
1721         if (attr_idx >= e.npattrs)
1722                 goto error;
1723
1724         /*
1725          * copy event_attr_info
1726          */
1727         info = e.pattrs[attr_idx];
1728
1729         /*
1730          * rewrite size to reflect what we are returning
1731          */
1732         info.size = sz;
1733         /*
1734          * info.idx = private, namespace specific index,
1735          * should not be visible externally, so override
1736          * with public index
1737          */
1738         info.idx  = attr_idx;
1739
1740         memcpy(uinfo, &info, sz);
1741
1742         ret = PFM_SUCCESS;
1743 error:
1744         pfmlib_release_event(&e);
1745         return ret;
1746 }
1747
1748 int
1749 pfm_get_pmu_info(pfm_pmu_t pmuid, pfm_pmu_info_t *uinfo)
1750 {
1751         pfm_pmu_info_t info;
1752         pfmlib_pmu_t *pmu;
1753         size_t sz = sizeof(info);
1754         int pidx;
1755
1756         if (!PFMLIB_INITIALIZED())
1757                 return PFM_ERR_NOINIT;
1758
1759         if (pmuid >= PFM_PMU_MAX)
1760                 return PFM_ERR_INVAL;
1761
1762         if (!uinfo)
1763                 return PFM_ERR_INVAL;
1764
1765         sz = pfmlib_check_struct(uinfo, uinfo->size, PFM_PMU_INFO_ABI0, sz);
1766         if (!sz)
1767                 return PFM_ERR_INVAL;
1768  
1769         pmu = pfmlib_pmus_map[pmuid];
1770         if (!pmu)
1771                 return PFM_ERR_NOTSUPP;
1772
1773         info.name = pmu->name;
1774         info.desc = pmu->desc;
1775         info.pmu  = pmuid;
1776         info.size = sz;
1777
1778         info.max_encoding    = pmu->max_encoding;
1779         info.num_cntrs       = pmu->num_cntrs;
1780         info.num_fixed_cntrs = pmu->num_fixed_cntrs;
1781
1782         pidx = pmu->get_event_first(pmu);
1783         if (pidx == -1)
1784                 info.first_event = -1;
1785         else
1786                 info.first_event = pfmlib_pidx2idx(pmu, pidx);
1787
1788         /*
1789          * XXX: pme_count only valid when PMU is detected
1790          */
1791         info.is_present = pfmlib_pmu_active(pmu);
1792         info.is_dfl     = !!(pmu->flags & PFMLIB_PMU_FL_ARCH_DFL);
1793         info.type       = pmu->type;
1794
1795         if (pmu->get_num_events)
1796                 info.nevents = pmu->get_num_events(pmu);
1797         else
1798                 info.nevents    = pmu->pme_count;
1799
1800         memcpy(uinfo, &info, sz);
1801
1802         return PFM_SUCCESS;
1803 }
1804
1805 pfmlib_pmu_t *
1806 pfmlib_get_pmu_by_type(pfm_pmu_type_t t)
1807 {
1808         pfmlib_pmu_t *pmu;
1809         int i;
1810
1811         pfmlib_for_each_pmu(i) {
1812                 pmu = pfmlib_pmus[i];
1813
1814                 if (!pfmlib_pmu_active(pmu))
1815                         continue;
1816
1817                 /* first match */
1818                 if (pmu->type != t)
1819                         continue;
1820
1821                 return pmu;
1822         }
1823         return NULL;
1824 }
1825
1826 static int
1827 pfmlib_compare_attr_id(const void *a, const void *b)
1828 {
1829         const pfmlib_attr_t *t1 = a;
1830         const pfmlib_attr_t *t2 = b;
1831
1832         if (t1->id < t2->id)
1833                 return -1;
1834         return t1->id == t2->id ? 0 : 1;
1835 }
1836
1837 void
1838 pfmlib_sort_attr(pfmlib_event_desc_t *e)
1839 {
1840         qsort(e->attrs, e->nattrs, sizeof(pfmlib_attr_t), pfmlib_compare_attr_id);
1841 }
1842
1843 static int
1844 pfmlib_raw_pmu_encode(void *this, const char *str, int dfl_plm, void *data)
1845 {
1846         pfm_pmu_encode_arg_t arg;
1847         pfm_pmu_encode_arg_t *uarg = data;
1848
1849         pfmlib_pmu_t *pmu;
1850         pfmlib_event_desc_t e;
1851         size_t sz = sizeof(arg);
1852         int ret, i;
1853
1854         sz = pfmlib_check_struct(uarg, uarg->size, PFM_RAW_ENCODE_ABI0, sz);
1855         if (!sz)
1856                 return PFM_ERR_INVAL;
1857
1858         memset(&arg, 0, sizeof(arg));
1859
1860         /*
1861          * get input data
1862          */
1863         memcpy(&arg, uarg, sz);
1864
1865         memset(&e, 0, sizeof(e));
1866
1867         e.osid    = PFM_OS_NONE;
1868         e.dfl_plm = dfl_plm;
1869
1870         ret = pfmlib_parse_event(str, &e);
1871         if (ret != PFM_SUCCESS)
1872                 return ret;
1873
1874         pmu = e.pmu;
1875
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;
1879         }
1880
1881         ret = pmu->get_event_encoding[PFM_OS_NONE](pmu, &e);
1882         if (ret != PFM_SUCCESS)
1883                 goto error;
1884         /*
1885          * return opaque event identifier
1886          */
1887         arg.idx = pfmlib_pidx2idx(e.pmu, e.event);
1888
1889         if (arg.codes == NULL) {
1890                 ret = PFM_ERR_NOMEM;
1891                 arg.codes = malloc(sizeof(uint64_t) * e.count);
1892                 if (!arg.codes)
1893                         goto error_fstr;
1894         } else if (arg.count < e.count) {
1895                 ret = PFM_ERR_TOOSMALL;
1896                 goto error_fstr;
1897         }
1898
1899         arg.count = e.count;
1900
1901         for (i = 0; i < e.count; i++)
1902                 arg.codes[i] = e.codes[i];
1903
1904         if (arg.fstr) {
1905                 ret = pfmlib_build_fstr(&e, arg.fstr);
1906                 if (ret != PFM_SUCCESS)
1907                         goto error;
1908         }
1909
1910         ret = PFM_SUCCESS;
1911
1912         /* copy out results */
1913         memcpy(uarg, &arg, sz);
1914
1915 error_fstr:
1916         if (ret != PFM_SUCCESS)
1917                 free(arg.fstr);
1918 error:
1919         /*
1920          * release resources allocated for event
1921          */
1922         pfmlib_release_event(&e);
1923         return ret;
1924 }
1925
1926 static int
1927 pfmlib_raw_pmu_detect(void *this)
1928 {
1929         return PFM_SUCCESS;
1930 }
1931
1932 static pfmlib_os_t pfmlib_os_none= {
1933         .name = "No OS (raw PMU)",
1934         .id = PFM_OS_NONE,
1935         .flags = PFMLIB_OS_FL_ACTIVATED,
1936         .encode = pfmlib_raw_pmu_encode,
1937         .detect = pfmlib_raw_pmu_detect,
1938 };