PAPI 7.1.0.0
Loading...
Searching...
No Matches
pfmlib_intel_atom.c
Go to the documentation of this file.
1/*
2 * pfmlib_intel_atom.c : Intel Atom PMU
3 *
4 * Copyright (c) 2008 Google, Inc
5 * Contributed by Stephane Eranian <eranian@gmail.com>
6 *
7 * Based on work:
8 * Copyright (c) 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 *
29 * This file implements support for Intel Core PMU as specified in the following document:
30 * "IA-32 Intel Architecture Software Developer's Manual - Volume 3B: System
31 * Programming Guide"
32 *
33 * Intel Atom = architectural v3 + PEBS
34 */
35#include <sys/types.h>
36#include <ctype.h>
37#include <string.h>
38#include <stdlib.h>
39#include <stdio.h>
40
41/* public headers */
43
44/* private headers */
45#include "pfmlib_priv.h"
47
48#include "intel_atom_events.h"
49
50/* let's define some handy shortcuts! */
51#define sel_event_select perfevtsel.sel_event_select
52#define sel_unit_mask perfevtsel.sel_unit_mask
53#define sel_usr perfevtsel.sel_usr
54#define sel_os perfevtsel.sel_os
55#define sel_edge perfevtsel.sel_edge
56#define sel_pc perfevtsel.sel_pc
57#define sel_int perfevtsel.sel_int
58#define sel_en perfevtsel.sel_en
59#define sel_inv perfevtsel.sel_inv
60#define sel_cnt_mask perfevtsel.sel_cnt_mask
61#define sel_any perfevtsel.sel_any
62
63#define has_pebs(i) (intel_atom_pe[i].pme_flags & PFMLIB_INTEL_ATOM_PEBS)
64
65
66/*
67 * Description of the PMC register mappings:
68 *
69 * 0 -> PMC0 -> PERFEVTSEL0
70 * 1 -> PMC1 -> PERFEVTSEL1
71 * 16 -> PMC16 -> FIXED_CTR_CTRL
72 * 17 -> PMC17 -> PEBS_ENABLED
73 *
74 * Description of the PMD register mapping:
75 *
76 * 0 -> PMD0 -> PMC0
77 * 1 -> PMD1 -> PMC1
78 * 16 -> PMD2 -> FIXED_CTR0
79 * 17 -> PMD3 -> FIXED_CTR1
80 * 18 -> PMD4 -> FIXED_CTR2
81 */
82#define INTEL_ATOM_SEL_BASE 0x186
83#define INTEL_ATOM_CTR_BASE 0xc1
84#define FIXED_CTR_BASE 0x309
85
86#define PFMLIB_INTEL_ATOM_ALL_FLAGS \
87 (PFM_INTEL_ATOM_SEL_INV|PFM_INTEL_ATOM_SEL_EDGE|PFM_INTEL_ATOM_SEL_ANYTHR)
88
90static int highest_counter;
91
92static int
94{
95 int ret, family, model;
96 char buffer[128];
97
98 ret = __pfm_getcpuinfo_attr("vendor_id", buffer, sizeof(buffer));
99 if (ret == -1)
100 return PFMLIB_ERR_NOTSUPP;
101
102 if (strcmp(buffer, "GenuineIntel"))
103 return PFMLIB_ERR_NOTSUPP;
104
105 ret = __pfm_getcpuinfo_attr("cpu family", buffer, sizeof(buffer));
106 if (ret == -1)
107 return PFMLIB_ERR_NOTSUPP;
108
109 family = atoi(buffer);
110
111 ret = __pfm_getcpuinfo_attr("model", buffer, sizeof(buffer));
112 if (ret == -1)
113 return PFMLIB_ERR_NOTSUPP;
114
115 model = atoi(buffer);
116
117 /*
118 * Atom : family 6 model 28
119 */
120 return family == 6 && model == 28 ? PFMLIB_SUCCESS : PFMLIB_ERR_NOTSUPP;
121}
122
123static int
125{
126 int i;
127
128 /* generic counters */
131
134
135 /* fixed counters */
137
141
142 /* lbr */
144 for(i=0; i < 16; i++)
146
147 highest_counter = 18;
148
149 /* PEBS */
151
152 return PFMLIB_SUCCESS;
153}
154
155static int
157{
158 unsigned int fl, flc, i;
159 unsigned int mask = 0;
160
162
163 /*
164 * first pass: check if event as a whole supports fixed counters
165 */
166 switch(f) {
167 case 0:
169 break;
170 case 1:
172 break;
173 case 2:
175 break;
176 default:
177 return 0;
178 }
179 if (fl & mask)
180 return 1;
181 /*
182 * second pass: check if unit mask supports fixed counter
183 *
184 * reject if mask not found OR if not all unit masks have
185 * same fixed counter mask
186 */
187 flc = 0;
188 for(i=0; i < e->num_masks; i++) {
190 if (fl & mask)
191 flc++;
192 }
193 return flc > 0 && flc == e->num_masks ? 1 : 0;
194}
195
196/*
197 * IMPORTANT: the interface guarantees that pfp_pmds[] elements are returned in the order the events
198 * were submitted.
199 */
200static int
202{
203#define HAS_OPTIONS(x) (cntrs && (cntrs[x].flags || cntrs[x].cnt_mask))
204#define is_fixed_pmc(a) (a == 16 || a == 17 || a == 18)
205
209 pfmlib_reg_t *pc, *pd;
210 pfmlib_regmask_t *r_pmcs;
211 uint64_t val;
212 unsigned long plm;
213 unsigned long long fixed_ctr;
214 unsigned int npc, npmc0, npmc1, nf2;
215 unsigned int i, j, n, k, ucode, use_pebs = 0, done_pebs;
216 unsigned int assign_pc[PMU_INTEL_ATOM_NUM_COUNTERS];
217 unsigned int next_gen, last_gen;
218
219 npc = npmc0 = npmc1 = nf2 = 0;
220
221 e = inp->pfp_events;
222 pc = outp->pfp_pmcs;
223 pd = outp->pfp_pmds;
224 n = inp->pfp_event_count;
225 r_pmcs = &inp->pfp_unavail_pmcs;
226 cntrs = param ? param->pfp_intel_atom_counters : NULL;
227 use_pebs = param ? param->pfp_intel_atom_pebs_used : 0;
228
230 return PFMLIB_ERR_TOOMANY;
231
232 /*
233 * initilize to empty
234 */
235 for(i=0; i < PMU_INTEL_ATOM_NUM_COUNTERS; i++)
236 assign_pc[i] = -1;
237
238 /*
239 * error checking
240 */
241 for(i=0; i < n; i++) {
242 /*
243 * only supports two priv levels for perf counters
244 */
245 if (e[i].plm & (PFM_PLM1|PFM_PLM2))
246 return PFMLIB_ERR_INVAL;
247
248 /*
249 * check for valid flags
250 */
251 if (cntrs && cntrs[i].flags & ~PFMLIB_INTEL_ATOM_ALL_FLAGS)
252 return PFMLIB_ERR_INVAL;
253
254 if (intel_atom_pe[e[i].event].pme_flags & PFMLIB_INTEL_ATOM_UMASK_NCOMBO
255 && e[i].num_masks > 1) {
256 DPRINT("events does not support unit mask combination\n");
257 return PFMLIB_ERR_NOASSIGN;
258 }
259
260 /*
261 * check event-level single register constraint (PMC0, PMC1, FIXED_CTR2)
262 * fail if more than two events requested for the same counter
263 */
264 if (intel_atom_pe[e[i].event].pme_flags & PFMLIB_INTEL_ATOM_PMC0) {
265 if (++npmc0 > 1) {
266 DPRINT("two events compete for a PMC0\n");
267 return PFMLIB_ERR_NOASSIGN;
268 }
269 }
270 /*
271 * check if PMC1 is available and if only one event is dependent on it
272 */
273 if (intel_atom_pe[e[i].event].pme_flags & PFMLIB_INTEL_ATOM_PMC1) {
274 if (++npmc1 > 1) {
275 DPRINT("two events compete for a PMC1\n");
276 return PFMLIB_ERR_NOASSIGN;
277 }
278 }
279 /*
280 * UNHALTED_REFERENCE_CYCLES can only be measured on FIXED_CTR2
281 */
282 if (intel_atom_pe[e[i].event].pme_flags & PFMLIB_INTEL_ATOM_FIXED2_ONLY) {
283 if (++nf2 > 1) {
284 DPRINT("two events compete for FIXED_CTR2\n");
285 return PFMLIB_ERR_NOASSIGN;
286 }
287 if (cntrs && ((cntrs[i].flags & (PFM_INTEL_ATOM_SEL_EDGE|PFM_INTEL_ATOM_SEL_INV)) || cntrs[i].cnt_mask)) {
288 DPRINT("UNHALTED_REFERENCE_CYCLES only accepts anythr filter\n");
289 return PFMLIB_ERR_NOASSIGN;
290 }
291 }
292 /*
293 * unit-mask level constraint checking (PMC0, PMC1, FIXED_CTR2)
294 */
295 for(j=0; j < e[i].num_masks; j++) {
296 unsigned int flags;
297
299
300 if (flags & PFMLIB_INTEL_ATOM_FIXED2_ONLY) {
301 if (++nf2 > 1) {
302 DPRINT("two events compete for FIXED_CTR2\n");
303 return PFMLIB_ERR_NOASSIGN;
304 }
305 if (HAS_OPTIONS(i)) {
306 DPRINT("fixed counters do not support inversion/counter-mask\n");
307 return PFMLIB_ERR_NOASSIGN;
308 }
309 }
310 }
311 }
312
313 next_gen = 0; /* first generic counter */
314 last_gen = 1; /* last generic counter */
315
316 /*
317 * strongest constraint first: works only in IA32_PMC0, IA32_PMC1, FIXED_CTR2
318 *
319 * When PEBS is used, we pick the first PEBS event and
320 * place it into PMC0. Subsequent PEBS events, will go
321 * in the other counters.
322 */
323 done_pebs = 0;
324 for(i=0; i < n; i++) {
325 if ((intel_atom_pe[e[i].event].pme_flags & PFMLIB_INTEL_ATOM_PMC0)
326 || (use_pebs && pfm_intel_atom_has_pebs(e+i) && done_pebs == 0)) {
327 if (pfm_regmask_isset(r_pmcs, 0))
328 return PFMLIB_ERR_NOASSIGN;
329 assign_pc[i] = 0;
330 next_gen = 1;
331 done_pebs = 1;
332 }
333 if (intel_atom_pe[e[i].event].pme_flags & PFMLIB_INTEL_ATOM_PMC1) {
334 if (pfm_regmask_isset(r_pmcs, 1))
335 return PFMLIB_ERR_NOASSIGN;
336 assign_pc[i] = 1;
337 if (next_gen == 1)
338 next_gen = 2;
339 else
340 next_gen = 0;
341 }
342 }
343 /*
344 * next constraint: fixed counters
345 *
346 * We abuse the mapping here for assign_pc to make it easier
347 * to provide the correct values for pd[].
348 * We use:
349 * - 16 : fixed counter 0 (pmc16, pmd16)
350 * - 17 : fixed counter 1 (pmc16, pmd17)
351 * - 18 : fixed counter 1 (pmc16, pmd18)
352 */
353 fixed_ctr = pfm_regmask_isset(r_pmcs, 16) ? 0 : 0x7;
354 if (fixed_ctr) {
355 for(i=0; i < n; i++) {
356 /* fixed counters do not support event options (filters) */
357 if (HAS_OPTIONS(i)) {
358 if (use_pebs && pfm_intel_atom_has_pebs(e+i))
359 continue;
360 if (cntrs[i].flags != PFM_INTEL_ATOM_SEL_ANYTHR)
361 continue;
362 }
363 if ((fixed_ctr & 0x1) && pfm_intel_atom_is_fixed(e+i, 0)) {
364 assign_pc[i] = 16;
365 fixed_ctr &= ~1;
366 }
367 if ((fixed_ctr & 0x2) && pfm_intel_atom_is_fixed(e+i, 1)) {
368 assign_pc[i] = 17;
369 fixed_ctr &= ~2;
370 }
371 if ((fixed_ctr & 0x4) && pfm_intel_atom_is_fixed(e+i, 2)) {
372 assign_pc[i] = 18;
373 fixed_ctr &= ~4;
374 }
375 }
376 }
377 /*
378 * assign what is left
379 */
380 for(i=0; i < n; i++) {
381 if (assign_pc[i] == -1) {
382 for(; next_gen <= last_gen; next_gen++) {
383 if (!pfm_regmask_isset(r_pmcs, next_gen))
384 break;
385 }
386 if (next_gen <= last_gen)
387 assign_pc[i] = next_gen++;
388 else {
389 DPRINT("cannot assign generic counters\n");
390 return PFMLIB_ERR_NOASSIGN;
391 }
392 }
393 }
394 j = 0;
395
396 /* setup fixed counters */
397 reg.val = 0;
398 k = 0;
399 for (i=0; i < n ; i++ ) {
400 if (!is_fixed_pmc(assign_pc[i]))
401 continue;
402 val = 0;
403 /* if plm is 0, then assume not specified per-event and use default */
404 plm = e[i].plm ? e[i].plm : inp->pfp_dfl_plm;
405 if (plm & PFM_PLM0)
406 val |= 1ULL;
407 if (plm & PFM_PLM3)
408 val |= 2ULL;
409 if (cntrs && cntrs[i].flags & PFM_INTEL_ATOM_SEL_ANYTHR)
410 val |= 4ULL;
411 val |= 1ULL << 3; /* force APIC int (kernel may force it anyway) */
412
413 reg.val |= val << ((assign_pc[i]-16)<<2);
414 }
415
416 if (reg.val) {
417 pc[npc].reg_num = 16;
418 pc[npc].reg_value = reg.val;
419 pc[npc].reg_addr = 0x38D;
420 pc[npc].reg_alt_addr = 0x38D;
421
422 __pfm_vbprintf("[FIXED_CTRL(pmc%u)=0x%"PRIx64" pmi0=1 en0=0x%"PRIx64" any0=%d pmi1=1 en1=0x%"PRIx64" any1=%d pmi2=1 en2=0x%"PRIx64" any2=%d] ",
423 pc[npc].reg_num,
424 reg.val,
425 reg.val & 0x3ULL,
426 !!(reg.val & 0x4ULL),
427 (reg.val>>4) & 0x3ULL,
428 !!((reg.val>>4) & 0x4ULL),
429 (reg.val>>8) & 0x3ULL,
430 !!((reg.val>>8) & 0x4ULL));
431
432 if ((fixed_ctr & 0x1) == 0)
433 __pfm_vbprintf("INSTRUCTIONS_RETIRED ");
434 if ((fixed_ctr & 0x2) == 0)
435 __pfm_vbprintf("UNHALTED_CORE_CYCLES ");
436 if ((fixed_ctr & 0x4) == 0)
437 __pfm_vbprintf("UNHALTED_REFERENCE_CYCLES ");
438 __pfm_vbprintf("\n");
439
440 npc++;
441
442 if ((fixed_ctr & 0x1) == 0)
443 __pfm_vbprintf("[FIXED_CTR0(pmd16)]\n");
444 if ((fixed_ctr & 0x2) == 0)
445 __pfm_vbprintf("[FIXED_CTR1(pmd17)]\n");
446 if ((fixed_ctr & 0x4) == 0)
447 __pfm_vbprintf("[FIXED_CTR2(pmd18)]\n");
448 }
449
450 for (i=0; i < n ; i++ ) {
451 /* skip fixed counters */
452 if (is_fixed_pmc(assign_pc[i]))
453 continue;
454
455 reg.val = 0; /* assume reserved bits are zerooed */
456
457 /* if plm is 0, then assume not specified per-event and use default */
458 plm = e[i].plm ? e[i].plm : inp->pfp_dfl_plm;
459
460 val = intel_atom_pe[e[i].event].pme_code;
461
462 reg.sel_event_select = val & 0xff;
463
464 ucode = (val >> 8) & 0xff;
465
466 for(k=0; k < e[i].num_masks; k++)
467 ucode |= intel_atom_pe[e[i].event].pme_umasks[e[i].unit_masks[k]].pme_ucode;
468
469 val |= ucode << 8;
470
471 reg.sel_unit_mask = ucode;
472 reg.sel_usr = plm & PFM_PLM3 ? 1 : 0;
473 reg.sel_os = plm & PFM_PLM0 ? 1 : 0;
474 reg.sel_en = 1; /* force enable bit to 1 */
475 reg.sel_int = 1; /* force APIC int to 1 */
476
477 reg.sel_cnt_mask = val >>24;
478 reg.sel_inv = val >> 23;
479 reg.sel_edge = val >> 18;
480 reg.sel_any = val >> 21;;
481
482 if (cntrs) {
483 if (!reg.sel_cnt_mask) {
484 /*
485 * counter mask is 8-bit wide, do not silently
486 * wrap-around
487 */
488 if (cntrs[i].cnt_mask > 255)
489 return PFMLIB_ERR_INVAL;
490 reg.sel_cnt_mask = cntrs[i].cnt_mask;
491 }
492
493 if (!reg.sel_edge)
494 reg.sel_edge = cntrs[i].flags & PFM_INTEL_ATOM_SEL_EDGE ? 1 : 0;
495 if (!reg.sel_inv)
496 reg.sel_inv = cntrs[i].flags & PFM_INTEL_ATOM_SEL_INV ? 1 : 0;
497 if (!reg.sel_any)
498 reg.sel_any = cntrs[i].flags & PFM_INTEL_ATOM_SEL_ANYTHR? 1 : 0;
499 }
500
501 pc[npc].reg_num = assign_pc[i];
502 pc[npc].reg_value = reg.val;
503 pc[npc].reg_addr = INTEL_ATOM_SEL_BASE+assign_pc[i];
504 pc[npc].reg_alt_addr= INTEL_ATOM_SEL_BASE+assign_pc[i];
505
506 __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",
507 pc[npc].reg_num,
508 pc[npc].reg_num,
509 reg.val,
511 reg.sel_unit_mask,
512 reg.sel_os,
513 reg.sel_usr,
514 reg.sel_en,
515 reg.sel_int,
516 reg.sel_inv,
517 reg.sel_edge,
518 reg.sel_cnt_mask,
519 reg.sel_any,
521
522 __pfm_vbprintf("[PMC%u(pmd%u)]\n",
523 pc[npc].reg_num,
524 pc[npc].reg_num);
525
526 npc++;
527 }
528 /*
529 * setup pmds: must be in the same order as the events
530 */
531 for (i=0; i < n ; i++) {
532 if (is_fixed_pmc(assign_pc[i])) {
533 /* setup pd array */
534 pd[i].reg_num = assign_pc[i];
535 pd[i].reg_addr = FIXED_CTR_BASE+assign_pc[i]-16;
536 pd[i].reg_alt_addr = 0x40000000+assign_pc[i]-16;
537 } else {
538 pd[i].reg_num = assign_pc[i];
539 pd[i].reg_addr = INTEL_ATOM_CTR_BASE+assign_pc[i];
540 /* index to use with RDPMC */
541 pd[i].reg_alt_addr = assign_pc[i];
542 }
543 }
544 outp->pfp_pmd_count = i;
545
546 /*
547 * setup PEBS_ENABLE
548 */
549 if (use_pebs && done_pebs) {
550 /*
551 * check that PEBS_ENABLE is available
552 */
553 if (pfm_regmask_isset(r_pmcs, 17))
554 return PFMLIB_ERR_NOASSIGN;
555 pc[npc].reg_num = 17;
556 pc[npc].reg_value = 1ULL;
557 pc[npc].reg_addr = 0x3f1; /* IA32_PEBS_ENABLE */
558 pc[npc].reg_alt_addr = 0x3f1; /* IA32_PEBS_ENABLE */
559
560 __pfm_vbprintf("[PEBS_ENABLE(pmc%u)=0x%"PRIx64" ena=%d]\n",
561 pc[npc].reg_num,
562 pc[npc].reg_value,
563 pc[npc].reg_value & 0x1ull);
564
565 npc++;
566
567 }
568 outp->pfp_pmc_count = npc;
569
570 return PFMLIB_SUCCESS;
571}
572
573static int
575{
577
578 if (inp->pfp_dfl_plm & (PFM_PLM1|PFM_PLM2)) {
579 DPRINT("invalid plm=%x\n", inp->pfp_dfl_plm);
580 return PFMLIB_ERR_INVAL;
581 }
582 return pfm_intel_atom_dispatch_counters(inp, mod_in, outp);
583}
584
585static int
586pfm_intel_atom_get_event_code(unsigned int i, unsigned int cnt, int *code)
587{
588 if (cnt != PFMLIB_CNT_FIRST
589 && (cnt > highest_counter ||
591 return PFMLIB_ERR_INVAL;
592
593 *code = intel_atom_pe[i].pme_code;
594
595 return PFMLIB_SUCCESS;
596}
597
598static void
600{
601 unsigned int n, i;
602 unsigned int has_f0, has_f1, has_f2;
603
604 memset(counters, 0, sizeof(*counters));
605
607 has_f0 = has_f1 = has_f2 = 0;
608
609 for (i=0; i < n; i++) {
610 if (intel_atom_pe[j].pme_umasks[i].pme_flags & PFMLIB_INTEL_ATOM_FIXED0)
611 has_f0 = 1;
612 if (intel_atom_pe[j].pme_umasks[i].pme_flags & PFMLIB_INTEL_ATOM_FIXED1)
613 has_f1 = 1;
614 if (intel_atom_pe[j].pme_umasks[i].pme_flags & PFMLIB_INTEL_ATOM_FIXED2_ONLY)
615 has_f2 = 1;
616 }
617
618 if (has_f0 == 0)
620 if (has_f1 == 0)
622 if (has_f2 == 0)
624
625 if (has_f0)
626 pfm_regmask_set(counters, 16);
627 if (has_f1)
628 pfm_regmask_set(counters, 17);
629 if (has_f2)
630 pfm_regmask_set(counters, 18);
631
632 /* the event on FIXED_CTR2 is exclusive CPU_CLK_UNHALTED:REF */
633 if (!has_f2) {
634 pfm_regmask_set(counters, 0);
635 pfm_regmask_set(counters, 1);
636
637 if (intel_atom_pe[j].pme_flags & PFMLIB_INTEL_ATOM_PMC0)
638 pfm_regmask_clr(counters, 1);
639 if (intel_atom_pe[j].pme_flags & PFMLIB_INTEL_ATOM_PMC1)
640 pfm_regmask_clr(counters, 0);
641 }
642}
643
644static void
646{
647 *impl_pmcs = intel_atom_impl_pmcs;
648}
649
650static void
652{
653 *impl_pmds = intel_atom_impl_pmds;
654}
655
656static void
658{
659 pfm_regmask_set(impl_counters, 0);
660 pfm_regmask_set(impl_counters, 1);
661 pfm_regmask_set(impl_counters, 16);
662 pfm_regmask_set(impl_counters, 17);
663 pfm_regmask_set(impl_counters, 18);
664}
665
666/*
667 * Even though, CPUID 0xa returns in eax the actual counter
668 * width, the architecture specifies that writes are limited
669 * to lower 32-bits. As such, only the lower 32-bit have full
670 * degree of freedom. That is the "useable" counter width.
671 */
672#define PMU_INTEL_ATOM_COUNTER_WIDTH 32
673
674static void
676{
677 /*
678 * Even though, CPUID 0xa returns in eax the actual counter
679 * width, the architecture specifies that writes are limited
680 * to lower 32-bits. As such, only the lower 31 bits have full
681 * degree of freedom. That is the "useable" counter width.
682 */
684}
685
686static char *
688{
689 return intel_atom_pe[i].pme_name;
690}
691
692static int
693pfm_intel_atom_get_event_description(unsigned int ev, char **str)
694{
695 char *s;
697 if (s) {
698 *str = strdup(s);
699 } else {
700 *str = NULL;
701 }
702 return PFMLIB_SUCCESS;
703}
704
705static char *
706pfm_intel_atom_get_event_mask_name(unsigned int ev, unsigned int midx)
707{
708 return intel_atom_pe[ev].pme_umasks[midx].pme_uname;
709}
710
711static int
712pfm_intel_atom_get_event_mask_desc(unsigned int ev, unsigned int midx, char **str)
713{
714 char *s;
715
717 if (s) {
718 *str = strdup(s);
719 } else {
720 *str = NULL;
721 }
722 return PFMLIB_SUCCESS;
723}
724
725static unsigned int
727{
728 return intel_atom_pe[ev].pme_numasks;
729}
730
731static int
732pfm_intel_atom_get_event_mask_code(unsigned int ev, unsigned int midx, unsigned int *code)
733{
734 *code =intel_atom_pe[ev].pme_umasks[midx].pme_ucode;
735 return PFMLIB_SUCCESS;
736}
737
738static int
740{
742 return PFMLIB_SUCCESS;
743}
744
745static int
747{
749 return PFMLIB_SUCCESS;
750}
751
752/*
753 * this function is directly accessible by external caller
754 * library initialization is not required, though recommended
755 */
756int
758{
759 unsigned int i, n=0;
760
761 if (e == NULL || e->event >= PME_INTEL_ATOM_EVENT_COUNT)
762 return 0;
763
765 return 1;
766
767 /*
768 * ALL unit mask must support PEBS for this test to return true
769 */
770 for(i=0; i < e->num_masks; i++) {
771 /* check for valid unit mask */
773 return 0;
775 n++;
776 }
777 return n > 0 && n == e->num_masks;
778}
779
781 .pmu_name = "Intel Atom",
782 .pmu_type = PFMLIB_INTEL_ATOM_PMU,
783 .pme_count = PME_INTEL_ATOM_EVENT_COUNT,
784 .pmc_count = 4,
785 .pmd_count = 22,
786 .num_cnt = 5,
787 .get_event_code = pfm_intel_atom_get_event_code,
788 .get_event_name = pfm_intel_atom_get_event_name,
789 .get_event_counters = pfm_intel_atom_get_event_counters,
790 .dispatch_events = pfm_intel_atom_dispatch_events,
791 .pmu_detect = pfm_intel_atom_detect,
792 .pmu_init = pfm_intel_atom_init,
793 .get_impl_pmcs = pfm_intel_atom_get_impl_pmcs,
794 .get_impl_pmds = pfm_intel_atom_get_impl_pmds,
795 .get_impl_counters = pfm_intel_atom_get_impl_counters,
796 .get_hw_counter_width = pfm_intel_atom_get_hw_counter_width,
797 .get_event_desc = pfm_intel_atom_get_event_description,
798 .get_num_event_masks = pfm_intel_atom_get_num_event_masks,
799 .get_event_mask_name = pfm_intel_atom_get_event_mask_name,
800 .get_event_mask_code = pfm_intel_atom_get_event_mask_code,
801 .get_event_mask_desc = pfm_intel_atom_get_event_mask_desc,
802 .get_cycle_event = pfm_intel_atom_get_cycle_event,
803 .get_inst_retired_event = pfm_intel_atom_get_inst_retired
804};
int i
double s
Definition: byte_profile.c:36
double f(double a)
Definition: cpi.c:23
#define PME_INTEL_ATOM_EVENT_COUNT
#define PME_INTEL_ATOM_UNHALTED_CORE_CYCLES
#define PME_INTEL_ATOM_INSTRUCTIONS_RETIRED
static pme_intel_atom_entry_t intel_atom_pe[]
#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
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
#define PFMLIB_INTEL_ATOM_PMU
Definition: pfmlib.h:237
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 pfmlib_regmask_t intel_atom_impl_pmds
static int pfm_intel_atom_get_cycle_event(pfmlib_event_t *e)
static void pfm_intel_atom_get_event_counters(unsigned int j, pfmlib_regmask_t *counters)
#define HAS_OPTIONS(x)
static pfmlib_regmask_t intel_atom_impl_pmcs
static int pfm_intel_atom_detect(void)
#define INTEL_ATOM_SEL_BASE
static int pfm_intel_atom_dispatch_counters(pfmlib_input_param_t *inp, pfmlib_intel_atom_input_param_t *param, pfmlib_output_param_t *outp)
static int pfm_intel_atom_get_event_description(unsigned int ev, char **str)
static void pfm_intel_atom_get_hw_counter_width(unsigned int *width)
static char * pfm_intel_atom_get_event_name(unsigned int i)
#define INTEL_ATOM_CTR_BASE
#define is_fixed_pmc(a)
static int highest_counter
#define FIXED_CTR_BASE
static void pfm_intel_atom_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
static unsigned int pfm_intel_atom_get_num_event_masks(unsigned int ev)
int pfm_intel_atom_has_pebs(pfmlib_event_t *e)
pfm_pmu_support_t intel_atom_support
#define PMU_INTEL_ATOM_COUNTER_WIDTH
static int pfm_intel_atom_get_inst_retired(pfmlib_event_t *e)
static char * pfm_intel_atom_get_event_mask_name(unsigned int ev, unsigned int midx)
static int pfm_intel_atom_init(void)
static int pfm_intel_atom_get_event_code(unsigned int i, unsigned int cnt, int *code)
static int pfm_intel_atom_get_event_mask_desc(unsigned int ev, unsigned int midx, char **str)
static int pfm_intel_atom_is_fixed(pfmlib_event_t *e, unsigned int f)
static int pfm_intel_atom_dispatch_events(pfmlib_input_param_t *inp, void *model_in, pfmlib_output_param_t *outp, void *model_out)
static void pfm_intel_atom_get_impl_counters(pfmlib_regmask_t *impl_counters)
#define PFMLIB_INTEL_ATOM_ALL_FLAGS
static void pfm_intel_atom_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
static int pfm_intel_atom_get_event_mask_code(unsigned int ev, unsigned int midx, unsigned int *code)
#define PMU_INTEL_ATOM_NUM_COUNTERS
#define PFM_INTEL_ATOM_SEL_ANYTHR
#define PFM_INTEL_ATOM_SEL_EDGE
#define PFM_INTEL_ATOM_SEL_INV
#define PFMLIB_INTEL_ATOM_FIXED0
#define PFMLIB_INTEL_ATOM_PMC0
#define PFMLIB_INTEL_ATOM_UMASK_NCOMBO
#define PFMLIB_INTEL_ATOM_PEBS
#define PFMLIB_INTEL_ATOM_FIXED2_ONLY
#define PFMLIB_INTEL_ATOM_FIXED1
#define PFMLIB_INTEL_ATOM_PMC1
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 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_intel_atom_counter_t pfp_intel_atom_counters[PMU_INTEL_ATOM_NUM_COUNTERS]
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_intel_atom_umask_t pme_umasks[PFMLIB_INTEL_ATOM_MAX_UMASK]
char * pme_name
unsigned int pme_code
unsigned int pme_flags
unsigned long long val