|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pfmlib_gen_ia64.c : support default architected IA-64 PMU features
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (c) 2001-2006 Hewlett-Packard Development Company, L.P.
|
|
Packit |
577717 |
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit |
577717 |
* of this software and associated documentation files (the "Software"), to deal
|
|
Packit |
577717 |
* in the Software without restriction, including without limitation the rights
|
|
Packit |
577717 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
Packit |
577717 |
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
Packit |
577717 |
* subject to the following conditions:
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* The above copyright notice and this permission notice shall be included in all
|
|
Packit |
577717 |
* copies or substantial portions of the Software.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
Packit |
577717 |
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
Packit |
577717 |
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
Packit |
577717 |
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
Packit |
577717 |
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
Packit |
577717 |
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#include <sys/types.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include <perfmon/pfmlib.h>
|
|
Packit |
577717 |
#include <perfmon/pfmlib_gen_ia64.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include "pfmlib_priv.h" /* library private */
|
|
Packit |
577717 |
#include "pfmlib_priv_ia64.h" /* architecture private */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define PMU_GEN_IA64_MAX_COUNTERS 4
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* number of architected events
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#define PME_GEN_COUNT 2
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Description of the PMC register mappings use by
|
|
Packit |
577717 |
* this module (as reported in pfmlib_reg_t.reg_num):
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* 0 -> PMC0
|
|
Packit |
577717 |
* 1 -> PMC1
|
|
Packit |
577717 |
* n -> PMCn
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#define PFMLIB_GEN_IA64_PMC_BASE 0
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* generic event as described by architecture
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
typedef struct {
|
|
Packit |
577717 |
unsigned long pme_code:8; /* major event code */
|
|
Packit |
577717 |
unsigned long pme_ig:56; /* ignored */
|
|
Packit |
577717 |
} pme_gen_ia64_code_t;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* union of all possible entry codes. All encodings must fit in 64bit
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
typedef union {
|
|
Packit |
577717 |
unsigned long pme_vcode;
|
|
Packit |
577717 |
pme_gen_ia64_code_t pme_gen_code;
|
|
Packit |
577717 |
} pme_gen_ia64_entry_code_t;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* entry in the event table (one table per implementation)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
typedef struct pme_entry {
|
|
Packit |
577717 |
char *pme_name;
|
|
Packit |
577717 |
pme_gen_ia64_entry_code_t pme_entry_code; /* event code */
|
|
Packit |
577717 |
pfmlib_regmask_t pme_counters; /* counter bitmask */
|
|
Packit |
577717 |
} pme_gen_ia64_entry_t;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* let's define some handy shortcuts ! */
|
|
Packit |
577717 |
#define pmc_plm pmc_gen_count_reg.pmc_plm
|
|
Packit |
577717 |
#define pmc_ev pmc_gen_count_reg.pmc_ev
|
|
Packit |
577717 |
#define pmc_oi pmc_gen_count_reg.pmc_oi
|
|
Packit |
577717 |
#define pmc_pm pmc_gen_count_reg.pmc_pm
|
|
Packit |
577717 |
#define pmc_es pmc_gen_count_reg.pmc_es
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* this table is patched by initialization code
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static pme_gen_ia64_entry_t generic_pe[PME_GEN_COUNT]={
|
|
Packit |
577717 |
#define PME_IA64_GEN_CPU_CYCLES 0
|
|
Packit |
577717 |
{ "CPU_CYCLES", },
|
|
Packit |
577717 |
#define PME_IA64_GEN_INST_RETIRED 1
|
|
Packit |
577717 |
{ "IA64_INST_RETIRED", },
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int pfm_gen_ia64_counter_width;
|
|
Packit |
577717 |
static int pfm_gen_ia64_counters;
|
|
Packit |
577717 |
static pfmlib_regmask_t pfm_gen_ia64_impl_pmcs;
|
|
Packit |
577717 |
static pfmlib_regmask_t pfm_gen_ia64_impl_pmds;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Description of the PMC register mappings use by
|
|
Packit |
577717 |
* this module (as reported in pfmlib_reg_t.reg_num):
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* 0 -> PMC0
|
|
Packit |
577717 |
* 1 -> PMC1
|
|
Packit |
577717 |
* n -> PMCn
|
|
Packit |
577717 |
* We do not use a mapping table, instead we make up the
|
|
Packit |
577717 |
* values on the fly given the base.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#define PFMLIB_GEN_IA64_PMC_BASE 0
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* convert text range (e.g. 4-15 18 12-26) into actual bitmask
|
|
Packit |
577717 |
* range argument is modified
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
parse_counter_range(char *range, pfmlib_regmask_t *b)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *p, c;
|
|
Packit |
577717 |
int start, end;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (range[strlen(range)-1] == '\n')
|
|
Packit |
577717 |
range[strlen(range)-1] = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while(range) {
|
|
Packit |
577717 |
p = range;
|
|
Packit |
577717 |
while (*p && *p != ' ' && *p != '-') p++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (*p == '\0') break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
c = *p;
|
|
Packit |
577717 |
*p = '\0';
|
|
Packit |
577717 |
start = atoi(range);
|
|
Packit |
577717 |
range = p+1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (c == '-') {
|
|
Packit |
577717 |
p++;
|
|
Packit |
577717 |
while (*p && *p != ' ' && *p != '-') p++;
|
|
Packit |
577717 |
if (*p) *p++ = '\0';
|
|
Packit |
577717 |
end = atoi(range);
|
|
Packit |
577717 |
range = p;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
end = start;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (end >= PFMLIB_REG_MAX|| start >= PFMLIB_REG_MAX)
|
|
Packit |
577717 |
goto invalid;
|
|
Packit |
577717 |
for (; start <= end; start++)
|
|
Packit |
577717 |
pfm_regmask_set(b, start);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
invalid:
|
|
Packit |
577717 |
fprintf(stderr, "%s.%s : bitmask too small need %d bits\n", __FILE__, __FUNCTION__, start);
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_gen_ia64_initialize(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
FILE *fp;
|
|
Packit |
577717 |
char *p;
|
|
Packit |
577717 |
char buffer[64];
|
|
Packit |
577717 |
int matches = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
fp = fopen("/proc/pal/cpu0/perfmon_info", "r");
|
|
Packit |
577717 |
if (fp == NULL) return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (;;) {
|
|
Packit |
577717 |
p = fgets(buffer, sizeof(buffer)-1, fp);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (p == NULL) break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((p = strchr(buffer, ':')) == NULL) break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*p = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!strncmp("Counter width", buffer, 13)) {
|
|
Packit |
577717 |
pfm_gen_ia64_counter_width = atoi(p+2);
|
|
Packit |
577717 |
matches++;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!strncmp("PMC/PMD pairs", buffer, 13)) {
|
|
Packit |
577717 |
pfm_gen_ia64_counters = atoi(p+2);
|
|
Packit |
577717 |
matches++;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!strncmp("Cycle event number", buffer, 18)) {
|
|
Packit |
577717 |
generic_pe[0].pme_entry_code.pme_vcode = atoi(p+2);
|
|
Packit |
577717 |
matches++;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!strncmp("Retired event number", buffer, 20)) {
|
|
Packit |
577717 |
generic_pe[1].pme_entry_code.pme_vcode = atoi(p+2);
|
|
Packit |
577717 |
matches++;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!strncmp("Cycles count capable", buffer, 20)) {
|
|
Packit |
577717 |
if (parse_counter_range(p+2, &generic_pe[0].pme_counters) == -1) return -1;
|
|
Packit |
577717 |
matches++;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!strncmp("Retired bundles count capable", buffer, 29)) {
|
|
Packit |
577717 |
if (parse_counter_range(p+2, &generic_pe[1].pme_counters) == -1) return -1;
|
|
Packit |
577717 |
matches++;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!strncmp("Implemented PMC", buffer, 15)) {
|
|
Packit |
577717 |
if (parse_counter_range(p+2, &pfm_gen_ia64_impl_pmcs) == -1) return -1;
|
|
Packit |
577717 |
matches++;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!strncmp("Implemented PMD", buffer, 15)) {
|
|
Packit |
577717 |
if (parse_counter_range(p+2, &pfm_gen_ia64_impl_pmds) == -1) return -1;
|
|
Packit |
577717 |
matches++;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pfm_regmask_weight(&pfm_gen_ia64_impl_pmcs, &generic_ia64_support.pmc_count);
|
|
Packit |
577717 |
pfm_regmask_weight(&pfm_gen_ia64_impl_pmds, &generic_ia64_support.pmd_count);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
fclose(fp);
|
|
Packit |
577717 |
return matches == 8 ? PFMLIB_SUCCESS : PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_gen_ia64_forced_initialize(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_gen_ia64_counter_width = 47;
|
|
Packit |
577717 |
pfm_gen_ia64_counters = 4;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
generic_pe[0].pme_entry_code.pme_vcode = 18;
|
|
Packit |
577717 |
generic_pe[1].pme_entry_code.pme_vcode = 8;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&pfm_gen_ia64_impl_pmcs, 0, sizeof(pfmlib_regmask_t));
|
|
Packit |
577717 |
memset(&pfm_gen_ia64_impl_pmds, 0, sizeof(pfmlib_regmask_t));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < 8; i++)
|
|
Packit |
577717 |
pfm_regmask_set(&pfm_gen_ia64_impl_pmcs, i);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=4; i < 8; i++)
|
|
Packit |
577717 |
pfm_regmask_set(&pfm_gen_ia64_impl_pmds, i);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&generic_pe[0].pme_counters, 0, sizeof(pfmlib_regmask_t));
|
|
Packit |
577717 |
memset(&generic_pe[1].pme_counters, 0, sizeof(pfmlib_regmask_t));
|
|
Packit |
577717 |
for(i=4; i < 8; i++) {
|
|
Packit |
577717 |
pfm_regmask_set(&generic_pe[0].pme_counters, i);
|
|
Packit |
577717 |
pfm_regmask_set(&generic_pe[1].pme_counters, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
generic_ia64_support.pmc_count = 8;
|
|
Packit |
577717 |
generic_ia64_support.pmd_count = 4;
|
|
Packit |
577717 |
generic_ia64_support.num_cnt = 4;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_gen_ia64_detect(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
/* PMU is architected, so guaranteed to be present */
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_gen_ia64_init(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (forced_pmu != PFMLIB_NO_PMU) {
|
|
Packit |
577717 |
pfm_gen_ia64_forced_initialize();
|
|
Packit |
577717 |
} else if (pfm_gen_ia64_initialize() == -1)
|
|
Packit |
577717 |
return PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
valid_assign(unsigned int *as, pfmlib_regmask_t *r_pmcs, unsigned int cnt)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
for(i=0; i < cnt; i++) {
|
|
Packit |
577717 |
if (as[i]==0) return 0;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* take care of restricted PMC registers
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (pfm_regmask_isset(r_pmcs, as[i]))
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Automatically dispatch events to corresponding counters following constraints.
|
|
Packit |
577717 |
* Upon return the pfarg_reg_t structure is ready to be submitted to kernel
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_gen_ia64_dispatch_counters(pfmlib_input_param_t *inp, pfmlib_output_param_t *outp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
#define has_counter(e,b) (pfm_regmask_isset(&generic_pe[e].pme_counters, b) ? b : 0)
|
|
Packit |
577717 |
unsigned int max_l0, max_l1, max_l2, max_l3;
|
|
Packit |
577717 |
unsigned int assign[PMU_GEN_IA64_MAX_COUNTERS];
|
|
Packit |
577717 |
pfm_gen_ia64_pmc_reg_t reg;
|
|
Packit |
577717 |
pfmlib_event_t *e;
|
|
Packit |
577717 |
pfmlib_reg_t *pc, *pd;
|
|
Packit |
577717 |
pfmlib_regmask_t *r_pmcs;
|
|
Packit |
577717 |
unsigned int i,j,k,l;
|
|
Packit |
577717 |
unsigned int cnt;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e = inp->pfp_events;
|
|
Packit |
577717 |
pc = outp->pfp_pmcs;
|
|
Packit |
577717 |
pd = outp->pfp_pmds;
|
|
Packit |
577717 |
cnt = inp->pfp_event_count;
|
|
Packit |
577717 |
r_pmcs = &inp->pfp_unavail_pmcs;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (cnt > PMU_GEN_IA64_MAX_COUNTERS) return PFMLIB_ERR_TOOMANY;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
max_l0 = PMU_GEN_IA64_FIRST_COUNTER + PMU_GEN_IA64_MAX_COUNTERS;
|
|
Packit |
577717 |
max_l1 = PMU_GEN_IA64_FIRST_COUNTER + PMU_GEN_IA64_MAX_COUNTERS*(cnt>1);
|
|
Packit |
577717 |
max_l2 = PMU_GEN_IA64_FIRST_COUNTER + PMU_GEN_IA64_MAX_COUNTERS*(cnt>2);
|
|
Packit |
577717 |
max_l3 = PMU_GEN_IA64_FIRST_COUNTER + PMU_GEN_IA64_MAX_COUNTERS*(cnt>3);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_DEBUG()) {
|
|
Packit |
577717 |
DPRINT("max_l0=%u max_l1=%u max_l2=%u max_l3=%u\n", max_l0, max_l1, max_l2, max_l3);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* This code needs fixing. It is not very pretty and
|
|
Packit |
577717 |
* won't handle more than 4 counters if more become
|
|
Packit |
577717 |
* available !
|
|
Packit |
577717 |
* For now, worst case in the loop nest: 4! (factorial)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (i=PMU_GEN_IA64_FIRST_COUNTER; i < max_l0; i++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
assign[0]= has_counter(e[0].event,i);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (max_l1 == PMU_GEN_IA64_FIRST_COUNTER && valid_assign(assign, r_pmcs, cnt)) goto done;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (j=PMU_GEN_IA64_FIRST_COUNTER; j < max_l1; j++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (j == i) continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
assign[1] = has_counter(e[1].event,j);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (max_l2 == PMU_GEN_IA64_FIRST_COUNTER && valid_assign(assign, r_pmcs, cnt)) goto done;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (k=PMU_GEN_IA64_FIRST_COUNTER; k < max_l2; k++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if(k == i || k == j) continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
assign[2] = has_counter(e[2].event,k);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (max_l3 == PMU_GEN_IA64_FIRST_COUNTER && valid_assign(assign, r_pmcs, cnt)) goto done;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (l=PMU_GEN_IA64_FIRST_COUNTER; l < max_l3; l++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if(l == i || l == j || l == k) continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
assign[3] = has_counter(e[3].event,l);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (valid_assign(assign, r_pmcs, cnt)) goto done;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/* we cannot satisfy the constraints */
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
done:
|
|
Packit |
577717 |
memset(pc, 0, cnt*sizeof(pfmlib_reg_t));
|
|
Packit |
577717 |
memset(pd, 0, cnt*sizeof(pfmlib_reg_t));
|
|
Packit |
577717 |
for (j=0; j < cnt ; j++ ) {
|
|
Packit |
577717 |
reg.pmc_val = 0; /* clear all */
|
|
Packit |
577717 |
/* if not specified per event, then use default (could be zero: measure nothing) */
|
|
Packit |
577717 |
reg.pmc_plm = e[j].plm ? e[j].plm: inp->pfp_dfl_plm;
|
|
Packit |
577717 |
reg.pmc_oi = 1; /* overflow interrupt */
|
|
Packit |
577717 |
reg.pmc_pm = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE? 1 : 0;
|
|
Packit |
577717 |
reg.pmc_es = generic_pe[e[j].event].pme_entry_code.pme_gen_code.pme_code;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[j].reg_num = assign[j];
|
|
Packit |
577717 |
pc[j].reg_value = reg.pmc_val;
|
|
Packit |
577717 |
pc[j].reg_addr = PFMLIB_GEN_IA64_PMC_BASE+j;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pd[j].reg_num = assign[j];
|
|
Packit |
577717 |
pd[j].reg_addr = assign[j];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[PMC%u(pmc%u)=0x%lx,es=0x%02x,plm=%d pm=%d] %s\n",
|
|
Packit |
577717 |
assign[j],
|
|
Packit |
577717 |
assign[j],
|
|
Packit |
577717 |
reg.pmc_val,
|
|
Packit |
577717 |
reg.pmc_es,reg.pmc_plm,
|
|
Packit |
577717 |
reg.pmc_pm,
|
|
Packit |
577717 |
generic_pe[e[j].event].pme_name);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[PMD%u(pmd%u)]\n", pd[j].reg_num, pd[j].reg_num);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/* number of PMC programmed */
|
|
Packit |
577717 |
outp->pfp_pmc_count = cnt;
|
|
Packit |
577717 |
outp->pfp_pmd_count = cnt;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_gen_ia64_dispatch_events(pfmlib_input_param_t *inp, void *dummy1, pfmlib_output_param_t *outp, void *dummy2)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return pfm_gen_ia64_dispatch_counters(inp, outp);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_gen_ia64_get_event_code(unsigned int i, unsigned int cnt, int *code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (cnt != PFMLIB_CNT_FIRST && (cnt < 4 || cnt > 7))
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*code = (int)generic_pe[i].pme_entry_code.pme_gen_code.pme_code;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static char *
|
|
Packit |
577717 |
pfm_gen_ia64_get_event_name(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return generic_pe[i].pme_name;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_gen_ia64_get_event_counters(unsigned int j, pfmlib_regmask_t *counters)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(counters, 0, sizeof(*counters));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < pfm_gen_ia64_counters; i++) {
|
|
Packit |
577717 |
if (pfm_regmask_isset(&generic_pe[j].pme_counters, i))
|
|
Packit |
577717 |
pfm_regmask_set(counters, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_gen_ia64_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
*impl_pmcs = pfm_gen_ia64_impl_pmcs;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_gen_ia64_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
*impl_pmds = pfm_gen_ia64_impl_pmds;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_gen_ia64_get_impl_counters(pfmlib_regmask_t *impl_counters)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* pmd4-pmd7 */
|
|
Packit |
577717 |
for(i=4; i < 8; i++)
|
|
Packit |
577717 |
pfm_regmask_set(impl_counters, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_gen_ia64_get_hw_counter_width(unsigned int *width)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
*width = pfm_gen_ia64_counter_width;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_gen_ia64_get_event_desc(unsigned int ev, char **str)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
switch(ev) {
|
|
Packit |
577717 |
case PME_IA64_GEN_CPU_CYCLES:
|
|
Packit |
577717 |
*str = strdup("CPU cycles");
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PME_IA64_GEN_INST_RETIRED:
|
|
Packit |
577717 |
*str = strdup("IA-64 instructions retired");
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
*str = NULL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_gen_ia64_get_cycle_event(pfmlib_event_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
e->event = PME_IA64_GEN_CPU_CYCLES;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_gen_ia64_get_inst_retired(pfmlib_event_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
e->event = PME_IA64_GEN_INST_RETIRED;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_pmu_support_t generic_ia64_support={
|
|
Packit |
577717 |
.pmu_name ="IA-64",
|
|
Packit |
577717 |
.pmu_type = PFMLIB_GEN_IA64_PMU,
|
|
Packit |
577717 |
.pme_count = PME_GEN_COUNT,
|
|
Packit |
577717 |
.pmc_count = 4+4,
|
|
Packit |
577717 |
.pmd_count = PMU_GEN_IA64_MAX_COUNTERS,
|
|
Packit |
577717 |
.num_cnt = PMU_GEN_IA64_MAX_COUNTERS,
|
|
Packit |
577717 |
.get_event_code = pfm_gen_ia64_get_event_code,
|
|
Packit |
577717 |
.get_event_name = pfm_gen_ia64_get_event_name,
|
|
Packit |
577717 |
.get_event_counters = pfm_gen_ia64_get_event_counters,
|
|
Packit |
577717 |
.dispatch_events = pfm_gen_ia64_dispatch_events,
|
|
Packit |
577717 |
.pmu_detect = pfm_gen_ia64_detect,
|
|
Packit |
577717 |
.pmu_init = pfm_gen_ia64_init,
|
|
Packit |
577717 |
.get_impl_pmcs = pfm_gen_ia64_get_impl_pmcs,
|
|
Packit |
577717 |
.get_impl_pmds = pfm_gen_ia64_get_impl_pmds,
|
|
Packit |
577717 |
.get_impl_counters = pfm_gen_ia64_get_impl_counters,
|
|
Packit |
577717 |
.get_hw_counter_width = pfm_gen_ia64_get_hw_counter_width,
|
|
Packit |
577717 |
.get_event_desc = pfm_gen_ia64_get_event_desc,
|
|
Packit |
577717 |
.get_cycle_event = pfm_gen_ia64_get_cycle_event,
|
|
Packit |
577717 |
.get_inst_retired_event = pfm_gen_ia64_get_inst_retired
|
|
Packit |
577717 |
};
|