static void show_event_info(char *name, unsigned int idx) { pfmlib_regmask_t cnt, impl_cnt; char *desc; unsigned int n1, n2, i, c; int code, prev_code = 0, first = 1; int ret; pfm_get_event_counters(idx, &cnt); pfm_get_num_counters(&n2); pfm_get_impl_counters(&impl_cnt); n1 = n2; printf("#-----------------------------\n" "Name : %s\n", name); pfm_get_event_description(idx, &desc); printf("Desc : %s\n", desc); free(desc); printf("Code :"); for (i=0; n1; i++) { if (pfm_regmask_isset(&impl_cnt, i)) n1--; if (pfm_regmask_isset(&cnt, i)) { pfm_get_event_code_counter(idx,i,&code); if (first == 1 || code != prev_code) { printf(" 0x%x", code); first = 0; } prev_code = code; } } putchar('\n'); n1 = n2; printf("Counters : [ "); for (i=0; n1; i++) { if (pfm_regmask_isset(&impl_cnt, i)) n1--; if (pfm_regmask_isset(&cnt, i)) printf("%d ", i); } puts("]"); pfm_get_num_event_masks(idx, &n1); for (i = 0; i < n1; i++) { ret = pfm_get_event_mask_name(idx, i, name, max_len+1); if (ret != PFMLIB_SUCCESS) continue; pfm_get_event_mask_description(idx, i, &desc); pfm_get_event_mask_code(idx, i, &c); printf("Umask-%02u : 0x%02x : [%s] : %s\n", i, c, name, desc); free(desc); } }
static int setup_preset_term(int *native, pfmlib_event_t *event) { /* It seems this could be greatly simplified. If impl_cnt is non-zero, the event lives on a counter. Therefore the entire routine could be: if (impl_cnt!= 0) encode_native_event. Am I wrong? */ pfmlib_regmask_t impl_cnt, evnt_cnt; unsigned int n; int j, ret; /* find out which counters it lives on */ if ((ret = pfm_get_event_counters(event->event,&evnt_cnt)) != PFMLIB_SUCCESS) { PAPIERROR("pfm_get_event_counters(%d,%p): %s",event->event,&evnt_cnt,pfm_strerror(ret)); return(PAPI_EBUG); } if ((ret = pfm_get_impl_counters(&impl_cnt)) != PFMLIB_SUCCESS) { PAPIERROR("pfm_get_impl_counters(%p): %s", &impl_cnt, pfm_strerror(ret)); return(PAPI_EBUG); } /* Make sure this event lives on some counter, if so, put in the description. If not, BUG */ if ((ret = pfm_get_num_counters(&n)) != PFMLIB_SUCCESS) { PAPIERROR("pfm_get_num_counters(%d): %s", n, pfm_strerror(ret)); return(PAPI_EBUG); } for (j=0;n;j++) { if (pfm_regmask_isset(&impl_cnt, j)) { n--; if (pfm_regmask_isset(&evnt_cnt,j)) { *native = encode_native_event(event->event,event->num_masks,event->unit_masks); return(PAPI_OK); } } } PAPIERROR("PAPI preset 0x%08x PFM event %d did not have any available counters", event->event, j); return(PAPI_ENOEVNT); }
static void pfm_gen_ia64_get_event_counters(unsigned int j, pfmlib_regmask_t *counters) { unsigned int i; memset(counters, 0, sizeof(*counters)); for(i=0; i < pfm_gen_ia64_counters; i++) { if (pfm_regmask_isset(&generic_pe[j].pme_counters, i)) pfm_regmask_set(counters, i); } }
static int valid_assign(unsigned int *as, pfmlib_regmask_t *r_pmcs, unsigned int cnt) { unsigned int i; for(i=0; i < cnt; i++) { if (as[i]==0) return 0; /* * take care of restricted PMC registers */ if (pfm_regmask_isset(r_pmcs, as[i])) return 0; } return 1; }
int main(int argc, char **argv) { unsigned int i, cnum = 0; pfarg_reg_t pc[NUM_PMCS]; pfmlib_regmask_t impl_pmcs; unsigned int num_pmcs; /* * Initialize pfm library (required before we can use it) */ if (pfm_initialize() != PFMLIB_SUCCESS) { printf("Can't initialize library\n"); exit(1); } memset(&impl_pmcs, 0, sizeof(impl_pmcs)); memset(pc, 0, sizeof(pc)); pfm_get_impl_pmcs(&impl_pmcs); pfm_get_num_pmcs(&num_pmcs); for(i=0; num_pmcs ; i++) { if (pfm_regmask_isset(&impl_pmcs, i) == 0) continue; pc[cnum++].reg_num = i; num_pmcs--; } if (perfmonctl(0, PFM_GET_PMC_RESET_VAL, pc, cnum) == -1 ) { if (errno == ENOSYS) { fatal_error("Your kernel does not have performance monitoring support!\n"); } fatal_error("cannot get reset values: %s\n", strerror(errno)); } for (i=0; i < cnum; i++) { printf("PMC%u 0x%lx\n", pc[i].reg_num, pc[i].reg_value); } return 0; }
/** * pentium4_dispatch_events * * Examine each desired event specified in "input" and find an appropriate * ESCR/CCCR pair that can be used to count them. **/ static int pentium4_dispatch_events(pfmlib_input_param_t *input, void *model_input, pfmlib_output_param_t *output, void *model_output) { unsigned int assigned_pmcs[PENTIUM4_NUM_PMCS] = {0}; unsigned int event, event_mask, mask; unsigned int bit, tag_value, tag_enable; unsigned int plm; unsigned int i, j, k, m, n; int escr, escr_pmc; int cccr, cccr_pmc, cccr_pmd; int assigned; pentium4_escr_value_t escr_value; pentium4_cccr_value_t cccr_value; if (input->pfp_event_count > PENTIUM4_NUM_PMDS) { /* Can't specify more events than we have counters. */ return PFMLIB_ERR_TOOMANY; } if (input->pfp_dfl_plm & (PFM_PLM1|PFM_PLM2)) { /* Can't specify privilege levels 1 or 2. */ return PFMLIB_ERR_INVAL; } /* Examine each event specified in input->pfp_events. i counts * through the input->pfp_events array, and j counts through the * PMCs in output->pfp_pmcs as they are set up. */ for (i = 0, j = 0; i < input->pfp_event_count; i++) { if (input->pfp_events[i].plm & (PFM_PLM1|PFM_PLM2)) { /* Can't specify privilege levels 1 or 2. */ return PFMLIB_ERR_INVAL; } /* * INSTR_COMPLETED event only exist for model 3, 4, 6 (Prescott) */ if (input->pfp_events[i].event == PME_INSTR_COMPLETED && p4_model != 3 && p4_model != 4 && p4_model != 6) return PFMLIB_ERR_EVTINCOMP; event = input->pfp_events[i].event; assigned = 0; /* Use the event-specific privilege mask if set. * Otherwise use the default privilege mask. */ plm = input->pfp_events[i].plm ? input->pfp_events[i].plm : input->pfp_dfl_plm; /* Examine each ESCR that this event could be assigned to. */ for (k = 0; k < MAX_ESCRS_PER_EVENT && !assigned; k++) { escr = pentium4_events[event].allowed_escrs[k]; if (escr < 0) continue; /* Make sure this ESCR isn't already assigned * and isn't on the "unavailable" list. */ escr_pmc = pentium4_escrs[escr].pmc; if (assigned_pmcs[escr_pmc] || pfm_regmask_isset(&input->pfp_unavail_pmcs, escr_pmc)) { continue; } /* Examine each CCCR that can be used with this ESCR. */ for (m = 0; m < MAX_CCCRS_PER_ESCR && !assigned; m++) { cccr = pentium4_escrs[escr].allowed_cccrs[m]; if (cccr < 0) { continue; } /* Make sure this CCCR isn't already assigned * and isn't on the "unavailable" list. */ cccr_pmc = pentium4_cccrs[cccr].pmc; cccr_pmd = pentium4_cccrs[cccr].pmd; if (assigned_pmcs[cccr_pmc] || pfm_regmask_isset(&input->pfp_unavail_pmcs, cccr_pmc)) { continue; } /* Found an available ESCR/CCCR pair. */ assigned = 1; assigned_pmcs[escr_pmc] = 1; assigned_pmcs[cccr_pmc] = 1; /* Calculate the event-mask value. Invalid masks * specified by the caller are ignored. */ event_mask = 0; tag_value = 0; tag_enable = 0; for (n = 0; n < input->pfp_events[i].num_masks; n++) { mask = input->pfp_events[i].unit_masks[n]; bit = pentium4_events[event].event_masks[mask].bit; if (bit < EVENT_MASK_BITS && pentium4_events[event].event_masks[mask].name) { event_mask |= (1 << bit); } if (bit >= EVENT_MASK_BITS && pentium4_events[event].event_masks[mask].name) { tag_value |= (1 << (bit - EVENT_MASK_BITS)); tag_enable = 1; } } /* Set up the ESCR and CCCR register values. */ escr_value.val = 0; escr_value.bits.t1_usr = 0; /* controlled by kernel */ escr_value.bits.t1_os = 0; /* controlled by kernel */ escr_value.bits.t0_usr = (plm & PFM_PLM3) ? 1 : 0; escr_value.bits.t0_os = (plm & PFM_PLM0) ? 1 : 0; escr_value.bits.tag_enable = tag_enable; escr_value.bits.tag_value = tag_value; escr_value.bits.event_mask = event_mask; escr_value.bits.event_select = pentium4_events[event].event_select; escr_value.bits.reserved = 0; cccr_value.val = 0; cccr_value.bits.reserved1 = 0; cccr_value.bits.enable = 1; cccr_value.bits.escr_select = pentium4_events[event].escr_select; cccr_value.bits.active_thread = 3; /* FIXME: This is set to count when either logical * CPU is active. Need a way to distinguish * between logical CPUs when HT is enabled. */ cccr_value.bits.compare = 0; /* FIXME: What do we do with "threshold" settings? */ cccr_value.bits.complement = 0; /* FIXME: What do we do with "threshold" settings? */ cccr_value.bits.threshold = 0; /* FIXME: What do we do with "threshold" settings? */ cccr_value.bits.force_ovf = 0; /* FIXME: Do we want to allow "forcing" overflow * interrupts on all counter increments? */ cccr_value.bits.ovf_pmi_t0 = 1; cccr_value.bits.ovf_pmi_t1 = 0; /* PMI taken care of by kernel typically */ cccr_value.bits.reserved2 = 0; cccr_value.bits.cascade = 0; /* FIXME: How do we handle "cascading" counters? */ cccr_value.bits.overflow = 0; /* Special processing for the replay event: Remove virtual mask bits from actual mask; scan mask bit list and OR bit values for each virtual mask into the PEBS ENABLE and PEBS MATRIX VERT registers */ if (event == PME_REPLAY_EVENT) { escr_value.bits.event_mask &= P4_REPLAY_REAL_MASK; /* remove virtual mask bits */ if (event_mask & P4_REPLAY_VIRT_MASK) { /* find a valid virtual mask */ output->pfp_pmcs[j].reg_value = 0; output->pfp_pmcs[j].reg_num = PMC_PEBS_ENABLE; output->pfp_pmcs[j].reg_addr = p4_pmc_regmap[PMC_PEBS_ENABLE].addr; output->pfp_pmcs[j+1].reg_value = 0; output->pfp_pmcs[j+1].reg_num = PMC_PEBS_MATRIX_VERT; output->pfp_pmcs[j+1].reg_addr = p4_pmc_regmap[PMC_PEBS_MATRIX_VERT].addr; for (n = 0; n < input->pfp_events[i].num_masks; n++) { mask = input->pfp_events[i].unit_masks[n]; if (mask > 1 && mask < 11) { /* process each valid mask we find */ output->pfp_pmcs[j].reg_value |= p4_replay_regs[mask].enb; output->pfp_pmcs[j+1].reg_value |= p4_replay_regs[mask].mat_vert; } } j += 2; output->pfp_pmc_count += 2; } } /* Set up the PMCs in the * output->pfp_pmcs array. */ output->pfp_pmcs[j].reg_num = escr_pmc; output->pfp_pmcs[j].reg_value = escr_value.val; output->pfp_pmcs[j].reg_addr = p4_pmc_regmap[escr_pmc].addr; j++; __pfm_vbprintf("[%s(pmc%u)=0x%lx os=%u usr=%u tag=%u tagval=0x%x mask=%u sel=0x%x] %s\n", p4_pmc_regmap[escr_pmc].name, escr_pmc, escr_value.val, escr_value.bits.t0_os, escr_value.bits.t0_usr, escr_value.bits.tag_enable, escr_value.bits.tag_value, escr_value.bits.event_mask, escr_value.bits.event_select, pentium4_events[event].name); output->pfp_pmcs[j].reg_num = cccr_pmc; output->pfp_pmcs[j].reg_value = cccr_value.val; output->pfp_pmcs[j].reg_addr = p4_pmc_regmap[cccr_pmc].addr; output->pfp_pmds[i].reg_num = cccr_pmd; output->pfp_pmds[i].reg_addr = p4_pmd_regmap[cccr_pmd].addr; __pfm_vbprintf("[%s(pmc%u)=0x%lx ena=1 sel=0x%x cmp=%u cmpl=%u thres=%u edg=%u cas=%u] %s\n", p4_pmc_regmap[cccr_pmc].name, cccr_pmc, cccr_value.val, cccr_value.bits.escr_select, cccr_value.bits.compare, cccr_value.bits.complement, cccr_value.bits.threshold, cccr_value.bits.edge, cccr_value.bits.cascade, pentium4_events[event].name); __pfm_vbprintf("[%s(pmd%u)]\n", p4_pmd_regmap[output->pfp_pmds[i].reg_num].name, output->pfp_pmds[i].reg_num); j++; output->pfp_pmc_count += 2; } } if (k == MAX_ESCRS_PER_EVENT && !assigned) { /* Couldn't find an available ESCR and/or CCCR. */ return PFMLIB_ERR_NOASSIGN; } } output->pfp_pmd_count = input->pfp_event_count; return PFMLIB_SUCCESS; }