PAPI 7.1.0.0
Loading...
Searching...
No Matches
pfmlib_gen_ia64.c
Go to the documentation of this file.
1/*
2 * pfmlib_gen_ia64.c : support default architected IA-64 PMU features
3 *
4 * Copyright (c) 2001-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#include <sys/types.h>
25#include <string.h>
26#include <stdio.h>
27#include <stdlib.h>
28
29#include <perfmon/pfmlib.h>
31
32#include "pfmlib_priv.h" /* library private */
33#include "pfmlib_priv_ia64.h" /* architecture private */
34
35#define PMU_GEN_IA64_MAX_COUNTERS 4
36/*
37 * number of architected events
38 */
39#define PME_GEN_COUNT 2
40
41/*
42 * Description of the PMC register mappings use by
43 * this module (as reported in pfmlib_reg_t.reg_num):
44 *
45 * 0 -> PMC0
46 * 1 -> PMC1
47 * n -> PMCn
48 */
49#define PFMLIB_GEN_IA64_PMC_BASE 0
50
51/*
52 * generic event as described by architecture
53 */
54typedef struct {
55 unsigned long pme_code:8; /* major event code */
56 unsigned long pme_ig:56; /* ignored */
58
59/*
60 * union of all possible entry codes. All encodings must fit in 64bit
61 */
62typedef union {
63 unsigned long pme_vcode;
66
67/*
68 * entry in the event table (one table per implementation)
69 */
70typedef struct pme_entry {
71 char *pme_name;
73 pfmlib_regmask_t pme_counters; /* counter bitmask */
75
76/* let's define some handy shortcuts ! */
77#define pmc_plm pmc_gen_count_reg.pmc_plm
78#define pmc_ev pmc_gen_count_reg.pmc_ev
79#define pmc_oi pmc_gen_count_reg.pmc_oi
80#define pmc_pm pmc_gen_count_reg.pmc_pm
81#define pmc_es pmc_gen_count_reg.pmc_es
82
83/*
84 * this table is patched by initialization code
85 */
87#define PME_IA64_GEN_CPU_CYCLES 0
88 { "CPU_CYCLES", },
89#define PME_IA64_GEN_INST_RETIRED 1
90 { "IA64_INST_RETIRED", },
91};
92
97/*
98 * Description of the PMC register mappings use by
99 * this module (as reported in pfmlib_reg_t.reg_num):
100 *
101 * 0 -> PMC0
102 * 1 -> PMC1
103 * n -> PMCn
104 * We do not use a mapping table, instead we make up the
105 * values on the fly given the base.
106 */
107#define PFMLIB_GEN_IA64_PMC_BASE 0
108
109
110/*
111 * convert text range (e.g. 4-15 18 12-26) into actual bitmask
112 * range argument is modified
113 */
114static int
116{
117 char *p, c;
118 int start, end;
119
120 if (range[strlen(range)-1] == '\n')
121 range[strlen(range)-1] = '\0';
122
123 while(range) {
124 p = range;
125 while (*p && *p != ' ' && *p != '-') p++;
126
127 if (*p == '\0') break;
128
129 c = *p;
130 *p = '\0';
131 start = atoi(range);
132 range = p+1;
133
134 if (c == '-') {
135 p++;
136 while (*p && *p != ' ' && *p != '-') p++;
137 if (*p) *p++ = '\0';
138 end = atoi(range);
139 range = p;
140 } else {
141 end = start;
142 }
143
144 if (end >= PFMLIB_REG_MAX|| start >= PFMLIB_REG_MAX)
145 goto invalid;
146 for (; start <= end; start++)
148 }
149 return 0;
150invalid:
151 fprintf(stderr, "%s.%s : bitmask too small need %d bits\n", __FILE__, __FUNCTION__, start);
152 return -1;
153}
154
155static int
157{
158 FILE *fp;
159 char *p;
160 char buffer[64];
161 int matches = 0;
162
163 fp = fopen("/proc/pal/cpu0/perfmon_info", "r");
164 if (fp == NULL) return PFMLIB_ERR_NOTSUPP;
165
166 for (;;) {
167 p = fgets(buffer, sizeof(buffer)-1, fp);
168
169 if (p == NULL) break;
170
171 if ((p = strchr(buffer, ':')) == NULL) break;
172
173 *p = '\0';
174
175 if (!strncmp("Counter width", buffer, 13)) {
176 pfm_gen_ia64_counter_width = atoi(p+2);
177 matches++;
178 continue;
179 }
180 if (!strncmp("PMC/PMD pairs", buffer, 13)) {
181 pfm_gen_ia64_counters = atoi(p+2);
182 matches++;
183 continue;
184 }
185 if (!strncmp("Cycle event number", buffer, 18)) {
186 generic_pe[0].pme_entry_code.pme_vcode = atoi(p+2);
187 matches++;
188 continue;
189 }
190 if (!strncmp("Retired event number", buffer, 20)) {
191 generic_pe[1].pme_entry_code.pme_vcode = atoi(p+2);
192 matches++;
193 continue;
194 }
195 if (!strncmp("Cycles count capable", buffer, 20)) {
196 if (parse_counter_range(p+2, &generic_pe[0].pme_counters) == -1) return -1;
197 matches++;
198 continue;
199 }
200 if (!strncmp("Retired bundles count capable", buffer, 29)) {
201 if (parse_counter_range(p+2, &generic_pe[1].pme_counters) == -1) return -1;
202 matches++;
203 continue;
204 }
205 if (!strncmp("Implemented PMC", buffer, 15)) {
206 if (parse_counter_range(p+2, &pfm_gen_ia64_impl_pmcs) == -1) return -1;
207 matches++;
208 continue;
209 }
210 if (!strncmp("Implemented PMD", buffer, 15)) {
211 if (parse_counter_range(p+2, &pfm_gen_ia64_impl_pmds) == -1) return -1;
212 matches++;
213 continue;
214 }
215 }
218
219 fclose(fp);
220 return matches == 8 ? PFMLIB_SUCCESS : PFMLIB_ERR_NOTSUPP;
221}
222
223static void
225{
226 unsigned int i;
227
230
233
234 memset(&pfm_gen_ia64_impl_pmcs, 0, sizeof(pfmlib_regmask_t));
235 memset(&pfm_gen_ia64_impl_pmds, 0, sizeof(pfmlib_regmask_t));
236
237 for(i=0; i < 8; i++)
239
240 for(i=4; i < 8; i++)
242
243 memset(&generic_pe[0].pme_counters, 0, sizeof(pfmlib_regmask_t));
244 memset(&generic_pe[1].pme_counters, 0, sizeof(pfmlib_regmask_t));
245 for(i=4; i < 8; i++) {
246 pfm_regmask_set(&generic_pe[0].pme_counters, i);
247 pfm_regmask_set(&generic_pe[1].pme_counters, i);
248 }
252}
253
254static int
256{
257 /* PMU is architected, so guaranteed to be present */
258 return PFMLIB_SUCCESS;
259}
260
261static int
263{
264 if (forced_pmu != PFMLIB_NO_PMU) {
266 } else if (pfm_gen_ia64_initialize() == -1)
267 return PFMLIB_ERR_NOTSUPP;
268
269 return PFMLIB_SUCCESS;
270}
271
272static int
273valid_assign(unsigned int *as, pfmlib_regmask_t *r_pmcs, unsigned int cnt)
274{
275 unsigned int i;
276 for(i=0; i < cnt; i++) {
277 if (as[i]==0) return 0;
278 /*
279 * take care of restricted PMC registers
280 */
281 if (pfm_regmask_isset(r_pmcs, as[i]))
282 return 0;
283 }
284 return 1;
285}
286
287/*
288 * Automatically dispatch events to corresponding counters following constraints.
289 * Upon return the pfarg_reg_t structure is ready to be submitted to kernel
290 */
291static int
293{
294#define has_counter(e,b) (pfm_regmask_isset(&generic_pe[e].pme_counters, b) ? b : 0)
295 unsigned int max_l0, max_l1, max_l2, max_l3;
296 unsigned int assign[PMU_GEN_IA64_MAX_COUNTERS];
299 pfmlib_reg_t *pc, *pd;
300 pfmlib_regmask_t *r_pmcs;
301 unsigned int i,j,k,l;
302 unsigned int cnt;
303
304 e = inp->pfp_events;
305 pc = outp->pfp_pmcs;
306 pd = outp->pfp_pmds;
307 cnt = inp->pfp_event_count;
308 r_pmcs = &inp->pfp_unavail_pmcs;
309
311
316
317 if (PFMLIB_DEBUG()) {
318 DPRINT("max_l0=%u max_l1=%u max_l2=%u max_l3=%u\n", max_l0, max_l1, max_l2, max_l3);
319 }
320 /*
321 * This code needs fixing. It is not very pretty and
322 * won't handle more than 4 counters if more become
323 * available !
324 * For now, worst case in the loop nest: 4! (factorial)
325 */
326 for (i=PMU_GEN_IA64_FIRST_COUNTER; i < max_l0; i++) {
327
328 assign[0]= has_counter(e[0].event,i);
329
330 if (max_l1 == PMU_GEN_IA64_FIRST_COUNTER && valid_assign(assign, r_pmcs, cnt)) goto done;
331
332 for (j=PMU_GEN_IA64_FIRST_COUNTER; j < max_l1; j++) {
333
334 if (j == i) continue;
335
336 assign[1] = has_counter(e[1].event,j);
337
338 if (max_l2 == PMU_GEN_IA64_FIRST_COUNTER && valid_assign(assign, r_pmcs, cnt)) goto done;
339
340 for (k=PMU_GEN_IA64_FIRST_COUNTER; k < max_l2; k++) {
341
342 if(k == i || k == j) continue;
343
344 assign[2] = has_counter(e[2].event,k);
345
346 if (max_l3 == PMU_GEN_IA64_FIRST_COUNTER && valid_assign(assign, r_pmcs, cnt)) goto done;
347
348 for (l=PMU_GEN_IA64_FIRST_COUNTER; l < max_l3; l++) {
349
350 if(l == i || l == j || l == k) continue;
351
352 assign[3] = has_counter(e[3].event,l);
353
354 if (valid_assign(assign, r_pmcs, cnt)) goto done;
355 }
356 }
357 }
358 }
359 /* we cannot satisfy the constraints */
360 return PFMLIB_ERR_NOASSIGN;
361done:
362 memset(pc, 0, cnt*sizeof(pfmlib_reg_t));
363 memset(pd, 0, cnt*sizeof(pfmlib_reg_t));
364 for (j=0; j < cnt ; j++ ) {
365 reg.pmc_val = 0; /* clear all */
366 /* if not specified per event, then use default (could be zero: measure nothing) */
367 reg.pmc_plm = e[j].plm ? e[j].plm: inp->pfp_dfl_plm;
368 reg.pmc_oi = 1; /* overflow interrupt */
369 reg.pmc_pm = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE? 1 : 0;
371
372 pc[j].reg_num = assign[j];
373 pc[j].reg_value = reg.pmc_val;
375
376 pd[j].reg_num = assign[j];
377 pd[j].reg_addr = assign[j];
378
379 __pfm_vbprintf("[PMC%u(pmc%u)=0x%lx,es=0x%02x,plm=%d pm=%d] %s\n",
380 assign[j],
381 assign[j],
382 reg.pmc_val,
383 reg.pmc_es,reg.pmc_plm,
384 reg.pmc_pm,
386
387 __pfm_vbprintf("[PMD%u(pmd%u)]\n", pd[j].reg_num, pd[j].reg_num);
388 }
389 /* number of PMC programmed */
390 outp->pfp_pmc_count = cnt;
391 outp->pfp_pmd_count = cnt;
392
393 return PFMLIB_SUCCESS;
394}
395
396static int
398{
399 return pfm_gen_ia64_dispatch_counters(inp, outp);
400}
401
402static int
403pfm_gen_ia64_get_event_code(unsigned int i, unsigned int cnt, int *code)
404{
405 if (cnt != PFMLIB_CNT_FIRST && (cnt < 4 || cnt > 7))
406 return PFMLIB_ERR_INVAL;
407
408 *code = (int)generic_pe[i].pme_entry_code.pme_gen_code.pme_code;
409
410 return PFMLIB_SUCCESS;
411}
412
413static char *
415{
416 return generic_pe[i].pme_name;
417}
418
419static void
421{
422 unsigned int i;
423
424 memset(counters, 0, sizeof(*counters));
425
426 for(i=0; i < pfm_gen_ia64_counters; i++) {
427 if (pfm_regmask_isset(&generic_pe[j].pme_counters, i))
428 pfm_regmask_set(counters, i);
429 }
430}
431
432static void
434{
435 *impl_pmcs = pfm_gen_ia64_impl_pmcs;
436}
437
438static void
440{
441 *impl_pmds = pfm_gen_ia64_impl_pmds;
442}
443
444static void
446{
447 unsigned int i = 0;
448
449 /* pmd4-pmd7 */
450 for(i=4; i < 8; i++)
451 pfm_regmask_set(impl_counters, i);
452}
453
454static void
456{
458}
459
460static int
461pfm_gen_ia64_get_event_desc(unsigned int ev, char **str)
462{
463 switch(ev) {
465 *str = strdup("CPU cycles");
466 break;
468 *str = strdup("IA-64 instructions retired");
469 break;
470 default:
471 *str = NULL;
472 }
473 return PFMLIB_SUCCESS;
474}
475
476static int
478{
480 return PFMLIB_SUCCESS;
481
482}
483
484static int
486{
488 return PFMLIB_SUCCESS;
489}
490
492 .pmu_name ="IA-64",
493 .pmu_type = PFMLIB_GEN_IA64_PMU,
494 .pme_count = PME_GEN_COUNT,
495 .pmc_count = 4+4,
496 .pmd_count = PMU_GEN_IA64_MAX_COUNTERS,
497 .num_cnt = PMU_GEN_IA64_MAX_COUNTERS,
498 .get_event_code = pfm_gen_ia64_get_event_code,
499 .get_event_name = pfm_gen_ia64_get_event_name,
500 .get_event_counters = pfm_gen_ia64_get_event_counters,
501 .dispatch_events = pfm_gen_ia64_dispatch_events,
502 .pmu_detect = pfm_gen_ia64_detect,
503 .pmu_init = pfm_gen_ia64_init,
504 .get_impl_pmcs = pfm_gen_ia64_get_impl_pmcs,
505 .get_impl_pmds = pfm_gen_ia64_get_impl_pmds,
506 .get_impl_counters = pfm_gen_ia64_get_impl_counters,
507 .get_hw_counter_width = pfm_gen_ia64_get_hw_counter_width,
508 .get_event_desc = pfm_gen_ia64_get_event_desc,
509 .get_cycle_event = pfm_gen_ia64_get_cycle_event,
510 .get_inst_retired_event = pfm_gen_ia64_get_inst_retired
511};
int i
static struct timeval start
static double b[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:39
static double c[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:40
FILE * stderr
int fclose(FILE *__stream)
static FILE * fp
#define PFMLIB_GEN_IA64_PMU
Definition: pfmlib.h:223
static int pfm_regmask_set(pfmlib_regmask_t *h, unsigned int b)
Definition: pfmlib.h:321
#define PFMLIB_SUCCESS
Definition: pfmlib.h:283
#define PFMLIB_NO_PMU
Definition: pfmlib.h:221
static int pfm_regmask_weight(pfmlib_regmask_t *h, unsigned int *w)
Definition: pfmlib.h:343
#define PFMLIB_ERR_INVAL
Definition: pfmlib.h:285
#define PFMLIB_ERR_TOOMANY
Definition: pfmlib.h:295
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 PFMLIB_PFP_SYSTEMWIDE
Definition: pfmlib.h:121
#define PFMLIB_REG_MAX
Definition: pfmlib.h:66
#define PFMLIB_ERR_NOTSUPP
Definition: pfmlib.h:284
int forced_pmu
static pfmlib_regmask_t pfm_gen_ia64_impl_pmds
static pme_gen_ia64_entry_t generic_pe[PME_GEN_COUNT]
static void pfm_gen_ia64_get_hw_counter_width(unsigned int *width)
static int pfm_gen_ia64_init(void)
static void pfm_gen_ia64_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
static void pfm_gen_ia64_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
static int pfm_gen_ia64_dispatch_counters(pfmlib_input_param_t *inp, pfmlib_output_param_t *outp)
#define PME_IA64_GEN_CPU_CYCLES
static void pfm_gen_ia64_get_impl_counters(pfmlib_regmask_t *impl_counters)
#define PME_GEN_COUNT
static int pfm_gen_ia64_get_event_desc(unsigned int ev, char **str)
static void pfm_gen_ia64_get_event_counters(unsigned int j, pfmlib_regmask_t *counters)
#define PME_IA64_GEN_INST_RETIRED
#define has_counter(e, b)
static pfmlib_regmask_t pfm_gen_ia64_impl_pmcs
pfm_pmu_support_t generic_ia64_support
static int pfm_gen_ia64_dispatch_events(pfmlib_input_param_t *inp, void *dummy1, pfmlib_output_param_t *outp, void *dummy2)
static int pfm_gen_ia64_counters
static int valid_assign(unsigned int *as, pfmlib_regmask_t *r_pmcs, unsigned int cnt)
static int pfm_gen_ia64_initialize(void)
static int pfm_gen_ia64_get_cycle_event(pfmlib_event_t *e)
static int pfm_gen_ia64_detect(void)
#define PMU_GEN_IA64_MAX_COUNTERS
static int pfm_gen_ia64_get_event_code(unsigned int i, unsigned int cnt, int *code)
static int pfm_gen_ia64_get_inst_retired(pfmlib_event_t *e)
#define PFMLIB_GEN_IA64_PMC_BASE
static int pfm_gen_ia64_counter_width
static int parse_counter_range(char *range, pfmlib_regmask_t *b)
static void pfm_gen_ia64_forced_initialize(void)
static char * pfm_gen_ia64_get_event_name(unsigned int i)
#define PMU_GEN_IA64_FIRST_COUNTER
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
int
Definition: sde_internal.h:89
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 plm
Definition: pfmlib.h:87
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
unsigned int pfp_flags
Definition: pfmlib.h:111
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
unsigned long pme_ig
unsigned long pme_code
pme_gen_ia64_entry_code_t pme_entry_code
pfmlib_regmask_t pme_counters
char * pme_name
unsigned long pme_vcode
pme_gen_ia64_code_t pme_gen_code