PAPI 7.1.0.0
Loading...
Searching...
No Matches
pfmlib_gen_ia32.c
Go to the documentation of this file.
1/*
2 * pfmlib_gen_ia32.c : Intel architectural PMU v1, v2, v3
3 *
4 * The file provides support for the Intel architectural PMU v1 and v2.
5 *
6 * Copyright (c) 2005-2007 Hewlett-Packard Development Company, L.P.
7 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
8 *
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
14 * of the Software, and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in all
18 * copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
22 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
24 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
25 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 *
28 * This file implements supports for the IA-32 architectural PMU as specified
29 * in the following document:
30 * "IA-32 Intel Architecture Software Developer's Manual - Volume 3B: System
31 * Programming Guide"
32 */
33#include <sys/types.h>
34#include <ctype.h>
35#include <string.h>
36#include <stdlib.h>
37#include <stdio.h>
38
39/* public headers */
41
42/* private headers */
43#include "pfmlib_priv.h" /* library private */
44#include "pfmlib_gen_ia32_priv.h" /* architecture private */
45
46#include "gen_ia32_events.h" /* architected event table */
47
48/* let's define some handy shortcuts! */
49#define sel_event_select perfevtsel.sel_event_select
50#define sel_unit_mask perfevtsel.sel_unit_mask
51#define sel_usr perfevtsel.sel_usr
52#define sel_os perfevtsel.sel_os
53#define sel_edge perfevtsel.sel_edge
54#define sel_pc perfevtsel.sel_pc
55#define sel_int perfevtsel.sel_int
56#define sel_any perfevtsel.sel_any
57#define sel_en perfevtsel.sel_en
58#define sel_inv perfevtsel.sel_inv
59#define sel_cnt_mask perfevtsel.sel_cnt_mask
60
62
63/*
64 * Description of the PMC/PMD register mappings use by
65 * this module (as reported in pfmlib_reg_t.reg_num)
66 *
67 * For V1 (up to 16 generic counters 0-15):
68 *
69 * 0 -> PMC0 -> PERFEVTSEL0 -> MSR @ 0x186
70 * 1 -> PMC1 -> PERFEVTSEL1 -> MSR @ 0x187
71 * ...
72 * n -> PMCn -> PERFEVTSELn -> MSR @ 0x186+n
73 *
74 * 0 -> PMD0 -> IA32_PMC0 -> MSR @ 0xc1
75 * 1 -> PMD1 -> IA32_PMC1 -> MSR @ 0xc2
76 * ...
77 * n -> PMDn -> IA32_PMCn -> MSR @ 0xc1+n
78 *
79 * For V2 (up to 16 generic and 16 fixed counters):
80 *
81 * 0 -> PMC0 -> PERFEVTSEL0 -> MSR @ 0x186
82 * 1 -> PMC1 -> PERFEVTSEL1 -> MSR @ 0x187
83 * ...
84 * 15 -> PMC15 -> PERFEVTSEL15 -> MSR @ 0x186+15
85 *
86 * 16 -> PMC16 -> IA32_FIXED_CTR_CTRL -> MSR @ 0x38d
87 *
88 * 0 -> PMD0 -> IA32_PMC0 -> MSR @ 0xc1
89 * 1 -> PMD1 -> IA32_PMC1 -> MSR @ 0xc2
90 * ...
91 * 15 -> PMD15 -> IA32_PMC15 -> MSR @ 0xc1+15
92 *
93 * 16 -> PMD16 -> IA32_FIXED_CTR0 -> MSR @ 0x309
94 * 17 -> PMD17 -> IA32_FIXED_CTR1 -> MSR @ 0x30a
95 * ...
96 * n -> PMDn -> IA32_FIXED_CTRn -> MSR @ 0x309+n
97 */
98#define GEN_IA32_SEL_BASE 0x186
99#define GEN_IA32_CTR_BASE 0xc1
100#define GEN_IA32_FIXED_CTR_BASE 0x309
101
102#define FIXED_PMD_BASE 16
103
104#define PFMLIB_GEN_IA32_ALL_FLAGS \
105 (PFM_GEN_IA32_SEL_INV|PFM_GEN_IA32_SEL_EDGE|PFM_GEN_IA32_SEL_ANYTHR)
106
107static char * pfm_gen_ia32_get_event_name(unsigned int i);
108
110
113
114#ifdef __i386__
115static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx,
116 unsigned int *ecx, unsigned int *edx)
117{
118 /*
119 * because ebx is used in Pic mode, we need to save/restore because
120 * cpuid clobbers it. I could not figure out a way to get ebx out in
121 * one cpuid instruction. To extract ebx, we need to move it to another
122 * register (here eax)
123 */
124 __asm__("pushl %%ebx;cpuid; popl %%ebx"
125 :"=a" (*eax)
126 : "a" (op)
127 : "ecx", "edx");
128
129 __asm__("pushl %%ebx;cpuid; movl %%ebx, %%eax;popl %%ebx"
130 :"=a" (*ebx)
131 : "a" (op)
132 : "ecx", "edx");
133}
134#else
135static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx,
136 unsigned int *ecx, unsigned int *edx)
137{
138 __asm__("cpuid"
139 : "=a" (*eax),
140 "=b" (*ebx),
141 "=c" (*ecx),
142 "=d" (*edx)
143 : "0" (op), "c"(0));
144}
145#endif
146
148
149/*
150 * create architected event table
151 */
152static int
153create_arch_event_table(unsigned int mask)
154{
156 unsigned int i, num_events = 0;
157 unsigned int m;
158
159 /*
160 * first pass: count the number of supported events
161 */
162 m = mask;
163 for(i=0; i < 7; i++, m>>=1) {
164 if ((m & 0x1) == 0)
165 num_events++;
166 }
168
170 if (gen_ia32_pe == NULL)
171 return PFMLIB_ERR_NOTSUPP;
172
173 /*
174 * second pass: populate the table
175 */
177 m = mask;
178 for(i=0, pe = gen_ia32_pe; i < 7; i++, m>>=1) {
179 if ((m & 0x1) == 0) {
180 *pe = gen_ia32_all_pe[i];
181 /*
182 * setup default event: cycles and inst_retired
183 */
188 pe++;
189 }
190 }
191 return PFMLIB_SUCCESS;
192}
193
194static int
196{
197 union {
198 unsigned int val;
199 pmu_eax_t eax;
200 pmu_edx_t edx;
201 } eax, ecx, edx, ebx;
202
203 /*
204 * check family number to reject for processors
205 * older than Pentium (family=5). Those processors
206 * did not have the CPUID instruction
207 */
208 if (family < 5)
209 return PFMLIB_ERR_NOTSUPP;
210
211 /*
212 * check if CPU supports 0xa function of CPUID
213 * 0xa started with Core Duo. Needed to detect if
214 * architected PMU is present
215 */
216 cpuid(0x0, &eax.val, &ebx.val, &ecx.val, &edx.val);
217 if (eax.val < 0xa)
218 return PFMLIB_ERR_NOTSUPP;
219
220 /*
221 * extract architected PMU information
222 */
223 cpuid(0xa, &eax.val, &ebx.val, &ecx.val, &edx.val);
224
225 /*
226 * version must be greater than zero
227 */
228 return eax.eax.version < 1 ? PFMLIB_ERR_NOTSUPP : PFMLIB_SUCCESS;
229}
230
231static int
233{
234 int ret, family;
235 char buffer[128];
236
237 ret = __pfm_getcpuinfo_attr("vendor_id", buffer, sizeof(buffer));
238 if (ret == -1)
239 return PFMLIB_ERR_NOTSUPP;
240
241 if (strcmp(buffer, "GenuineIntel"))
242 return PFMLIB_ERR_NOTSUPP;
243
244 ret = __pfm_getcpuinfo_attr("cpu family", buffer, sizeof(buffer));
245 if (ret == -1)
246 return PFMLIB_ERR_NOTSUPP;
247
248 family = atoi(buffer);
249
250 return check_arch_pmu(family);
251}
252
253static int
255{
256 union {
257 unsigned int val;
258 pmu_eax_t eax;
259 pmu_edx_t edx;
260 } eax, ecx, edx, ebx;
261 unsigned int num_cnt, i;
262 int ret;
263
264 /*
265 * extract architected PMU information
266 */
267 if (forced_pmu == PFMLIB_NO_PMU) {
268 cpuid(0xa, &eax.val, &ebx.val, &ecx.val, &edx.val);
269 } else {
270 /*
271 * when forced, simulate v2
272 * with 2 generic and 3 fixed counters
273 */
274 eax.eax.version = 3;
275 eax.eax.num_cnt = 2;
276 eax.eax.cnt_width = 40;
277 eax.eax.ebx_length = 0; /* unused */
278 ebx.val = 0;
279 edx.edx.num_cnt = 3;
280 edx.edx.cnt_width = 40;
281 }
282
283 num_cnt = eax.eax.num_cnt;
284 pmu_version = eax.eax.version;
285
286 /*
287 * populate impl_pm* bitmasks for generic counters
288 */
289 for(i=0; i < num_cnt; i++) {
292 }
293
294 /* check for fixed counters */
295 if (pmu_version >= 2) {
296 /*
297 * As described in IA-32 Developer's manual vol 3b
298 * in section 18.12.2.1, early processors supporting
299 * V2 may report invalid information concerning the fixed
300 * counters. So we compensate for this here by forcing
301 * num_cnt to 3.
302 */
303 if (edx.edx.num_cnt == 0)
304 edx.edx.num_cnt = 3;
305
306 for(i=0; i < edx.edx.num_cnt; i++)
308 if (i)
310
311 }
312
313 num_gen_cnt = eax.eax.num_cnt;
314 num_fixed_cnt = edx.edx.num_cnt;
315
319
320 __pfm_vbprintf("Intel architected PMU: version=%d num_gen=%u num_fixed=%u pmc=%u pmd=%d\n",
325
326 ret = create_arch_event_table(ebx.val);
327 if (ret != PFMLIB_SUCCESS)
328 return ret;
329
331
332 return PFMLIB_SUCCESS;
333}
334
335static int
337{
338 pfmlib_gen_ia32_input_param_t *param = mod_in;
342 pfmlib_reg_t *pc, *pd;
343 pfmlib_regmask_t *r_pmcs;
344 unsigned long plm;
345 unsigned int i, j, cnt, k, ucode, val;
346 unsigned int assign[PMU_GEN_IA32_MAX_COUNTERS];
347
348 e = inp->pfp_events;
349 pc = outp->pfp_pmcs;
350 pd = outp->pfp_pmds;
351 cnt = inp->pfp_event_count;
352 r_pmcs = &inp->pfp_unavail_pmcs;
353 cntrs = param ? param->pfp_gen_ia32_counters : NULL;
354
355 if (PFMLIB_DEBUG()) {
356 for (j=0; j < cnt; j++) {
357 DPRINT("ev[%d]=%s\n", j, gen_ia32_pe[e[j].event].pme_name);
358 }
359 }
360
361 if (cnt > gen_support->pmd_count)
362 return PFMLIB_ERR_TOOMANY;
363
364 for(i=0, j=0; j < cnt; j++) {
365 if (e[j].plm & (PFM_PLM1|PFM_PLM2)) {
366 DPRINT("event=%d invalid plm=%d\n", e[j].event, e[j].plm);
367 return PFMLIB_ERR_INVAL;
368 }
369
370 if (e[j].flags & ~PFMLIB_GEN_IA32_ALL_FLAGS) {
371 DPRINT("event=%d invalid flags=0x%lx\n", e[j].event, e[j].flags);
372 return PFMLIB_ERR_INVAL;
373 }
374
375 if (cntrs && pmu_version != 3 && (cntrs[j].flags & PFM_GEN_IA32_SEL_ANYTHR)) {
376 DPRINT("event=%d anythread requires architectural perfmon v3", e[j].event);
377 return PFMLIB_ERR_INVAL;
378 }
379 /*
380 * exclude restricted registers from assignment
381 */
382 while(i < gen_support->pmc_count && pfm_regmask_isset(r_pmcs, i)) i++;
383
384 if (i == gen_support->pmc_count)
385 return PFMLIB_ERR_TOOMANY;
386
387 /*
388 * events can be assigned to any counter
389 */
390 assign[j] = i++;
391 }
392
393 for (j=0; j < cnt ; j++ ) {
394 reg.val = 0; /* assume reserved bits are zerooed */
395
396 /* if plm is 0, then assume not specified per-event and use default */
397 plm = e[j].plm ? e[j].plm : inp->pfp_dfl_plm;
398
399 val = gen_ia32_pe[e[j].event].pme_code;
400
401 reg.sel_event_select = val & 0xff;
402
403 ucode = (val >> 8) & 0xff;
404
405 for(k=0; k < e[j].num_masks; k++)
406 ucode |= gen_ia32_pe[e[j].event].pme_umasks[e[j].unit_masks[k]].pme_ucode;
407
408 val |= ucode << 8;
409
410 reg.sel_unit_mask = ucode; /* use 8 least significant bits */
411 reg.sel_usr = plm & PFM_PLM3 ? 1 : 0;
412 reg.sel_os = plm & PFM_PLM0 ? 1 : 0;
413 reg.sel_en = 1; /* force enable bit to 1 */
414 reg.sel_int = 1; /* force APIC int to 1 */
415
416 reg.sel_cnt_mask = val >>24;
417 reg.sel_inv = val >> 23;
418 reg.sel_any = val >> 21;;
419 reg.sel_edge = val >> 18;
420
421 if (cntrs) {
422 if (!reg.sel_cnt_mask) {
423 /*
424 * counter mask is 8-bit wide, do not silently
425 * wrap-around
426 */
427 if (cntrs[i].cnt_mask > 255)
428 return PFMLIB_ERR_INVAL;
429 reg.sel_cnt_mask = cntrs[j].cnt_mask;
430 }
431
432 if (!reg.sel_edge)
433 reg.sel_edge = cntrs[j].flags & PFM_GEN_IA32_SEL_EDGE ? 1 : 0;
434 if (!reg.sel_inv)
435 reg.sel_inv = cntrs[j].flags & PFM_GEN_IA32_SEL_INV ? 1 : 0;
436 }
437
438 pc[j].reg_num = assign[j];
439 pc[j].reg_addr = GEN_IA32_SEL_BASE+assign[j];
440 pc[j].reg_value = reg.val;
441
442 pd[j].reg_num = assign[j];
443 pd[j].reg_addr = GEN_IA32_CTR_BASE+assign[j];
444
445 __pfm_vbprintf("[PERFEVTSEL%u(pmc%u)=0x%llx event_sel=0x%x umask=0x%x os=%d usr=%d en=%d int=%d inv=%d edge=%d cnt_mask=%d] %s\n",
446 assign[j],
447 assign[j],
448 reg.val,
450 reg.sel_unit_mask,
451 reg.sel_os,
452 reg.sel_usr,
453 reg.sel_en,
454 reg.sel_int,
455 reg.sel_inv,
456 reg.sel_edge,
457 reg.sel_cnt_mask,
459
460 __pfm_vbprintf("[PMC%u(pmd%u)]\n", pd[j].reg_num, pd[j].reg_num);
461 }
462 /* number of evtsel registers programmed */
463 outp->pfp_pmc_count = cnt;
464 outp->pfp_pmd_count = cnt;
465
466 return PFMLIB_SUCCESS;
467}
468
469static const char *fixed_event_names[]={ "INSTRUCTIONS_RETIRED", "UNHALTED_CORE_CYCLES ", "UNHALTED_REFERENCE_CYCLES " };
470#define MAX_EVENT_NAMES (sizeof(fixed_event_names)/sizeof(char *))
471
472static int
474{
475#define HAS_OPTIONS(x) (cntrs && (cntrs[i].flags || cntrs[i].cnt_mask))
476#define is_fixed_pmc(a) (a > 15)
477
481 pfmlib_reg_t *pc, *pd;
482 pfmlib_regmask_t *r_pmcs;
483 uint64_t val;
484 unsigned long plm;
485 unsigned int fixed_ctr_mask;
486 unsigned int npc = 0;
487 unsigned int i, j, n, k, ucode;
488 unsigned int assign[PMU_GEN_IA32_MAX_COUNTERS];
489 unsigned int next_gen, last_gen;
490
491 e = inp->pfp_events;
492 pc = outp->pfp_pmcs;
493 pd = outp->pfp_pmds;
494 n = inp->pfp_event_count;
495 r_pmcs = &inp->pfp_unavail_pmcs;
496 cntrs = param ? param->pfp_gen_ia32_counters : NULL;
497
498 if (n > gen_support->pmd_count)
499 return PFMLIB_ERR_TOOMANY;
500
501 /*
502 * initilize to empty
503 */
504 for(i=0; i < n; i++)
505 assign[i] = -1;
506
507 /*
508 * error checking
509 */
510 for(j=0; j < n; j++) {
511 /*
512 * only supports two priv levels for perf counters
513 */
514 if (e[j].plm & (PFM_PLM1|PFM_PLM2))
515 return PFMLIB_ERR_INVAL;
516
517 /*
518 * check for valid flags
519 */
520 if (cntrs && cntrs[j].flags & ~PFMLIB_GEN_IA32_ALL_FLAGS)
521 return PFMLIB_ERR_INVAL;
522
523 if (cntrs && pmu_version != 3 && (cntrs[j].flags & PFM_GEN_IA32_SEL_ANYTHR)) {
524 DPRINT("event=%d anythread requires architectural perfmon v3", e[j].event);
525 return PFMLIB_ERR_INVAL;
526 }
527 }
528
529 next_gen = 0; /* first generic counter */
530 last_gen = num_gen_cnt - 1; /* last generic counter */
531
532 fixed_ctr_mask = (1 << num_fixed_cnt) - 1;
533 /*
534 * first constraint: fixed counters (try using them first)
535 */
536 if (fixed_ctr_mask) {
537 for(i=0; i < n; i++) {
538 /* fixed counters do not support event options (filters) */
539 if (HAS_OPTIONS(i)) {
540 if (pmu_version != 3)
541 continue;
542 if (cntrs[i].flags != PFM_GEN_IA32_SEL_ANYTHR)
543 continue;
544 /* ok for ANYTHR */
545 }
546 for(j=0; j < num_fixed_cnt; j++) {
547 if ((fixed_ctr_mask & (1<<j)) && gen_ia32_pe[e[i].event].pme_fixed == (FIXED_PMD_BASE+j)) {
548 assign[i] = FIXED_PMD_BASE+j;
549 fixed_ctr_mask &= ~(1<<j);
550 break;
551 }
552 }
553 }
554 }
555 /*
556 * assign what is left
557 */
558 for(i=0; i < n; i++) {
559 if (assign[i] == -1) {
560 for(; next_gen <= last_gen; next_gen++) {
561 if (!pfm_regmask_isset(r_pmcs, next_gen))
562 break;
563 }
564 if (next_gen <= last_gen)
565 assign[i] = next_gen++;
566 else
567 return PFMLIB_ERR_NOASSIGN;
568 }
569 }
570 j = 0;
571
572 /* setup fixed counters */
573 reg.val = 0;
574 k = 0;
575 for (i=0; i < n ; i++ ) {
576 if (!is_fixed_pmc(assign[i]))
577 continue;
578 val = 0;
579 /* if plm is 0, then assume not specified per-event and use default */
580 plm = e[i].plm ? e[i].plm : inp->pfp_dfl_plm;
581 if (plm & PFM_PLM0)
582 val |= 1ULL;
583 if (plm & PFM_PLM3)
584 val |= 2ULL;
585
586 /* only possible for v3 */
587 if (cntrs && cntrs[i].flags & PFM_GEN_IA32_SEL_ANYTHR)
588 val |= 4ULL;
589
590 val |= 1ULL << 3; /* force APIC int (kernel may force it anyway) */
591
592 reg.val |= val << ((assign[i]-FIXED_PMD_BASE)<<2);
593
594 /* setup pd array */
595 pd[i].reg_num = assign[i];
597 }
598
599 if (reg.val) {
600 pc[npc].reg_num = 16;
601 pc[npc].reg_value = reg.val;
602 pc[npc].reg_addr = 0x38D;
603
604 __pfm_vbprintf("[FIXED_CTRL(pmc%u)=0x%"PRIx64,
605 pc[npc].reg_num,
606 reg.val);
607
608 for(i=0; i < num_fixed_cnt; i++) {
609 if (pmu_version != 3)
610 __pfm_vbprintf(" pmi%d=1 en%d=0x%"PRIx64,
611 i, i,
612 (reg.val >> (i*4)) & 0x3ULL);
613 else
614 __pfm_vbprintf(" pmi%d=1 en%d=0x%"PRIx64 " any%d=%"PRId64,
615 i, i,
616 (reg.val >> (i*4)) & 0x3ULL,
617 i,
618 !!((reg.val >> (i*4)) & 0x4ULL));
619 }
620
621 __pfm_vbprintf("] ");
622 for(i=0; i < num_fixed_cnt; i++) {
623 if ((fixed_ctr_mask & (0x1 << i)) == 0) {
624 if (i < MAX_EVENT_NAMES)
626 else
627 __pfm_vbprintf("??? ");
628 }
629 }
630 __pfm_vbprintf("\n");
631
632 npc++;
633
634 for (i=0; i < n ; i++ ) {
635 if (!is_fixed_pmc(assign[i]))
636 continue;
637 __pfm_vbprintf("[FIXED_CTR%u(pmd%u)]\n", pd[i].reg_num, pd[i].reg_num);
638 }
639 }
640
641 for (i=0; i < n ; i++ ) {
642 /* skip fixed counters */
643 if (is_fixed_pmc(assign[i]))
644 continue;
645
646 reg.val = 0; /* assume reserved bits are zerooed */
647
648 /* if plm is 0, then assume not specified per-event and use default */
649 plm = e[i].plm ? e[i].plm : inp->pfp_dfl_plm;
650
651 val = gen_ia32_pe[e[i].event].pme_code;
652
653 reg.sel_event_select = val & 0xff;
654
655 ucode = (val >> 8) & 0xff;
656
657 for(k=0; k < e[i].num_masks; k++)
658 ucode |= gen_ia32_pe[e[i].event].pme_umasks[e[i].unit_masks[k]].pme_ucode;
659
660 val |= ucode << 8;
661
662 reg.sel_unit_mask = ucode;
663 reg.sel_usr = plm & PFM_PLM3 ? 1 : 0;
664 reg.sel_os = plm & PFM_PLM0 ? 1 : 0;
665 reg.sel_en = 1; /* force enable bit to 1 */
666 reg.sel_int = 1; /* force APIC int to 1 */
667
668 reg.sel_cnt_mask = val >>24;
669 reg.sel_inv = val >> 23;
670 reg.sel_any = val >> 21;;
671 reg.sel_edge = val >> 18;
672
673 if (cntrs) {
674 if (!reg.sel_cnt_mask) {
675 /*
676 * counter mask is 8-bit wide, do not silently
677 * wrap-around
678 */
679 if (cntrs[i].cnt_mask > 255)
680 return PFMLIB_ERR_INVAL;
681 reg.sel_cnt_mask = cntrs[i].cnt_mask;
682 }
683 if (!reg.sel_edge)
684 reg.sel_edge = cntrs[i].flags & PFM_GEN_IA32_SEL_EDGE ? 1 : 0;
685 if (!reg.sel_inv)
686 reg.sel_inv = cntrs[i].flags & PFM_GEN_IA32_SEL_INV ? 1 : 0;
687 if (!reg.sel_any)
688 reg.sel_any = cntrs[i].flags & PFM_GEN_IA32_SEL_ANYTHR? 1 : 0;
689 }
690
691 pc[npc].reg_num = assign[i];
692 pc[npc].reg_value = reg.val;
693 pc[npc].reg_addr = GEN_IA32_SEL_BASE+assign[i];
694 pd[i].reg_num = assign[i];
695 pd[i].reg_addr = GEN_IA32_CTR_BASE+assign[i];
696
697 if (pmu_version < 3)
698 __pfm_vbprintf("[PERFEVTSEL%u(pmc%u)=0x%"PRIx64" event_sel=0x%x umask=0x%x os=%d usr=%d en=%d int=%d inv=%d edge=%d cnt_mask=%d] %s\n",
699 pc[npc].reg_num,
700 pc[npc].reg_num,
701 reg.val,
703 reg.sel_unit_mask,
704 reg.sel_os,
705 reg.sel_usr,
706 reg.sel_en,
707 reg.sel_int,
708 reg.sel_inv,
709 reg.sel_edge,
710 reg.sel_cnt_mask,
712 else
713 __pfm_vbprintf("[PERFEVTSEL%u(pmc%u)=0x%"PRIx64" event_sel=0x%x umask=0x%x os=%d usr=%d en=%d int=%d inv=%d edge=%d cnt_mask=%d anythr=%d] %s\n",
714 pc[npc].reg_num,
715 pc[npc].reg_num,
716 reg.val,
718 reg.sel_unit_mask,
719 reg.sel_os,
720 reg.sel_usr,
721 reg.sel_en,
722 reg.sel_int,
723 reg.sel_inv,
724 reg.sel_edge,
725 reg.sel_cnt_mask,
726 reg.sel_any,
728
729 __pfm_vbprintf("[PMC%u(pmd%u)]\n",
730 pd[i].reg_num,
731 pd[i].reg_num);
732
733 npc++;
734 }
735 /* number of evtsel/ctr registers programmed */
736 outp->pfp_pmc_count = npc;
737 outp->pfp_pmd_count = n;
738 return PFMLIB_SUCCESS;
739}
740
741static int
743{
744 pfmlib_gen_ia32_input_param_t *mod_in = model_in;
745
746 if (inp->pfp_dfl_plm & (PFM_PLM1|PFM_PLM2)) {
747 DPRINT("invalid plm=%x\n", inp->pfp_dfl_plm);
748 return PFMLIB_ERR_INVAL;
749 }
750
751 /* simplfied v1 (no fixed counters */
752 if (pmu_version == 1)
753 return pfm_gen_ia32_dispatch_counters_v1(inp, mod_in, outp);
754 /* v2 or above */
755 return pfm_gen_ia32_dispatch_counters_v23(inp, mod_in, outp);
756}
757
758static int
759pfm_gen_ia32_get_event_code(unsigned int i, unsigned int cnt, int *code)
760{
761 if (cnt != PFMLIB_CNT_FIRST && cnt > gen_support->pmc_count)
762 return PFMLIB_ERR_INVAL;
763
764 *code = gen_ia32_pe[i].pme_code;
765
766 return PFMLIB_SUCCESS;
767}
768
769static void
771{
772 unsigned int i;
773
774 memset(counters, 0, sizeof(*counters));
775 for(i=0; i < num_gen_cnt; i++)
776 pfm_regmask_set(counters, i);
777
778 for(i=0; i < num_fixed_cnt; i++) {
779 if (gen_ia32_pe[j].pme_fixed == (FIXED_PMD_BASE+i))
781 }
782}
783
784static void
786{
787 *impl_pmcs = gen_ia32_impl_pmcs;
788}
789
790static void
792{
793 *impl_pmds = gen_ia32_impl_pmds;
794}
795
796static void
798{
799 /* all pmds are counters */
800 *impl_counters = gen_ia32_impl_pmds;
801}
802
803static void
805{
806 /*
807 * Even though, CPUID 0xa returns in eax the actual counter
808 * width, the architecture specifies that writes are limited
809 * to lower 32-bits. As such, only the lower 31 bits have full
810 * degree of freedom. That is the "useable" counter width.
811 */
813}
814
815static char *
817{
818 return gen_ia32_pe[i].pme_name;
819}
820
821static int
822pfm_gen_ia32_get_event_description(unsigned int ev, char **str)
823{
824 char *s;
825 s = gen_ia32_pe[ev].pme_desc;
826 if (s) {
827 *str = strdup(s);
828 } else {
829 *str = NULL;
830 }
831 return PFMLIB_SUCCESS;
832}
833
834static char *
835pfm_gen_ia32_get_event_mask_name(unsigned int ev, unsigned int midx)
836{
837 return gen_ia32_pe[ev].pme_umasks[midx].pme_uname;
838}
839
840static int
841pfm_gen_ia32_get_event_mask_desc(unsigned int ev, unsigned int midx, char **str)
842{
843 char *s;
844
845 s = gen_ia32_pe[ev].pme_umasks[midx].pme_udesc;
846 if (s) {
847 *str = strdup(s);
848 } else {
849 *str = NULL;
850 }
851 return PFMLIB_SUCCESS;
852}
853
854static unsigned int
856{
857 return gen_ia32_pe[ev].pme_numasks;
858}
859
860static int
861pfm_gen_ia32_get_event_mask_code(unsigned int ev, unsigned int midx, unsigned int *code)
862{
863 *code =gen_ia32_pe[ev].pme_umasks[midx].pme_ucode;
864 return PFMLIB_SUCCESS;
865}
866
867static int
869{
870 if (gen_ia32_cycle_event == -1)
871 return PFMLIB_ERR_NOTSUPP;
872
874 return PFMLIB_SUCCESS;
875
876}
877
878static int
880{
882 return PFMLIB_ERR_NOTSUPP;
883
885 return PFMLIB_SUCCESS;
886}
887
888/* architected PMU */
890 .pmu_name = "Intel architectural PMU",
891 .pmu_type = PFMLIB_GEN_IA32_PMU,
892 .pme_count = 0,
893 .pmc_count = 0,
894 .pmd_count = 0,
895 .num_cnt = 0,
896 .get_event_code = pfm_gen_ia32_get_event_code,
897 .get_event_name = pfm_gen_ia32_get_event_name,
898 .get_event_counters = pfm_gen_ia32_get_event_counters,
899 .dispatch_events = pfm_gen_ia32_dispatch_events,
900 .pmu_detect = pfm_gen_ia32_detect,
901 .pmu_init = pfm_gen_ia32_init,
902 .get_impl_pmcs = pfm_gen_ia32_get_impl_pmcs,
903 .get_impl_pmds = pfm_gen_ia32_get_impl_pmds,
904 .get_impl_counters = pfm_gen_ia32_get_impl_counters,
905 .get_hw_counter_width = pfm_gen_ia32_get_hw_counter_width,
906 .get_event_desc = pfm_gen_ia32_get_event_description,
907 .get_cycle_event = pfm_gen_ia32_get_cycle_event,
908 .get_inst_retired_event = pfm_gen_ia32_get_inst_retired,
909 .get_num_event_masks = pfm_gen_ia32_get_num_event_masks,
910 .get_event_mask_name = pfm_gen_ia32_get_event_mask_name,
911 .get_event_mask_code = pfm_gen_ia32_get_event_mask_code,
912 .get_event_mask_desc = pfm_gen_ia32_get_event_mask_desc
913};
int i
double s
Definition: byte_profile.c:36
static pme_gen_ia32_entry_t gen_ia32_all_pe[]
#define PME_GEN_IA32_INSTRUCTIONS_RETIRED
#define PME_GEN_IA32_UNHALTED_CORE_CYCLES
static int num_events
#define PFM_PLM2
Definition: pfmlib.h:52
static int pfm_regmask_set(pfmlib_regmask_t *h, unsigned int b)
Definition: pfmlib.h:321
#define PFMLIB_SUCCESS
Definition: pfmlib.h:283
#define PFM_PLM3
Definition: pfmlib.h:53
#define PFMLIB_NO_PMU
Definition: pfmlib.h:221
#define PFMLIB_ERR_INVAL
Definition: pfmlib.h:285
#define PFMLIB_ERR_TOOMANY
Definition: pfmlib.h:295
#define PFM_PLM0
Definition: pfmlib.h:50
static int pfm_regmask_isset(pfmlib_regmask_t *h, unsigned int b)
Definition: pfmlib.h:313
#define PFMLIB_ERR_NOASSIGN
Definition: pfmlib.h:288
#define PFM_PLM1
Definition: pfmlib.h:51
#define PFMLIB_ERR_NOTSUPP
Definition: pfmlib.h:284
#define PFMLIB_GEN_IA32_PMU
Definition: pfmlib.h:228
int family
Definition: pfmlib_amd64.c:85
int forced_pmu
static int gen_ia32_inst_retired_event
#define GEN_IA32_FIXED_CTR_BASE
static pfmlib_regmask_t gen_ia32_impl_pmcs
#define HAS_OPTIONS(x)
static char * pfm_gen_ia32_get_event_mask_name(unsigned int ev, unsigned int midx)
static int pfm_gen_ia32_get_event_description(unsigned int ev, char **str)
static int create_arch_event_table(unsigned int mask)
static pme_gen_ia32_entry_t * gen_ia32_pe
static void pfm_gen_ia32_get_impl_counters(pfmlib_regmask_t *impl_counters)
static const char * fixed_event_names[]
static char * pfm_gen_ia32_get_event_name(unsigned int i)
#define PFMLIB_GEN_IA32_ALL_FLAGS
static int check_arch_pmu(int family)
static int pfm_gen_ia32_dispatch_events(pfmlib_input_param_t *inp, void *model_in, pfmlib_output_param_t *outp, void *model_out)
#define is_fixed_pmc(a)
static unsigned int pfm_gen_ia32_get_num_event_masks(unsigned int ev)
#define GEN_IA32_CTR_BASE
static unsigned int num_gen_cnt
pfm_pmu_support_t * gen_support
static void pfm_gen_ia32_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
#define MAX_EVENT_NAMES
static int pfm_gen_ia32_get_cycle_event(pfmlib_event_t *e)
static int gen_ia32_cycle_event
static void pfm_gen_ia32_get_hw_counter_width(unsigned int *width)
static int pfm_gen_ia32_get_event_code(unsigned int i, unsigned int cnt, int *code)
#define FIXED_PMD_BASE
static int pfm_gen_ia32_init(void)
static int pfm_gen_ia32_get_event_mask_code(unsigned int ev, unsigned int midx, unsigned int *code)
static void pfm_gen_ia32_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
static unsigned int num_fixed_cnt
static void pfm_gen_ia32_get_event_counters(unsigned int j, pfmlib_regmask_t *counters)
static int pfm_gen_ia32_get_inst_retired(pfmlib_event_t *e)
static int pfm_gen_ia32_dispatch_counters_v23(pfmlib_input_param_t *inp, pfmlib_gen_ia32_input_param_t *param, pfmlib_output_param_t *outp)
static int pfm_gen_ia32_dispatch_counters_v1(pfmlib_input_param_t *inp, pfmlib_gen_ia32_input_param_t *mod_in, pfmlib_output_param_t *outp)
static void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
static unsigned int pmu_version
#define GEN_IA32_SEL_BASE
pfm_pmu_support_t gen_ia32_support
static int pfm_gen_ia32_detect(void)
static pfmlib_regmask_t gen_ia32_impl_pmds
static int pfm_gen_ia32_get_event_mask_desc(unsigned int ev, unsigned int midx, char **str)
#define PFM_GEN_IA32_SEL_INV
#define PMU_GEN_IA32_MAX_COUNTERS
#define PFM_GEN_IA32_SEL_EDGE
#define PMU_GEN_IA32_COUNTER_WIDTH
#define PFM_GEN_IA32_SEL_ANYTHR
static const pme_power_entry_t * pe
int __pfm_getcpuinfo_attr(const char *attr, char *ret_buf, size_t maxlen)
void __pfm_vbprintf(const char *fmt,...)
Definition: pfmlib_priv.c:52
#define DPRINT(fmt, a...)
Definition: pfmlib_priv.h:90
#define PFMLIB_DEBUG()
Definition: pfmlib_priv.h:76
#define PFMLIB_CNT_FIRST
Definition: pfmlib_priv.h:62
unsigned int pmc_count
Definition: pfmlib_priv.h:37
unsigned int num_cnt
Definition: pfmlib_priv.h:38
unsigned int pmd_count
Definition: pfmlib_priv.h:36
unsigned int pme_count
Definition: pfmlib_priv.h:35
unsigned int num_masks
Definition: pfmlib.h:90
unsigned int plm
Definition: pfmlib.h:87
unsigned int event
Definition: pfmlib.h:86
pfmlib_gen_ia32_counter_t pfp_gen_ia32_counters[PMU_GEN_IA32_MAX_COUNTERS]
unsigned int pfp_dfl_plm
Definition: pfmlib.h:110
pfmlib_regmask_t pfp_unavail_pmcs
Definition: pfmlib.h:114
pfmlib_event_t pfp_events[PFMLIB_MAX_PMCS]
Definition: pfmlib.h:113
unsigned int pfp_event_count
Definition: pfmlib.h:109
pfmlib_reg_t pfp_pmds[PFMLIB_MAX_PMDS]
Definition: pfmlib.h:130
pfmlib_reg_t pfp_pmcs[PFMLIB_MAX_PMCS]
Definition: pfmlib.h:129
unsigned int pfp_pmc_count
Definition: pfmlib.h:127
unsigned int pfp_pmd_count
Definition: pfmlib.h:128
unsigned long long reg_value
Definition: pfmlib.h:98
unsigned int reg_num
Definition: pfmlib.h:100
unsigned long long reg_addr
Definition: pfmlib.h:99
pme_gen_ia32_umask_t pme_umasks[PFMLIB_GEN_IA32_MAX_UMASK]
char * pme_name
unsigned int pme_code
unsigned int pme_numasks
unsigned int pme_fixed
char * pme_desc
unsigned long long val
unsigned long sel_event_select
unsigned long sel_cnt_mask
unsigned long sel_unit_mask