PAPI 7.1.0.0
Loading...
Searching...
No Matches
pfmlib_core.c
Go to the documentation of this file.
1/*
2 * pfmlib_core.c : Intel Core PMU
3 *
4 * Copyright (c) 2006 Hewlett-Packard Development Company, L.P.
5 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11 * of the Software, and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 *
25 * This file implements support for Intel Core PMU as specified in the following document:
26 * "IA-32 Intel Architecture Software Developer's Manual - Volume 3B: System
27 * Programming Guide"
28 *
29 * Core PMU = architectural perfmon v2 + PEBS
30 */
31#include <sys/types.h>
32#include <ctype.h>
33#include <string.h>
34#include <stdlib.h>
35#include <stdio.h>
36
37/* public headers */
38#include <perfmon/pfmlib_core.h>
39
40/* private headers */
41#include "pfmlib_priv.h"
42#include "pfmlib_core_priv.h"
43
44#include "core_events.h"
45
46/* let's define some handy shortcuts! */
47#define sel_event_select perfevtsel.sel_event_select
48#define sel_unit_mask perfevtsel.sel_unit_mask
49#define sel_usr perfevtsel.sel_usr
50#define sel_os perfevtsel.sel_os
51#define sel_edge perfevtsel.sel_edge
52#define sel_pc perfevtsel.sel_pc
53#define sel_int perfevtsel.sel_int
54#define sel_en perfevtsel.sel_en
55#define sel_inv perfevtsel.sel_inv
56#define sel_cnt_mask perfevtsel.sel_cnt_mask
57
58#define is_pebs(i) (core_pe[i].pme_flags & PFMLIB_CORE_PEBS)
59
60
61/*
62 * Description of the PMC register mappings:
63 *
64 * 0 -> PMC0 -> PERFEVTSEL0
65 * 1 -> PMC1 -> PERFEVTSEL1
66 * 16 -> PMC16 -> FIXED_CTR_CTRL
67 * 17 -> PMC17 -> PEBS_ENABLED
68 *
69 * Description of the PMD register mapping:
70 *
71 * 0 -> PMD0 -> PMC0
72 * 1 -> PMD1 -> PMC1
73 * 16 -> PMD2 -> FIXED_CTR0
74 * 17 -> PMD3 -> FIXED_CTR1
75 * 18 -> PMD4 -> FIXED_CTR2
76 */
77#define CORE_SEL_BASE 0x186
78#define CORE_CTR_BASE 0xc1
79#define FIXED_CTR_BASE 0x309
80
81#define PFMLIB_CORE_ALL_FLAGS \
82 (PFM_CORE_SEL_INV|PFM_CORE_SEL_EDGE)
83
85static int highest_counter;
86
87static int
89{
90 int ret;
91 int family, model;
92 char buffer[128];
93
94 ret = __pfm_getcpuinfo_attr("vendor_id", buffer, sizeof(buffer));
95 if (ret == -1)
96 return PFMLIB_ERR_NOTSUPP;
97
98 if (strcmp(buffer, "GenuineIntel"))
99 return PFMLIB_ERR_NOTSUPP;
100
101 ret = __pfm_getcpuinfo_attr("cpu family", buffer, sizeof(buffer));
102 if (ret == -1)
103 return PFMLIB_ERR_NOTSUPP;
104
105 family = atoi(buffer);
106
107 ret = __pfm_getcpuinfo_attr("model", buffer, sizeof(buffer));
108 if (ret == -1)
109 return PFMLIB_ERR_NOTSUPP;
110
111 if (family != 6)
112 return PFMLIB_ERR_NOTSUPP;
113
114 model = atoi(buffer);
115 switch(model) {
116 case 15: /* Merom */
117 case 23: /* Penryn */
118 case 29: /* Dunnington */
119 break;
120 default:
121 return PFMLIB_ERR_NOTSUPP;
122 }
123 return PFMLIB_SUCCESS;
124}
125
126static int
128{
129 int i;
130
135
141
142 /* lbr */
144 for(i=0; i < 8; i++)
146
147 highest_counter = 18;
148
149 return PFMLIB_SUCCESS;
150}
151
152static int
154{
155 unsigned int fl, flc, i;
156 unsigned int mask = 0;
157
158 fl = core_pe[e->event].pme_flags;
159
160 /*
161 * first pass: check if event as a whole supports fixed counters
162 */
163 switch(f) {
164 case 0:
165 mask = PFMLIB_CORE_FIXED0;
166 break;
167 case 1:
168 mask = PFMLIB_CORE_FIXED1;
169 break;
170 case 2:
172 break;
173 default:
174 return 0;
175 }
176 if (fl & mask)
177 return 1;
178 /*
179 * second pass: check if unit mask support fixed counter
180 *
181 * reject if mask not found OR if not all unit masks have
182 * same fixed counter mask
183 */
184 flc = 0;
185 for(i=0; i < e->num_masks; i++) {
187 if (fl & mask)
188 flc++;
189 }
190 return flc > 0 && flc == e->num_masks ? 1 : 0;
191}
192
193/*
194 * IMPORTANT: the interface guarantees that pfp_pmds[] elements are returned in the order the events
195 * were submitted.
196 */
197static int
199{
200#define HAS_OPTIONS(x) (cntrs && (cntrs[x].flags || cntrs[x].cnt_mask))
201#define is_fixed_pmc(a) (a == 16 || a == 17 || a == 18)
202
206 pfmlib_reg_t *pc, *pd;
207 pfmlib_regmask_t *r_pmcs;
208 uint64_t val;
209 unsigned long plm;
210 unsigned long long fixed_ctr;
211 unsigned int npc, npmc0, npmc1, nf2;
212 unsigned int i, j, n, k, ucode, use_pebs = 0, done_pebs;
213 unsigned int assign_pc[PMU_CORE_NUM_COUNTERS];
214 unsigned int next_gen, last_gen;
215
216 npc = npmc0 = npmc1 = nf2 = 0;
217
218 e = inp->pfp_events;
219 pc = outp->pfp_pmcs;
220 pd = outp->pfp_pmds;
221 n = inp->pfp_event_count;
222 r_pmcs = &inp->pfp_unavail_pmcs;
223 cntrs = param ? param->pfp_core_counters : NULL;
224 use_pebs = param ? param->pfp_core_pebs.pebs_used : 0;
225
226 if (n > PMU_CORE_NUM_COUNTERS)
227 return PFMLIB_ERR_TOOMANY;
228
229 /*
230 * initilize to empty
231 */
232 for(i=0; i < PMU_CORE_NUM_COUNTERS; i++)
233 assign_pc[i] = -1;
234
235 /*
236 * error checking
237 */
238 for(i=0; i < n; i++) {
239 /*
240 * only supports two priv levels for perf counters
241 */
242 if (e[i].plm & (PFM_PLM1|PFM_PLM2))
243 return PFMLIB_ERR_INVAL;
244
245 /*
246 * check for valid flags
247 */
248 if (cntrs && cntrs[i].flags & ~PFMLIB_CORE_ALL_FLAGS)
249 return PFMLIB_ERR_INVAL;
250
251 if (core_pe[e[i].event].pme_flags & PFMLIB_CORE_UMASK_NCOMBO
252 && e[i].num_masks > 1) {
253 DPRINT("events does not support unit mask combination\n");
254 return PFMLIB_ERR_NOASSIGN;
255 }
256
257 /*
258 * check event-level single register constraint (PMC0, PMC1, FIXED_CTR2)
259 * fail if more than two events requested for the same counter
260 */
261 if (core_pe[e[i].event].pme_flags & PFMLIB_CORE_PMC0) {
262 if (++npmc0 > 1) {
263 DPRINT("two events compete for a PMC0\n");
264 return PFMLIB_ERR_NOASSIGN;
265 }
266 }
267 /*
268 * check if PMC1 is available and if only one event is dependent on it
269 */
270 if (core_pe[e[i].event].pme_flags & PFMLIB_CORE_PMC1) {
271 if (++npmc1 > 1) {
272 DPRINT("two events compete for a PMC1\n");
273 return PFMLIB_ERR_NOASSIGN;
274 }
275 }
276 /*
277 * UNHALTED_REFERENCE_CYCLES can only be measured on FIXED_CTR2
278 */
279 if (core_pe[e[i].event].pme_flags & PFMLIB_CORE_FIXED2_ONLY) {
280 if (++nf2 > 1) {
281 DPRINT("two events compete for FIXED_CTR2\n");
282 return PFMLIB_ERR_NOASSIGN;
283 }
284 if (HAS_OPTIONS(i)) {
285 DPRINT("fixed counters do not support inversion/counter-mask\n");
286 return PFMLIB_ERR_NOASSIGN;
287 }
288 }
289 /*
290 * unit-mask level constraint checking (PMC0, PMC1, FIXED_CTR2)
291 */
292 for(j=0; j < e[i].num_masks; j++) {
293 unsigned int flags;
294
295 flags = core_pe[e[i].event].pme_umasks[e[i].unit_masks[j]].pme_flags;
296
297 if (flags & PFMLIB_CORE_FIXED2_ONLY) {
298 if (++nf2 > 1) {
299 DPRINT("two events compete for FIXED_CTR2\n");
300 return PFMLIB_ERR_NOASSIGN;
301 }
302 if (HAS_OPTIONS(i)) {
303 DPRINT("fixed counters do not support inversion/counter-mask\n");
304 return PFMLIB_ERR_NOASSIGN;
305 }
306 }
307 }
308 }
309
310 next_gen = 0; /* first generic counter */
311 last_gen = 1; /* last generic counter */
312
313 /*
314 * strongest constraint first: works only in IA32_PMC0, IA32_PMC1, FIXED_CTR2
315 *
316 * When PEBS is used, we pick the first PEBS event and
317 * place it into PMC0. Subsequent PEBS events, will go
318 * in the other counters.
319 */
320 done_pebs = 0;
321 for(i=0; i < n; i++) {
322 if ((core_pe[e[i].event].pme_flags & PFMLIB_CORE_PMC0)
323 || (use_pebs && pfm_core_is_pebs(e+i) && done_pebs == 0)) {
324 if (pfm_regmask_isset(r_pmcs, 0))
325 return PFMLIB_ERR_NOASSIGN;
326 assign_pc[i] = 0;
327 next_gen = 1;
328 done_pebs = 1;
329 }
330 if (core_pe[e[i].event].pme_flags & PFMLIB_CORE_PMC1) {
331 if (pfm_regmask_isset(r_pmcs, 1))
332 return PFMLIB_ERR_NOASSIGN;
333 assign_pc[i] = 1;
334 if (next_gen == 1)
335 next_gen = 2;
336 else
337 next_gen = 0;
338 }
339 }
340 /*
341 * next constraint: fixed counters
342 *
343 * We abuse the mapping here for assign_pc to make it easier
344 * to provide the correct values for pd[].
345 * We use:
346 * - 16 : fixed counter 0 (pmc16, pmd16)
347 * - 17 : fixed counter 1 (pmc16, pmd17)
348 * - 18 : fixed counter 1 (pmc16, pmd18)
349 */
350 fixed_ctr = pfm_regmask_isset(r_pmcs, 16) ? 0 : 0x7;
351 if (fixed_ctr) {
352 for(i=0; i < n; i++) {
353 /* fixed counters do not support event options (filters) */
354 if (HAS_OPTIONS(i) || (use_pebs && pfm_core_is_pebs(e+i)))
355 continue;
356
357 if ((fixed_ctr & 0x1) && pfm_core_is_fixed(e+i, 0)) {
358 assign_pc[i] = 16;
359 fixed_ctr &= ~1;
360 }
361 if ((fixed_ctr & 0x2) && pfm_core_is_fixed(e+i, 1)) {
362 assign_pc[i] = 17;
363 fixed_ctr &= ~2;
364 }
365 if ((fixed_ctr & 0x4) && pfm_core_is_fixed(e+i, 2)) {
366 assign_pc[i] = 18;
367 fixed_ctr &= ~4;
368 }
369 }
370 }
371 /*
372 * assign what is left
373 */
374 for(i=0; i < n; i++) {
375 if (assign_pc[i] == -1) {
376 for(; next_gen <= last_gen; next_gen++) {
377DPRINT("i=%d next_gen=%d last=%d isset=%d\n", i, next_gen, last_gen, pfm_regmask_isset(r_pmcs, next_gen));
378 if (!pfm_regmask_isset(r_pmcs, next_gen))
379 break;
380 }
381 if (next_gen <= last_gen)
382 assign_pc[i] = next_gen++;
383 else {
384 DPRINT("cannot assign generic counters\n");
385 return PFMLIB_ERR_NOASSIGN;
386 }
387 }
388 }
389 j = 0;
390
391 /* setup fixed counters */
392 reg.val = 0;
393 k = 0;
394 for (i=0; i < n ; i++ ) {
395 if (!is_fixed_pmc(assign_pc[i]))
396 continue;
397 val = 0;
398 /* if plm is 0, then assume not specified per-event and use default */
399 plm = e[i].plm ? e[i].plm : inp->pfp_dfl_plm;
400 if (plm & PFM_PLM0)
401 val |= 1ULL;
402 if (plm & PFM_PLM3)
403 val |= 2ULL;
404 val |= 1ULL << 3; /* force APIC int (kernel may force it anyway) */
405
406 reg.val |= val << ((assign_pc[i]-16)<<2);
407 }
408
409 if (reg.val) {
410 pc[npc].reg_num = 16;
411 pc[npc].reg_value = reg.val;
412 pc[npc].reg_addr = 0x38D;
413 pc[npc].reg_alt_addr = 0x38D;
414
415 __pfm_vbprintf("[FIXED_CTRL(pmc%u)=0x%"PRIx64" pmi0=1 en0=0x%"PRIx64" pmi1=1 en1=0x%"PRIx64" pmi2=1 en2=0x%"PRIx64"] ",
416 pc[npc].reg_num,
417 reg.val,
418 reg.val & 0x3ULL,
419 (reg.val>>4) & 0x3ULL,
420 (reg.val>>8) & 0x3ULL);
421
422 if ((fixed_ctr & 0x1) == 0)
423 __pfm_vbprintf("INSTRUCTIONS_RETIRED ");
424 if ((fixed_ctr & 0x2) == 0)
425 __pfm_vbprintf("UNHALTED_CORE_CYCLES ");
426 if ((fixed_ctr & 0x4) == 0)
427 __pfm_vbprintf("UNHALTED_REFERENCE_CYCLES ");
428 __pfm_vbprintf("\n");
429
430 npc++;
431
432 if ((fixed_ctr & 0x1) == 0)
433 __pfm_vbprintf("[FIXED_CTR0(pmd16)]\n");
434 if ((fixed_ctr & 0x2) == 0)
435 __pfm_vbprintf("[FIXED_CTR1(pmd17)]\n");
436 if ((fixed_ctr & 0x4) == 0)
437 __pfm_vbprintf("[FIXED_CTR2(pmd18)]\n");
438 }
439
440 for (i=0; i < n ; i++ ) {
441 /* skip fixed counters */
442 if (is_fixed_pmc(assign_pc[i]))
443 continue;
444
445 reg.val = 0; /* assume reserved bits are zerooed */
446
447 /* if plm is 0, then assume not specified per-event and use default */
448 plm = e[i].plm ? e[i].plm : inp->pfp_dfl_plm;
449
450 val = core_pe[e[i].event].pme_code;
451
452 reg.sel_event_select = val & 0xff;
453
454 ucode = (val >> 8) & 0xff;
455
456 for(k=0; k < e[i].num_masks; k++) {
457 ucode |= core_pe[e[i].event].pme_umasks[e[i].unit_masks[k]].pme_ucode;
458 }
459
460 /*
461 * for events supporting Core specificity (self, both), a value
462 * of 0 for bits 15:14 (7:6 in our umask) is reserved, therefore we
463 * force to SELF if user did not specify anything
464 */
465 if ((core_pe[e[i].event].pme_flags & PFMLIB_CORE_CSPEC)
466 && ((ucode & (0x3 << 6)) == 0)) {
467 ucode |= 1 << 6;
468 }
469 /*
470 * for events supporting MESI, a value
471 * of 0 for bits 11:8 (0-3 in our umask) means nothing will be
472 * counted. Therefore, we force a default of 0xf (M,E,S,I).
473 */
474 if ((core_pe[e[i].event].pme_flags & PFMLIB_CORE_MESI)
475 && ((ucode & 0xf) == 0)) {
476 ucode |= 0xf;
477 }
478
479 val |= ucode << 8;
480
481 reg.sel_unit_mask = ucode;
482 reg.sel_usr = plm & PFM_PLM3 ? 1 : 0;
483 reg.sel_os = plm & PFM_PLM0 ? 1 : 0;
484 reg.sel_en = 1; /* force enable bit to 1 */
485 reg.sel_int = 1; /* force APIC int to 1 */
486
487 reg.sel_cnt_mask = val >>24;
488 reg.sel_inv = val >> 23;
489 reg.sel_edge = val >> 18;
490
491 if (cntrs) {
492 if (!reg.sel_cnt_mask) {
493 /*
494 * counter mask is 8-bit wide, do not silently
495 * wrap-around
496 */
497 if (cntrs[i].cnt_mask > 255)
498 return PFMLIB_ERR_INVAL;
499 reg.sel_cnt_mask = cntrs[i].cnt_mask;
500 }
501
502 if (!reg.sel_edge)
503 reg.sel_edge = cntrs[i].flags & PFM_CORE_SEL_EDGE ? 1 : 0;
504 if (!reg.sel_inv)
505 reg.sel_inv = cntrs[i].flags & PFM_CORE_SEL_INV ? 1 : 0;
506 }
507
508 pc[npc].reg_num = assign_pc[i];
509 pc[npc].reg_value = reg.val;
510 pc[npc].reg_addr = CORE_SEL_BASE+assign_pc[i];
511 pc[npc].reg_alt_addr= CORE_SEL_BASE+assign_pc[i];
512
513 __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",
514 pc[npc].reg_num,
515 pc[npc].reg_num,
516 reg.val,
518 reg.sel_unit_mask,
519 reg.sel_os,
520 reg.sel_usr,
521 reg.sel_en,
522 reg.sel_int,
523 reg.sel_inv,
524 reg.sel_edge,
525 reg.sel_cnt_mask,
526 core_pe[e[i].event].pme_name);
527
528 __pfm_vbprintf("[PMC%u(pmd%u)]\n",
529 pc[npc].reg_num,
530 pc[npc].reg_num);
531
532 npc++;
533 }
534 /*
535 * setup pmds: must be in the same order as the events
536 */
537 for (i=0; i < n ; i++) {
538 if (is_fixed_pmc(assign_pc[i])) {
539 /* setup pd array */
540 pd[i].reg_num = assign_pc[i];
541 pd[i].reg_addr = FIXED_CTR_BASE+assign_pc[i]-16;
542 pd[i].reg_alt_addr = 0x40000000+assign_pc[i]-16;
543 } else {
544 pd[i].reg_num = assign_pc[i];
545 pd[i].reg_addr = CORE_CTR_BASE+assign_pc[i];
546 /* index to use with RDPMC */
547 pd[i].reg_alt_addr = assign_pc[i];
548 }
549 }
550 outp->pfp_pmd_count = i;
551
552 /*
553 * setup PEBS_ENABLE
554 */
555 if (use_pebs && done_pebs) {
556 /*
557 * check that PEBS_ENABLE is available
558 */
559 if (pfm_regmask_isset(r_pmcs, 17))
560 return PFMLIB_ERR_NOASSIGN;
561 pc[npc].reg_num = 17;
562 pc[npc].reg_value = 1ULL;
563 pc[npc].reg_addr = 0x3f1; /* IA32_PEBS_ENABLE */
564 pc[npc].reg_alt_addr = 0x3f1; /* IA32_PEBS_ENABLE */
565
566 __pfm_vbprintf("[PEBS_ENABLE(pmc%u)=0x%"PRIx64" ena=%d]\n",
567 pc[npc].reg_num,
568 pc[npc].reg_value,
569 pc[npc].reg_value & 0x1ull);
570
571 npc++;
572
573 }
574 outp->pfp_pmc_count = npc;
575
576 return PFMLIB_SUCCESS;
577}
578
579#if 0
580static int
581pfm_core_dispatch_pebs(pfmlib_input_param_t *inp, pfmlib_core_input_param_t *mod_in, pfmlib_output_param_t *outp)
582{
585 unsigned int umask, npc, npd, k, plm;
586 pfmlib_regmask_t *r_pmcs;
587 pfmlib_reg_t *pc, *pd;
588 int event;
589
590 npc = outp->pfp_pmc_count;
591 npd = outp->pfp_pmd_count;
592 pc = outp->pfp_pmcs;
593 pd = outp->pfp_pmds;
594 r_pmcs = &inp->pfp_unavail_pmcs;
595
596 e = inp->pfp_events;
597 /*
598 * check for valid flags
599 */
600 if (e[0].flags & ~PFMLIB_CORE_ALL_FLAGS)
601 return PFMLIB_ERR_INVAL;
602
603 /*
604 * check event supports PEBS
605 */
606 if (pfm_core_is_pebs(e) == 0)
607 return PFMLIB_ERR_FEATCOMB;
608
609 /*
610 * check that PMC0 is available
611 * PEBS works only on PMC0
612 * Some PEBS at-retirement events do require PMC0 anyway
613 */
614 if (pfm_regmask_isset(r_pmcs, 0))
615 return PFMLIB_ERR_NOASSIGN;
616
617 /*
618 * check that PEBS_ENABLE is available
619 */
620 if (pfm_regmask_isset(r_pmcs, 17))
621 return PFMLIB_ERR_NOASSIGN;
622
623 reg.val = 0; /* assume reserved bits are zerooed */
624
625 event = e[0].event;
626
627 /* if plm is 0, then assume not specified per-event and use default */
628 plm = e[0].plm ? e[0].plm : inp->pfp_dfl_plm;
629
630 reg.sel_event_select = core_pe[event].pme_code & 0xff;
631
632 umask = (core_pe[event].pme_code >> 8) & 0xff;
633
634 for(k=0; k < e[0].num_masks; k++) {
635 umask |= core_pe[event].pme_umasks[e[0].unit_masks[k]].pme_ucode;
636 }
637 reg.sel_unit_mask = umask;
638 reg.sel_usr = plm & PFM_PLM3 ? 1 : 0;
639 reg.sel_os = plm & PFM_PLM0 ? 1 : 0;
640 reg.sel_en = 1; /* force enable bit to 1 */
641 reg.sel_int = 0; /* not INT for PEBS counter */
642
643 reg.sel_cnt_mask = mod_in->pfp_core_counters[0].cnt_mask;
644 reg.sel_edge = mod_in->pfp_core_counters[0].flags & PFM_CORE_SEL_EDGE ? 1 : 0;
645 reg.sel_inv = mod_in->pfp_core_counters[0].flags & PFM_CORE_SEL_INV ? 1 : 0;
646
647 pc[npc].reg_num = 0;
648 pc[npc].reg_value = reg.val;
649 pc[npc].reg_addr = CORE_SEL_BASE;
651
652 pd[npd].reg_num = 0;
653 pd[npd].reg_addr = CORE_CTR_BASE;
654 pd[npd].reg_alt_addr = 0;
655
656 __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",
657 pc[npc].reg_num,
658 pc[npc].reg_num,
659 reg.val,
661 reg.sel_unit_mask,
662 reg.sel_os,
663 reg.sel_usr,
664 reg.sel_en,
665 reg.sel_int,
666 reg.sel_inv,
667 reg.sel_edge,
668 reg.sel_cnt_mask,
669 core_pe[e[0].event].pme_name);
670
671 __pfm_vbprintf("[PMC%u(pmd%u)]\n",
672 pd[npd].reg_num,
673 pd[npd].reg_num);
674
675 npc++;
676 npd++;
677 /*
678 * setup PEBS_ENABLE
679 */
680 pc[npc].reg_num = 17;
681 pc[npc].reg_value = 1ULL;
682 pc[npc].reg_addr = 0x3f1; /* IA32_PEBS_ENABLE */
683 pc[npc].reg_alt_addr = 0x3f1; /* IA32_PEBS_ENABLE */
684
685 __pfm_vbprintf("[PEBS_ENABLE(pmc%u)=0x%"PRIx64" ena=%d]\n",
686 pc[npc].reg_num,
687 pc[npc].reg_value,
688 pc[npc].reg_value & 0x1ull);
689
690 npc++;
691
692 /* number of evtsel/ctr registers programmed */
693 outp->pfp_pmc_count = npc;
694 outp->pfp_pmd_count = npd;
695
696 return PFMLIB_SUCCESS;
697}
698#endif
699
700static int
701pfm_core_dispatch_events(pfmlib_input_param_t *inp, void *model_in, pfmlib_output_param_t *outp, void *model_out)
702{
704
705 if (inp->pfp_dfl_plm & (PFM_PLM1|PFM_PLM2)) {
706 DPRINT("invalid plm=%x\n", inp->pfp_dfl_plm);
707 return PFMLIB_ERR_INVAL;
708 }
709 return pfm_core_dispatch_counters(inp, mod_in, outp);
710}
711
712static int
713pfm_core_get_event_code(unsigned int i, unsigned int cnt, int *code)
714{
715 if (cnt != PFMLIB_CNT_FIRST
716 && (cnt > highest_counter ||
718 return PFMLIB_ERR_INVAL;
719
720 *code = core_pe[i].pme_code;
721
722 return PFMLIB_SUCCESS;
723}
724
725static void
727{
728 unsigned int n, i;
729 unsigned int has_f0, has_f1, has_f2;
730
731 memset(counters, 0, sizeof(*counters));
732
733 n = core_pe[j].pme_numasks;
734 has_f0 = has_f1 = has_f2 = 0;
735
736 for (i=0; i < n; i++) {
737 if (core_pe[j].pme_umasks[i].pme_flags & PFMLIB_CORE_FIXED0)
738 has_f0 = 1;
739 if (core_pe[j].pme_umasks[i].pme_flags & PFMLIB_CORE_FIXED1)
740 has_f1 = 1;
741 if (core_pe[j].pme_umasks[i].pme_flags & PFMLIB_CORE_FIXED2_ONLY)
742 has_f2 = 1;
743 }
744
745 if (has_f0 == 0)
747 if (has_f1 == 0)
749 if (has_f2 == 0)
751
752 if (has_f0)
753 pfm_regmask_set(counters, 16);
754 if (has_f1)
755 pfm_regmask_set(counters, 17);
756 if (has_f2)
757 pfm_regmask_set(counters, 18);
758
759 /* the event on FIXED_CTR2 is exclusive CPU_CLK_UNHALTED:REF */
760 if (!has_f2) {
761 pfm_regmask_set(counters, 0);
762 pfm_regmask_set(counters, 1);
763
764 if (core_pe[j].pme_flags & PFMLIB_CORE_PMC0)
765 pfm_regmask_clr(counters, 1);
766 if (core_pe[j].pme_flags & PFMLIB_CORE_PMC1)
767 pfm_regmask_clr(counters, 0);
768 }
769}
770
771static void
773{
774 *impl_pmcs = core_impl_pmcs;
775}
776
777static void
779{
780 *impl_pmds = core_impl_pmds;
781}
782
783static void
785{
786 pfm_regmask_set(impl_counters, 0);
787 pfm_regmask_set(impl_counters, 1);
788 pfm_regmask_set(impl_counters, 16);
789 pfm_regmask_set(impl_counters, 17);
790 pfm_regmask_set(impl_counters, 18);
791}
792
793/*
794 * Even though, CPUID 0xa returns in eax the actual counter
795 * width, the architecture specifies that writes are limited
796 * to lower 32-bits. As such, only the lower 32-bit have full
797 * degree of freedom. That is the "useable" counter width.
798 */
799#define PMU_CORE_COUNTER_WIDTH 32
800
801static void
803{
804 /*
805 * Even though, CPUID 0xa returns in eax the actual counter
806 * width, the architecture specifies that writes are limited
807 * to lower 32-bits. As such, only the lower 31 bits have full
808 * degree of freedom. That is the "useable" counter width.
809 */
810 *width = PMU_CORE_COUNTER_WIDTH;
811}
812
813static char *
815{
816 return core_pe[i].pme_name;
817}
818
819static int
820pfm_core_get_event_description(unsigned int ev, char **str)
821{
822 char *s;
823 s = core_pe[ev].pme_desc;
824 if (s) {
825 *str = strdup(s);
826 } else {
827 *str = NULL;
828 }
829 return PFMLIB_SUCCESS;
830}
831
832static char *
833pfm_core_get_event_mask_name(unsigned int ev, unsigned int midx)
834{
835 return core_pe[ev].pme_umasks[midx].pme_uname;
836}
837
838static int
839pfm_core_get_event_mask_desc(unsigned int ev, unsigned int midx, char **str)
840{
841 char *s;
842
843 s = core_pe[ev].pme_umasks[midx].pme_udesc;
844 if (s) {
845 *str = strdup(s);
846 } else {
847 *str = NULL;
848 }
849 return PFMLIB_SUCCESS;
850}
851
852static unsigned int
854{
855 return core_pe[ev].pme_numasks;
856}
857
858static int
859pfm_core_get_event_mask_code(unsigned int ev, unsigned int midx, unsigned int *code)
860{
861 *code =core_pe[ev].pme_umasks[midx].pme_ucode;
862 return PFMLIB_SUCCESS;
863}
864
865static int
867{
869 return PFMLIB_SUCCESS;
870}
871
872static int
874{
876 return PFMLIB_SUCCESS;
877}
878
879int
881{
882 unsigned int i, n=0;
883
884 if (e == NULL || e->event >= PME_CORE_EVENT_COUNT)
885 return 0;
886
888 return 1;
889
890 /*
891 * ALL unit mask must support PEBS for this test to return true
892 */
893 for(i=0; i < e->num_masks; i++) {
894 /* check for valid unit mask */
895 if (e->unit_masks[i] >= core_pe[e->event].pme_numasks)
896 return 0;
898 n++;
899 }
900 return n > 0 && n == e->num_masks;
901}
902
904 .pmu_name = "Intel Core",
905 .pmu_type = PFMLIB_CORE_PMU,
906 .pme_count = PME_CORE_EVENT_COUNT,
907 .pmc_count = 4,
908 .pmd_count = 14,
909 .num_cnt = 5,
910 .get_event_code = pfm_core_get_event_code,
911 .get_event_name = pfm_core_get_event_name,
912 .get_event_counters = pfm_core_get_event_counters,
913 .dispatch_events = pfm_core_dispatch_events,
914 .pmu_detect = pfm_core_detect,
915 .pmu_init = pfm_core_init,
916 .get_impl_pmcs = pfm_core_get_impl_pmcs,
917 .get_impl_pmds = pfm_core_get_impl_pmds,
918 .get_impl_counters = pfm_core_get_impl_counters,
919 .get_hw_counter_width = pfm_core_get_hw_counter_width,
920 .get_event_desc = pfm_core_get_event_description,
921 .get_num_event_masks = pfm_core_get_num_event_masks,
922 .get_event_mask_name = pfm_core_get_event_mask_name,
923 .get_event_mask_code = pfm_core_get_event_mask_code,
924 .get_event_mask_desc = pfm_core_get_event_mask_desc,
925 .get_cycle_event = pfm_core_get_cycle_event,
926 .get_inst_retired_event = pfm_core_get_inst_retired
927};
int i
double s
Definition: byte_profile.c:36
#define PME_CORE_INSTRUCTIONS_RETIRED
Definition: core_events.h:1506
#define PME_CORE_EVENT_COUNT
Definition: core_events.h:1507
#define PME_CORE_UNHALTED_CORE_CYCLES
Definition: core_events.h:1505
static pme_core_entry_t core_pe[]
Definition: core_events.h:79
double f(double a)
Definition: cpi.c:23
#define PFMLIB_ERR_FEATCOMB
Definition: pfmlib.h:292
#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_ERR_INVAL
Definition: pfmlib.h:285
#define PFMLIB_CORE_PMU
Definition: pfmlib.h:233
static int pfm_regmask_clr(pfmlib_regmask_t *h, unsigned int b)
Definition: pfmlib.h:332
#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
int model
Definition: pfmlib_amd64.c:86
int family
Definition: pfmlib_amd64.c:85
static int pfm_core_dispatch_events(pfmlib_input_param_t *inp, void *model_in, pfmlib_output_param_t *outp, void *model_out)
Definition: pfmlib_core.c:701
static int pfm_core_get_event_code(unsigned int i, unsigned int cnt, int *code)
Definition: pfmlib_core.c:713
static int pfm_core_is_fixed(pfmlib_event_t *e, unsigned int f)
Definition: pfmlib_core.c:153
static char * pfm_core_get_event_mask_name(unsigned int ev, unsigned int midx)
Definition: pfmlib_core.c:833
#define HAS_OPTIONS(x)
static int pfm_core_get_event_mask_code(unsigned int ev, unsigned int midx, unsigned int *code)
Definition: pfmlib_core.c:859
static void pfm_core_get_event_counters(unsigned int j, pfmlib_regmask_t *counters)
Definition: pfmlib_core.c:726
#define CORE_CTR_BASE
Definition: pfmlib_core.c:78
static int pfm_core_get_inst_retired(pfmlib_event_t *e)
Definition: pfmlib_core.c:873
pfm_pmu_support_t core_support
Definition: pfmlib_core.c:903
static int pfm_core_detect(void)
Definition: pfmlib_core.c:88
#define is_fixed_pmc(a)
static int highest_counter
Definition: pfmlib_core.c:85
#define FIXED_CTR_BASE
Definition: pfmlib_core.c:79
static pfmlib_regmask_t core_impl_pmds
Definition: pfmlib_core.c:84
static int pfm_core_get_event_mask_desc(unsigned int ev, unsigned int midx, char **str)
Definition: pfmlib_core.c:839
static char * pfm_core_get_event_name(unsigned int i)
Definition: pfmlib_core.c:814
static void pfm_core_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
Definition: pfmlib_core.c:772
static int pfm_core_get_cycle_event(pfmlib_event_t *e)
Definition: pfmlib_core.c:866
int pfm_core_is_pebs(pfmlib_event_t *e)
Definition: pfmlib_core.c:880
#define CORE_SEL_BASE
Definition: pfmlib_core.c:77
static void pfm_core_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
Definition: pfmlib_core.c:778
static int pfm_core_init(void)
Definition: pfmlib_core.c:127
static int pfm_core_dispatch_counters(pfmlib_input_param_t *inp, pfmlib_core_input_param_t *param, pfmlib_output_param_t *outp)
Definition: pfmlib_core.c:198
static pfmlib_regmask_t core_impl_pmcs
Definition: pfmlib_core.c:84
static void pfm_core_get_hw_counter_width(unsigned int *width)
Definition: pfmlib_core.c:802
static int pfm_core_get_event_description(unsigned int ev, char **str)
Definition: pfmlib_core.c:820
#define PMU_CORE_COUNTER_WIDTH
Definition: pfmlib_core.c:799
static void pfm_core_get_impl_counters(pfmlib_regmask_t *impl_counters)
Definition: pfmlib_core.c:784
#define PFMLIB_CORE_ALL_FLAGS
Definition: pfmlib_core.c:81
static unsigned int pfm_core_get_num_event_masks(unsigned int ev)
Definition: pfmlib_core.c:853
#define PMU_CORE_NUM_COUNTERS
Definition: pfmlib_core.h:43
#define PFM_CORE_SEL_INV
Definition: pfmlib_core.h:68
#define PFM_CORE_SEL_EDGE
Definition: pfmlib_core.h:69
#define PFMLIB_CORE_UMASK_NCOMBO
#define PFMLIB_CORE_FIXED1
#define PFMLIB_CORE_FIXED0
#define PFMLIB_CORE_FIXED2_ONLY
#define PFMLIB_CORE_PMC1
#define PFMLIB_CORE_PEBS
#define PFMLIB_CORE_CSPEC
#define PFMLIB_CORE_PMC0
#define PFMLIB_CORE_MESI
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_CNT_FIRST
Definition: pfmlib_priv.h:62
unsigned long cnt_mask
Definition: pfmlib_core.h:64
unsigned int flags
Definition: pfmlib_core.h:65
pfmlib_core_pebs_t pfp_core_pebs
Definition: pfmlib_core.h:80
pfmlib_core_counter_t pfp_core_counters[PMU_CORE_NUM_COUNTERS]
Definition: pfmlib_core.h:79
unsigned int pebs_used
Definition: pfmlib_core.h:75
unsigned int num_masks
Definition: pfmlib.h:90
unsigned int plm
Definition: pfmlib.h:87
unsigned int unit_masks[PFMLIB_MAX_MASKS_PER_EVENT]
Definition: pfmlib.h:89
unsigned int event
Definition: pfmlib.h:86
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 reg_alt_addr
Definition: pfmlib.h:102
unsigned long long reg_addr
Definition: pfmlib.h:99
char * pme_desc
unsigned int pme_numasks
pme_core_umask_t pme_umasks[PFMLIB_CORE_MAX_UMASK]
unsigned int pme_code
unsigned int pme_flags
char * pme_name
unsigned int pme_flags
unsigned int pme_ucode
unsigned long sel_cnt_mask
Definition: pfmlib_core.h:58
unsigned long sel_os
Definition: pfmlib_core.h:51
unsigned long sel_inv
Definition: pfmlib_core.h:57
unsigned long sel_en
Definition: pfmlib_core.h:56
unsigned long long val
Definition: pfmlib_core.h:46
unsigned long sel_event_select
Definition: pfmlib_core.h:48
unsigned long sel_usr
Definition: pfmlib_core.h:50
unsigned long sel_unit_mask
Definition: pfmlib_core.h:49
unsigned long sel_int
Definition: pfmlib_core.h:54
unsigned long sel_edge
Definition: pfmlib_core.h:52