PAPI 7.1.0.0
Loading...
Searching...
No Matches
pfmlib_sparc.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
3 *
4 * Based upon gen_powerpc code which is:
5 * Copyright (C) IBM Corporation, 2007. All rights reserved.
6 * Contributed by Corey Ashford (cjashfor@us.ibm.com)
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * IN THE SOFTWARE.
25 *
26 * pfmlib_sparc.c
27 *
28 * Support for libpfm for Sparc processors.
29 */
30
31#ifndef _GNU_SOURCE
32 #define _GNU_SOURCE /* for getline */
33#endif
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <limits.h>
38
39/* private headers */
40#include "pfmlib_priv.h"
41
42#include "pfmlib_sparc_priv.h"
43
44#include "ultra12_events.h"
45#include "ultra3_events.h"
46#include "ultra3i_events.h"
47#include "ultra3plus_events.h"
48#include "ultra4plus_events.h"
49#include "niagara1_events.h"
50#include "niagara2_events.h"
51
52static char *get_event_name(int event)
53{
54 switch (sparc_support.pmu_type) {
56 return ultra12_pe[event].pme_name;
58 return ultra3_pe[event].pme_name;
60 return ultra3i_pe[event].pme_name;
62 return ultra3plus_pe[event].pme_name;
64 return ultra4plus_pe[event].pme_name;
66 return niagara1_pe[event].pme_name;
68 return niagara2_pe[event].pme_name;
69 }
70 return (char *)-1;
71}
72
73static char *get_event_desc(int event)
74{
75 switch (sparc_support.pmu_type) {
77 return ultra12_pe[event].pme_desc;
79 return ultra3_pe[event].pme_desc;
81 return ultra3i_pe[event].pme_desc;
83 return ultra3plus_pe[event].pme_desc;
85 return ultra4plus_pe[event].pme_desc;
87 return niagara1_pe[event].pme_desc;
89 return niagara2_pe[event].pme_desc;
90 }
91 return (char *)-1;
92}
93
94static char get_ctrl(int event)
95{
96 switch (sparc_support.pmu_type) {
98 return ultra12_pe[event].pme_ctrl;
100 return ultra3_pe[event].pme_ctrl;
102 return ultra3i_pe[event].pme_ctrl;
104 return ultra3plus_pe[event].pme_ctrl;
106 return ultra4plus_pe[event].pme_ctrl;
108 return niagara1_pe[event].pme_ctrl;
110 return niagara2_pe[event].pme_ctrl;
111 }
112 return 0xff;
113}
114
115static int get_val(int event)
116{
117 switch (sparc_support.pmu_type) {
119 return ultra12_pe[event].pme_val;
121 return ultra3_pe[event].pme_val;
123 return ultra3i_pe[event].pme_val;
125 return ultra3plus_pe[event].pme_val;
127 return ultra4plus_pe[event].pme_val;
129 return niagara1_pe[event].pme_val;
131 return niagara2_pe[event].pme_val;
132 }
133 return -1;
134}
135
136static int pfm_sparc_get_event_code(unsigned int event,
137 unsigned int pmd,
138 int *code)
139{
140 *code = get_val(event);
141 return 0;
142}
143
144static char *pfm_sparc_get_event_name(unsigned int event)
145{
146 return get_event_name(event);
147}
148
149static char *pfm_sparc_get_event_mask_name(unsigned int event,
150 unsigned int mask)
151{
153
155 return "";
156
157 e = &niagara2_pe[event];
158 return e->pme_masks[mask].mask_name;
159}
160
161static void pfm_sparc_get_event_counters(unsigned int event,
162 pfmlib_regmask_t *counters)
163{
165 counters->bits[0] = (1 << 0) | (1 << 1);
166 } else {
167 char ctrl = get_ctrl(event);
168
169 counters->bits[0] = 0;
170 if (ctrl & PME_CTRL_S0)
171 counters->bits[0] |= (1 << 0);
172 if (ctrl & PME_CTRL_S1)
173 counters->bits[0] |= (1 << 1);
174 }
175}
176
177static unsigned int pfm_sparc_get_num_event_masks(unsigned int event)
178{
180 return 0;
181 return (event == 0 ? 0 : EVENT_MASK_BITS);
182}
183
184/* Bits common to all PCR implementations */
185#define PCR_PRIV (0x1UL << 0)
186#define PCR_SYS_TRACE (0x1UL << 1)
187#define PCR_USER_TRACE (0x1UL << 2)
188
189/* The S0 and S1 fields determine which events are monitored in
190 * the assosciated PIC (PIC0 vs. PIC1 respectively). For ultra12
191 * these fields are 4 bits, on ultra3/3i/3+/4+ they are 6 bits.
192 * For Niagara-1 there is only S0 and it is 3 bits in size.
193 * Niagara-1's PIC1 is hard-coded to record retired instructions.
194 */
195#define PCR_S0_SHIFT 4
196#define PCR_S0 (0x1fUL << PCR_S0_SHIFT)
197#define PCR_S1_SHIFT 11
198#define PCR_S1 (0x1fUL << PCR_S1_SHIFT)
199
200/* Niagara-2 specific PCR bits. It supports event masking. */
201#define PCR_N2_HYP_TRACE (0x1UL << 3)
202#define PCR_N2_TOE0 (0x1UL << 4)
203#define PCR_N2_TOE1 (0x1UL << 5)
204#define PCR_N2_SL0_SHIFT 14
205#define PCR_N2_SL0 (0xf << PCR_N2_SL0_SHIFT)
206#define PCR_N2_MASK0_SHIFT 6
207#define PCR_N2_MASK0 (0xff << PCR_N2_MASK0_SHIFT)
208#define PCR_N2_SL1_SHIFT 27
209#define PCR_N2_SL1 (0xf << PCR_N2_SL1_SHIFT)
210#define PCR_N2_MASK1_SHIFT 19
211#define PCR_N2_MASK1 (0xff << PCR_N2_MASK1_SHIFT)
212
214 void *model_input,
215 pfmlib_output_param_t *output,
216 void *model_output)
217{
218 unsigned long long pcr, vals[2];
219 unsigned int plm, i;
220 int niagara2;
221 char ctrls[2];
222
223 if (input->pfp_event_count > 2)
224 return PFMLIB_ERR_TOOMANY;
225
226 plm = ((input->pfp_events[0].plm != 0) ?
227 input->pfp_events[0].plm :
228 input->pfp_dfl_plm);
229 for (i = 1; i < input->pfp_event_count; i++) {
230 if (input->pfp_events[i].plm == 0) {
231 /* it's ok if the default is the same as plm */
232 if (plm != input->pfp_dfl_plm)
233 return PFMLIB_ERR_NOASSIGN;
234 } else {
235 if (plm != input->pfp_events[i].plm)
236 return PFMLIB_ERR_NOASSIGN;
237 }
238 }
239
240 niagara2 = 0;
242 niagara2 = 1;
243
244 pcr = 0;
245 if (plm & PFM_PLM3)
246 pcr |= PCR_USER_TRACE;
247 if (plm & PFM_PLM0)
248 pcr |= PCR_SYS_TRACE;
249 if (niagara2 && (plm & PFM_PLM1))
250 pcr |= PCR_N2_HYP_TRACE;
251
252 for (i = 0; i < input->pfp_event_count; i++) {
253 pfmlib_event_t *e = &input->pfp_events[i];
254
255 ctrls[i] = get_ctrl(e->event);
256 vals[i] = get_val(e->event);
257
258 if (i == 1) {
259 if ((ctrls[0] & ctrls[1]) == 0)
260 continue;
261
262 if (ctrls[0] == (PME_CTRL_S0|PME_CTRL_S1)) {
263 if (ctrls[1] == (PME_CTRL_S0|PME_CTRL_S1)) {
264 ctrls[0] = PME_CTRL_S0;
265 ctrls[1] = PME_CTRL_S1;
266 } else {
267 ctrls[0] &= ~ctrls[1];
268 }
269 } else if (ctrls[1] == (PME_CTRL_S0|PME_CTRL_S1)) {
270 ctrls[1] &= ~ctrls[0];
271 } else
272 return PFMLIB_ERR_INVAL;
273 }
274 }
275
276 if (input->pfp_event_count == 1) {
277 if (ctrls[0] == (PME_CTRL_S0|PME_CTRL_S1))
278 ctrls[0] = PME_CTRL_S0;
279 }
280
281 for (i = 0; i < input->pfp_event_count; i++) {
282 unsigned long long val = vals[i];
283 char ctrl = ctrls[i];
284
285 switch (ctrl) {
286 case PME_CTRL_S0:
287 output->pfp_pmds[i].reg_num = 0;
288 pcr |= (val <<
289 (niagara2 ?
291 PCR_S0_SHIFT));
292 break;
293
294 case PME_CTRL_S1:
295 output->pfp_pmds[i].reg_num = 1;
296 pcr |= (val <<
297 (niagara2 ?
299 PCR_S1_SHIFT));
300 break;
301
302 default:
303 return PFMLIB_ERR_INVAL;
304 }
305 if (niagara2) {
306 pfmlib_event_t *e = &input->pfp_events[i];
307 unsigned int j, shift;
308
309 if (ctrl == PME_CTRL_S0) {
310 pcr |= PCR_N2_TOE0;
311 shift = PCR_N2_MASK0_SHIFT;
312 } else {
313 pcr |= PCR_N2_TOE1;
314 shift = PCR_N2_MASK1_SHIFT;
315 }
316 for (j = 0; j < e->num_masks; j++) {
317 unsigned int mask;
318
319 mask = e->unit_masks[j];
320 if (mask >= EVENT_MASK_BITS)
321 return PFMLIB_ERR_INVAL;
322 pcr |= (1ULL << (shift + mask));
323 }
324 }
325
326 output->pfp_pmds[i].reg_value = 0;
327 output->pfp_pmds[i].reg_addr = 0;
328 output->pfp_pmds[i].reg_alt_addr = 0;
329 output->pfp_pmds[i].reg_reserved1 = 0;
330 output->pfp_pmd_count = i + 1;
331 }
332
333 output->pfp_pmcs[0].reg_value = pcr;
334 output->pfp_pmcs[0].reg_addr = 0;
335 output->pfp_pmcs[0].reg_num = 0;
336 output->pfp_pmcs[0].reg_reserved1 = 0;
337 output->pfp_pmc_count = 1;
338
339 return PFMLIB_SUCCESS;
340}
341
342static int pmu_name_to_pmu_type(char *name)
343{
344 if (!strcmp(name, "ultra12"))
346 if (!strcmp(name, "ultra3"))
348 if (!strcmp(name, "ultra3i"))
350 if (!strcmp(name, "ultra3+"))
352 if (!strcmp(name, "ultra4+"))
354 if (!strcmp(name, "niagara2"))
356 if (!strcmp(name, "niagara"))
358 return -1;
359}
360
361static int pfm_sparc_pmu_detect(void)
362{
363 int ret, pmu_type, pme_count;
364 char buffer[32];
365
366 ret = __pfm_getcpuinfo_attr("pmu", buffer, sizeof(buffer));
367 if (ret == -1)
368 return PFMLIB_ERR_NOTSUPP;
369
370 pmu_type = pmu_name_to_pmu_type(buffer);
371 if (pmu_type == -1)
372 return PFMLIB_ERR_NOTSUPP;
373
374 switch (pmu_type) {
375 default:
376 return PFMLIB_ERR_NOTSUPP;
377
379 pme_count = PME_ULTRA12_EVENT_COUNT;
380 break;
381
383 pme_count = PME_ULTRA3_EVENT_COUNT;
384 break;
385
387 pme_count = PME_ULTRA3I_EVENT_COUNT;
388 break;
389
391 pme_count = PME_ULTRA3PLUS_EVENT_COUNT;
392 break;
393
395 pme_count = PME_ULTRA4PLUS_EVENT_COUNT;
396 break;
397
399 pme_count = PME_NIAGARA1_EVENT_COUNT;
400 break;
401
403 pme_count = PME_NIAGARA2_EVENT_COUNT;
404 break;
405 }
406
407 sparc_support.pmu_type = pmu_type;
408 sparc_support.pmu_name = strdup(buffer);
409 sparc_support.pme_count = pme_count;
410
411 return PFMLIB_SUCCESS;
412}
413
415{
416 impl_pmcs->bits[0] = 0x1;
417}
418
420{
421 impl_pmds->bits[0] = 0x3;
422}
423
425{
426 pfm_sparc_get_impl_pmds(impl_counters);
427}
428
429static void pfm_sparc_get_hw_counter_width(unsigned int *width)
430{
431 *width = 32;
432}
433
434static int pfm_sparc_get_event_desc(unsigned int event, char **desc)
435{
436 *desc = strdup(get_event_desc(event));
437 return 0;
438}
439
440static int pfm_sparc_get_event_mask_desc(unsigned int event,
441 unsigned int mask, char **desc)
442{
444 *desc = strdup("");
445 } else {
447
448 e = &niagara2_pe[event];
449 *desc = strdup(e->pme_masks[mask].mask_desc);
450 }
451 return 0;
452}
453
454static int pfm_sparc_get_event_mask_code(unsigned int event,
455 unsigned int mask, unsigned int *code)
456{
458 *code = 0;
459 else
460 *code = mask;
461 return 0;
462}
463
464static int
466{
467 switch (sparc_support.pmu_type) {
473 e->event = 0;
474 break;
475
478 default:
479 return PFMLIB_ERR_NOTSUPP;
480 }
481
482 return PFMLIB_SUCCESS;
483}
484
485static int
487{
488 unsigned int i;
489
490 switch (sparc_support.pmu_type) {
496 e->event = 1;
497 break;
498
500 e->event = 0;
501 break;
502
504 e->event = 1;
506 for (i = 0; i < e->num_masks; i++)
507 e->unit_masks[i] = i;
508 break;
509
510 default:
511 return PFMLIB_ERR_NOTSUPP;
512 }
513 return PFMLIB_SUCCESS;
514}
515
520 /* the next 3 fields are initialized in pfm_sparc_pmu_detect */
521 .pmu_name = NULL,
522 .pmu_type = PFMLIB_UNKNOWN_PMU,
523 .pme_count = 0,
524
525 .pmd_count = 2,
526 .pmc_count = 1,
527 .num_cnt = 2,
528
529 .get_event_code = pfm_sparc_get_event_code,
530 .get_event_name = pfm_sparc_get_event_name,
531 .get_event_mask_name = pfm_sparc_get_event_mask_name,
532 .get_event_counters = pfm_sparc_get_event_counters,
533 .get_num_event_masks = pfm_sparc_get_num_event_masks,
534 .dispatch_events = pfm_sparc_dispatch_events,
535 .pmu_detect = pfm_sparc_pmu_detect,
536 .get_impl_pmcs = pfm_sparc_get_impl_pmcs,
537 .get_impl_pmds = pfm_sparc_get_impl_pmds,
538 .get_impl_counters = pfm_sparc_get_impl_counters,
539 .get_hw_counter_width = pfm_sparc_get_hw_counter_width,
540 .get_event_desc = pfm_sparc_get_event_desc,
541 .get_event_mask_desc = pfm_sparc_get_event_mask_desc,
542 .get_event_mask_code = pfm_sparc_get_event_mask_code,
543 .get_cycle_event = pfm_sparc_get_cycle_event,
544 .get_inst_retired_event = pfm_sparc_get_inst_retired
545};
int i
static pme_sparc_entry_t niagara1_pe[]
#define PME_NIAGARA1_EVENT_COUNT
#define PME_NIAGARA2_EVENT_COUNT
static pme_sparc_mask_entry_t niagara2_pe[]
#define PFMLIB_SPARC_ULTRA3I_PMU
Definition: pfmlib.h:274
#define PFMLIB_SPARC_NIAGARA1_PMU
Definition: pfmlib.h:277
#define PFMLIB_SPARC_ULTRA12_PMU
Definition: pfmlib.h:272
#define PFMLIB_SUCCESS
Definition: pfmlib.h:283
#define PFMLIB_SPARC_ULTRA3PLUS_PMU
Definition: pfmlib.h:275
#define PFM_PLM3
Definition: pfmlib.h:53
#define PFMLIB_SPARC_ULTRA3_PMU
Definition: pfmlib.h:273
#define PFMLIB_SPARC_NIAGARA2_PMU
Definition: pfmlib.h:278
#define PFMLIB_ERR_INVAL
Definition: pfmlib.h:285
#define PFMLIB_ERR_TOOMANY
Definition: pfmlib.h:295
#define PFM_PLM0
Definition: pfmlib.h:50
#define PFMLIB_ERR_NOASSIGN
Definition: pfmlib.h:288
#define PFM_PLM1
Definition: pfmlib.h:51
#define PFMLIB_SPARC_ULTRA4PLUS_PMU
Definition: pfmlib.h:276
#define PFMLIB_ERR_NOTSUPP
Definition: pfmlib.h:284
#define PFMLIB_UNKNOWN_PMU
Definition: pfmlib.h:222
int __pfm_getcpuinfo_attr(const char *attr, char *ret_buf, size_t maxlen)
#define EVENT_MASK_BITS
#define PCR_N2_SL0_SHIFT
Definition: pfmlib_sparc.c:204
pfm_pmu_support_t sparc_support
Definition: pfmlib_sparc.c:519
static int pfm_sparc_get_event_mask_desc(unsigned int event, unsigned int mask, char **desc)
Definition: pfmlib_sparc.c:440
static int pfm_sparc_pmu_detect(void)
Definition: pfmlib_sparc.c:361
#define PCR_S1_SHIFT
Definition: pfmlib_sparc.c:197
static int pfm_sparc_get_event_desc(unsigned int event, char **desc)
Definition: pfmlib_sparc.c:434
#define PCR_N2_MASK1_SHIFT
Definition: pfmlib_sparc.c:210
static int pfm_sparc_dispatch_events(pfmlib_input_param_t *input, void *model_input, pfmlib_output_param_t *output, void *model_output)
Definition: pfmlib_sparc.c:213
#define PCR_USER_TRACE
Definition: pfmlib_sparc.c:187
static int pfm_sparc_get_inst_retired(pfmlib_event_t *e)
Definition: pfmlib_sparc.c:486
static char * get_event_name(int event)
Definition: pfmlib_sparc.c:52
static int pfm_sparc_get_cycle_event(pfmlib_event_t *e)
Definition: pfmlib_sparc.c:465
static unsigned int pfm_sparc_get_num_event_masks(unsigned int event)
Definition: pfmlib_sparc.c:177
static void pfm_sparc_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
Definition: pfmlib_sparc.c:414
static char * pfm_sparc_get_event_mask_name(unsigned int event, unsigned int mask)
Definition: pfmlib_sparc.c:149
static void pfm_sparc_get_hw_counter_width(unsigned int *width)
Definition: pfmlib_sparc.c:429
#define PCR_SYS_TRACE
Definition: pfmlib_sparc.c:186
static int get_val(int event)
Definition: pfmlib_sparc.c:115
#define PCR_N2_MASK0_SHIFT
Definition: pfmlib_sparc.c:206
static int pmu_name_to_pmu_type(char *name)
Definition: pfmlib_sparc.c:342
static char * pfm_sparc_get_event_name(unsigned int event)
Definition: pfmlib_sparc.c:144
static int pfm_sparc_get_event_mask_code(unsigned int event, unsigned int mask, unsigned int *code)
Definition: pfmlib_sparc.c:454
#define PCR_N2_SL1_SHIFT
Definition: pfmlib_sparc.c:208
static char * get_event_desc(int event)
Definition: pfmlib_sparc.c:73
#define PCR_S0_SHIFT
Definition: pfmlib_sparc.c:195
static void pfm_sparc_get_event_counters(unsigned int event, pfmlib_regmask_t *counters)
Definition: pfmlib_sparc.c:161
#define PCR_N2_HYP_TRACE
Definition: pfmlib_sparc.c:201
static void pfm_sparc_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
Definition: pfmlib_sparc.c:419
static void pfm_sparc_get_impl_counters(pfmlib_regmask_t *impl_counters)
Definition: pfmlib_sparc.c:424
static int pfm_sparc_get_event_code(unsigned int event, unsigned int pmd, int *code)
Definition: pfmlib_sparc.c:136
static char get_ctrl(int event)
Definition: pfmlib_sparc.c:94
#define PCR_N2_TOE1
Definition: pfmlib_sparc.c:203
#define PCR_N2_TOE0
Definition: pfmlib_sparc.c:202
#define PME_CTRL_S0
#define PME_CTRL_S1
const char * name
Definition: rocs.c:225
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 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_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 int reg_reserved1
Definition: pfmlib.h:101
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
pfmlib_regmask_bits_t bits[PFMLIB_REG_BV]
Definition: pfmlib.h:76
int pme_val
char * pme_desc
char pme_ctrl
char * pme_name
char pme_ctrl
char * pme_name
int pme_val
pme_sparc_mask_t pme_masks[EVENT_MASK_BITS]
char * pme_desc
static pme_sparc_entry_t ultra12_pe[]
Definition: ultra12_events.h:1
#define PME_ULTRA12_EVENT_COUNT
#define PME_ULTRA3_EVENT_COUNT
static pme_sparc_entry_t ultra3_pe[]
Definition: ultra3_events.h:1
static pme_sparc_entry_t ultra3i_pe[]
Definition: ultra3i_events.h:1
#define PME_ULTRA3I_EVENT_COUNT
#define PME_ULTRA3PLUS_EVENT_COUNT
static pme_sparc_entry_t ultra3plus_pe[]
#define PME_ULTRA4PLUS_EVENT_COUNT
static pme_sparc_entry_t ultra4plus_pe[]