|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pfmlib_itanium2.c : support for the Itanium2 PMU family
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (c) 2002-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 <ctype.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* public headers */
|
|
Packit |
577717 |
#include <perfmon/pfmlib_itanium2.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* private headers */
|
|
Packit |
577717 |
#include "pfmlib_priv.h" /* library private */
|
|
Packit |
577717 |
#include "pfmlib_priv_ia64.h" /* architecture private */
|
|
Packit |
577717 |
#include "pfmlib_itanium2_priv.h" /* PMU private */
|
|
Packit |
577717 |
#include "itanium2_events.h" /* PMU private */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define is_ear(i) event_is_ear(itanium2_pe+(i))
|
|
Packit |
577717 |
#define is_ear_tlb(i) event_is_ear_tlb(itanium2_pe+(i))
|
|
Packit |
577717 |
#define is_ear_alat(i) event_is_ear_alat(itanium2_pe+(i))
|
|
Packit |
577717 |
#define is_ear_cache(i) event_is_ear_cache(itanium2_pe+(i))
|
|
Packit |
577717 |
#define is_iear(i) event_is_iear(itanium2_pe+(i))
|
|
Packit |
577717 |
#define is_dear(i) event_is_dear(itanium2_pe+(i))
|
|
Packit |
577717 |
#define is_btb(i) event_is_btb(itanium2_pe+(i))
|
|
Packit |
577717 |
#define has_opcm(i) event_opcm_ok(itanium2_pe+(i))
|
|
Packit |
577717 |
#define has_iarr(i) event_iarr_ok(itanium2_pe+(i))
|
|
Packit |
577717 |
#define has_darr(i) event_darr_ok(itanium2_pe+(i))
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define evt_use_opcm(e) ((e)->pfp_ita2_pmc8.opcm_used != 0 || (e)->pfp_ita2_pmc9.opcm_used !=0)
|
|
Packit |
577717 |
#define evt_use_irange(e) ((e)->pfp_ita2_irange.rr_used)
|
|
Packit |
577717 |
#define evt_use_drange(e) ((e)->pfp_ita2_drange.rr_used)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define evt_grp(e) (int)itanium2_pe[e].pme_qualifiers.pme_qual.pme_group
|
|
Packit |
577717 |
#define evt_set(e) (int)itanium2_pe[e].pme_qualifiers.pme_qual.pme_set
|
|
Packit |
577717 |
#define evt_umask(e) itanium2_pe[e].pme_umask
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define FINE_MODE_BOUNDARY_BITS 12
|
|
Packit |
577717 |
#define FINE_MODE_MASK ~((1U<<12)-1)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* let's define some handy shortcuts! */
|
|
Packit |
577717 |
#define pmc_plm pmc_ita2_counter_reg.pmc_plm
|
|
Packit |
577717 |
#define pmc_ev pmc_ita2_counter_reg.pmc_ev
|
|
Packit |
577717 |
#define pmc_oi pmc_ita2_counter_reg.pmc_oi
|
|
Packit |
577717 |
#define pmc_pm pmc_ita2_counter_reg.pmc_pm
|
|
Packit |
577717 |
#define pmc_es pmc_ita2_counter_reg.pmc_es
|
|
Packit |
577717 |
#define pmc_umask pmc_ita2_counter_reg.pmc_umask
|
|
Packit |
577717 |
#define pmc_thres pmc_ita2_counter_reg.pmc_thres
|
|
Packit |
577717 |
#define pmc_ism pmc_ita2_counter_reg.pmc_ism
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static char * pfm_ita2_get_event_name(unsigned int i);
|
|
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 |
* The following are in the model specific rr_br[]:
|
|
Packit |
577717 |
* IBR0 -> 0
|
|
Packit |
577717 |
* IBR1 -> 1
|
|
Packit |
577717 |
* ...
|
|
Packit |
577717 |
* IBR7 -> 7
|
|
Packit |
577717 |
* DBR0 -> 0
|
|
Packit |
577717 |
* DBR1 -> 1
|
|
Packit |
577717 |
* ...
|
|
Packit |
577717 |
* DBR7 -> 7
|
|
Packit |
577717 |
*
|
|
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 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* The Itanium2 PMU has a bug in the fine mode implementation.
|
|
Packit |
577717 |
* It only sees ranges with a granularity of two bundles.
|
|
Packit |
577717 |
* So we prepare for the day they fix it.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int has_fine_mode_bug;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_ita2_detect(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int tmp;
|
|
Packit |
577717 |
int ret = PFMLIB_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
tmp = pfm_ia64_get_cpu_family();
|
|
Packit |
577717 |
if (tmp == 0x1f) {
|
|
Packit |
577717 |
has_fine_mode_bug = 1;
|
|
Packit |
577717 |
ret = PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Check the event for incompatibilities. This is useful
|
|
Packit |
577717 |
* for L1 and L2 related events. Due to wire limitations,
|
|
Packit |
577717 |
* some caches events are separated into sets. There
|
|
Packit |
577717 |
* are 5 sets for the L1D cache group and 6 sets for L2 group.
|
|
Packit |
577717 |
* It is NOT possible to simultaneously measure events from
|
|
Packit |
577717 |
* differents sets within a group. For instance, you cannot
|
|
Packit |
577717 |
* measure events from set0 and set1 in L1D cache group. However
|
|
Packit |
577717 |
* it is possible to measure set0 in L1D and set1 in L2 at the same
|
|
Packit |
577717 |
* time.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* This function verifies that the set constraint are respected.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
check_cross_groups_and_umasks(pfmlib_input_param_t *inp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned long ref_umask, umask;
|
|
Packit |
577717 |
int g, s;
|
|
Packit |
577717 |
unsigned int cnt = inp->pfp_event_count;
|
|
Packit |
577717 |
pfmlib_event_t *e = inp->pfp_events;
|
|
Packit |
577717 |
unsigned int i, j;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* XXX: could possibly be optimized
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (i=0; i < cnt; i++) {
|
|
Packit |
577717 |
g = evt_grp(e[i].event);
|
|
Packit |
577717 |
s = evt_set(e[i].event);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (g == PFMLIB_ITA2_EVT_NO_GRP) continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ref_umask = evt_umask(e[i].event);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (j=i+1; j < cnt; j++) {
|
|
Packit |
577717 |
if (evt_grp(e[j].event) != g) continue;
|
|
Packit |
577717 |
if (evt_set(e[j].event) != s) return PFMLIB_ERR_EVTSET;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* only care about L2 cache group */
|
|
Packit |
577717 |
if (g != PFMLIB_ITA2_EVT_L2_CACHE_GRP || (s == 1 || s == 2)) continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
umask = evt_umask(e[j].event);
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* there is no assignement possible if the event in PMC4
|
|
Packit |
577717 |
* has a umask (ref_umask) and an event (from the same
|
|
Packit |
577717 |
* set) also has a umask AND it is different. For some
|
|
Packit |
577717 |
* sets, the umasks are shared, therefore the value
|
|
Packit |
577717 |
* programmed into PMC4 determines the umask for all
|
|
Packit |
577717 |
* the other events (with umask) from the set.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (umask && ref_umask != umask) return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Certain prefetch events must be treated specially when instruction range restriction
|
|
Packit |
577717 |
* is in use because they can only be constrained by IBRP1 in fine-mode. Other events
|
|
Packit |
577717 |
* will use IBRP0 if tagged as a demand fetch OR IBPR1 if tagged as a prefetch match.
|
|
Packit |
577717 |
* From the library's point of view there is no way of distinguishing this, so we leave
|
|
Packit |
577717 |
* it up to the user to interpret the results.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Events which can be qualified by the two pairs depending on their tag:
|
|
Packit |
577717 |
* - IBP_BUNPAIRS_IN
|
|
Packit |
577717 |
* - L1I_FETCH_RAB_HIT
|
|
Packit |
577717 |
* - L1I_FETCH_ISB_HIT
|
|
Packit |
577717 |
* - L1I_FILLS
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* This function returns the number of qualifying prefetch events found
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* XXX: not clear which events do qualify as prefetch events.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int prefetch_events[]={
|
|
Packit |
577717 |
PME_ITA2_L1I_PREFETCHES,
|
|
Packit |
577717 |
PME_ITA2_L1I_STRM_PREFETCHES,
|
|
Packit |
577717 |
PME_ITA2_L2_INST_PREFETCHES
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
#define NPREFETCH_EVENTS sizeof(prefetch_events)/sizeof(int)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
check_prefetch_events(pfmlib_input_param_t *inp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int code;
|
|
Packit |
577717 |
int prefetch_codes[NPREFETCH_EVENTS];
|
|
Packit |
577717 |
unsigned int i, j, count;
|
|
Packit |
577717 |
int c;
|
|
Packit |
577717 |
int found = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < NPREFETCH_EVENTS; i++) {
|
|
Packit |
577717 |
pfm_get_event_code(prefetch_events[i], &code);
|
|
Packit |
577717 |
prefetch_codes[i] = code;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
count = inp->pfp_event_count;
|
|
Packit |
577717 |
for(i=0; i < count; i++) {
|
|
Packit |
577717 |
pfm_get_event_code(inp->pfp_events[i].event, &c);
|
|
Packit |
577717 |
for(j=0; j < NPREFETCH_EVENTS; j++) {
|
|
Packit |
577717 |
if (c == prefetch_codes[j]) found++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return found;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* IA64_INST_RETIRED (and subevents) is the only event which can be measured on all
|
|
Packit |
577717 |
* 4 IBR when non-fine mode is not possible.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* This function returns:
|
|
Packit |
577717 |
* - the number of events matching the IA64_INST_RETIRED code
|
|
Packit |
577717 |
* - in retired_mask the bottom 4 bits indicates which of the 4 INST_RETIRED event
|
|
Packit |
577717 |
* is present
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static unsigned int
|
|
Packit |
577717 |
check_inst_retired_events(pfmlib_input_param_t *inp, unsigned long *retired_mask)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int code;
|
|
Packit |
577717 |
int c, ret;
|
|
Packit |
577717 |
unsigned int i, count, found = 0;
|
|
Packit |
577717 |
unsigned long umask, mask;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_get_event_code(PME_ITA2_IA64_INST_RETIRED_THIS, &code);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
count = inp->pfp_event_count;
|
|
Packit |
577717 |
mask = 0;
|
|
Packit |
577717 |
for(i=0; i < count; i++) {
|
|
Packit |
577717 |
ret = pfm_get_event_code(inp->pfp_events[i].event, &c);
|
|
Packit |
577717 |
if (c == code) {
|
|
Packit |
577717 |
ret = pfm_ita2_get_event_umask(inp->pfp_events[i].event, &umask);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS)
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
switch(umask) {
|
|
Packit |
577717 |
case 0: mask |= 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 1: mask |= 2;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 2: mask |= 4;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 3: mask |= 8;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
found++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (retired_mask) *retired_mask = mask;
|
|
Packit |
577717 |
return found;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
check_fine_mode_possible(pfmlib_ita2_input_rr_t *rr, int n)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_ita2_input_rr_desc_t *lim = rr->rr_limits;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < n; i++) {
|
|
Packit |
577717 |
if ((lim[i].rr_start & FINE_MODE_MASK) != (lim[i].rr_end & FINE_MODE_MASK))
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* mode = 0 -> check code (enforce bundle alignment)
|
|
Packit |
577717 |
* mode = 1 -> check data
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
check_intervals(pfmlib_ita2_input_rr_t *irr, int mode, unsigned int *n_intervals)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
pfmlib_ita2_input_rr_desc_t *lim = irr->rr_limits;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < 4; i++) {
|
|
Packit |
577717 |
/* end marker */
|
|
Packit |
577717 |
if (lim[i].rr_start == 0 && lim[i].rr_end == 0) break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* invalid entry */
|
|
Packit |
577717 |
if (lim[i].rr_start >= lim[i].rr_end) return PFMLIB_ERR_IRRINVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (mode == 0 && (lim[i].rr_start & 0xf || lim[i].rr_end & 0xf))
|
|
Packit |
577717 |
return PFMLIB_ERR_IRRALIGN;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
*n_intervals = i;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
valid_assign(pfmlib_event_t *e, unsigned int *as, pfmlib_regmask_t *r_pmcs, unsigned int cnt)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned long pmc4_umask = 0, umask;
|
|
Packit |
577717 |
char *name;
|
|
Packit |
577717 |
int l1_grp_present = 0, l2_grp_present = 0;
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
int c, failure;
|
|
Packit |
577717 |
int need_pmc5, need_pmc4;
|
|
Packit |
577717 |
int pmc5_evt = -1, pmc4_evt = -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_DEBUG()) {
|
|
Packit |
577717 |
unsigned int j;
|
|
Packit |
577717 |
for(j=0;j
|
|
Packit |
577717 |
name = pfm_ita2_get_event_name(e[j].event);
|
|
Packit |
577717 |
printf("%-2u (%d,%d): %s\n",
|
|
Packit |
577717 |
as[j],
|
|
Packit |
577717 |
evt_grp(e[j].event) == PFMLIB_ITA2_EVT_NO_GRP ? -1 : evt_grp(e[j].event),
|
|
Packit |
577717 |
evt_set(e[j].event) == 0xf ? -1 : evt_set(e[j].event),
|
|
Packit |
577717 |
name);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
failure = 1;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* first: check that all events have an assigned counter
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(i=0; i < cnt; i++) {
|
|
Packit |
577717 |
if (as[i]==0) goto do_failure;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* take care of restricted PMC registers
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (pfm_regmask_isset(r_pmcs, as[i]))
|
|
Packit |
577717 |
goto do_failure;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* second: scan list of events for the presence of groups
|
|
Packit |
577717 |
* at this point, we know that there can be no set crossing per group
|
|
Packit |
577717 |
* because this has been tested earlier.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(i=0; i < cnt; i++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
c = e[i].event;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (evt_grp(c) == PFMLIB_ITA2_EVT_L1_CACHE_GRP) l1_grp_present = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (evt_grp(c) == PFMLIB_ITA2_EVT_L2_CACHE_GRP) l2_grp_present = 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* third: scan assignements and make sure that there is at least one
|
|
Packit |
577717 |
* member of a special group assigned to either PMC4 or PMC5 depending
|
|
Packit |
577717 |
* on the constraint for that group
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (l1_grp_present || l2_grp_present) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
need_pmc5 = l1_grp_present;
|
|
Packit |
577717 |
need_pmc4 = l2_grp_present;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < cnt; i++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (need_pmc5 && as[i] == 5 && evt_grp(e[i].event) == PFMLIB_ITA2_EVT_L1_CACHE_GRP) {
|
|
Packit |
577717 |
need_pmc5 = 0;
|
|
Packit |
577717 |
pmc5_evt = e[i].event;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (need_pmc4 && as[i] == 4 && evt_grp(e[i].event) == PFMLIB_ITA2_EVT_L2_CACHE_GRP) {
|
|
Packit |
577717 |
need_pmc4 = 0;
|
|
Packit |
577717 |
pmc4_evt = e[i].event;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (need_pmc4 == 0 && need_pmc5 == 0) break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
failure = 2;
|
|
Packit |
577717 |
if (need_pmc4) goto do_failure;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
failure = 3;
|
|
Packit |
577717 |
if (need_pmc5) goto do_failure;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* fourth: for the L2 cache event group, you must make sure that there is no
|
|
Packit |
577717 |
* umask conflict, except for sets 1 and 2 which do not suffer from this restriction.
|
|
Packit |
577717 |
* The umask in PMC4 determines the umask for all the other events in the same set.
|
|
Packit |
577717 |
* It is ignored if the event does no belong to a set or if the event has no
|
|
Packit |
577717 |
* umask (don't care umask).
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* XXX: redudant, already checked in check_cross_groups_and_umasks(pfmlib_param_t *evt)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (l2_grp_present && evt_set(pmc4_evt) != 1 && evt_set(pmc4_evt) != 2) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* extract the umask of the "key" event
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pmc4_umask = evt_umask(pmc4_evt);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
failure = 4;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < cnt; i++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
umask = evt_umask(e[i].event);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("pmc4_evt=%d pmc4_umask=0x%lx cnt_list[%d]=%d grp=%d umask=0x%lx\n", pmc4_evt, pmc4_umask, i, e[i].event,evt_grp(e[i].event), umask);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (as[i] != 4 && evt_grp(e[i].event) == PFMLIB_ITA2_EVT_L2_CACHE_GRP && umask != 0 && umask != pmc4_umask) break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (i != cnt) goto do_failure;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
do_failure:
|
|
Packit |
577717 |
DPRINT("%s : failure %d\n", __FUNCTION__, failure);
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* It is not possible to measure more than one of the
|
|
Packit |
577717 |
* L2_OZQ_CANCELS0, L2_OZQ_CANCELS1, L2_OZQ_CANCELS2 at the
|
|
Packit |
577717 |
* same time.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int cancel_events[]=
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
PME_ITA2_L2_OZQ_CANCELS0_ANY,
|
|
Packit |
577717 |
PME_ITA2_L2_OZQ_CANCELS1_REL,
|
|
Packit |
577717 |
PME_ITA2_L2_OZQ_CANCELS2_ACQ
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define NCANCEL_EVENTS sizeof(cancel_events)/sizeof(int)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
check_cancel_events(pfmlib_input_param_t *inp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i, j, count;
|
|
Packit |
577717 |
int code;
|
|
Packit |
577717 |
int cancel_codes[NCANCEL_EVENTS];
|
|
Packit |
577717 |
int idx = -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < NCANCEL_EVENTS; i++) {
|
|
Packit |
577717 |
pfm_get_event_code(cancel_events[i], &code);
|
|
Packit |
577717 |
cancel_codes[i] = code;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
count = inp->pfp_event_count;
|
|
Packit |
577717 |
for(i=0; i < count; i++) {
|
|
Packit |
577717 |
for (j=0; j < NCANCEL_EVENTS; j++) {
|
|
Packit |
577717 |
pfm_get_event_code(inp->pfp_events[i].event, &code);
|
|
Packit |
577717 |
if (code == cancel_codes[j]) {
|
|
Packit |
577717 |
if (idx != -1) {
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
idx = inp->pfp_events[i].event;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Automatically dispatch events to corresponding counters following constraints.
|
|
Packit |
577717 |
* Upon return the pfarg_regt structure is ready to be submitted to kernel
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_ita2_dispatch_counters(pfmlib_input_param_t *inp, pfmlib_ita2_input_param_t *mod_in, pfmlib_output_param_t *outp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
#define has_counter(e,b) (itanium2_pe[e].pme_counters & (1 << (b)) ? (b) : 0)
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t *param = mod_in;
|
|
Packit |
577717 |
pfm_ita2_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 |
int ret;
|
|
Packit |
577717 |
unsigned int max_l0, max_l1, max_l2, max_l3;
|
|
Packit |
577717 |
unsigned int assign[PMU_ITA2_NUM_COUNTERS];
|
|
Packit |
577717 |
unsigned int m, 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 (PFMLIB_DEBUG())
|
|
Packit |
577717 |
for (m=0; m < cnt; m++) {
|
|
Packit |
577717 |
DPRINT("ev[%d]=%s counters=0x%lx\n", m, itanium2_pe[e[m].event].pme_name,
|
|
Packit |
577717 |
itanium2_pe[e[m].event].pme_counters);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (cnt > PMU_ITA2_NUM_COUNTERS) return PFMLIB_ERR_TOOMANY;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = check_cross_groups_and_umasks(inp);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = check_cancel_events(inp);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
max_l0 = PMU_ITA2_FIRST_COUNTER + PMU_ITA2_NUM_COUNTERS;
|
|
Packit |
577717 |
max_l1 = PMU_ITA2_FIRST_COUNTER + PMU_ITA2_NUM_COUNTERS*(cnt>1);
|
|
Packit |
577717 |
max_l2 = PMU_ITA2_FIRST_COUNTER + PMU_ITA2_NUM_COUNTERS*(cnt>2);
|
|
Packit |
577717 |
max_l3 = PMU_ITA2_FIRST_COUNTER + PMU_ITA2_NUM_COUNTERS*(cnt>3);
|
|
Packit |
577717 |
|
|
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 |
* For now, worst case in the loop nest: 4! (factorial)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (i=PMU_ITA2_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_ITA2_FIRST_COUNTER && valid_assign(e, assign, r_pmcs, cnt) == PFMLIB_SUCCESS) goto done;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (j=PMU_ITA2_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_ITA2_FIRST_COUNTER && valid_assign(e, assign, r_pmcs, cnt) == PFMLIB_SUCCESS) goto done;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (k=PMU_ITA2_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_ITA2_FIRST_COUNTER && valid_assign(e, assign, r_pmcs, cnt) == PFMLIB_SUCCESS) goto done;
|
|
Packit |
577717 |
for (l=PMU_ITA2_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(e, assign, r_pmcs, cnt) == PFMLIB_SUCCESS) 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 |
for (j=0; j < cnt ; j++ ) {
|
|
Packit |
577717 |
reg.pmc_val = 0; /* clear all, bits 26-27 must be zero for proper operations */
|
|
Packit |
577717 |
/* if plm is 0, then assume not specified per-event and use default */
|
|
Packit |
577717 |
reg.pmc_plm = inp->pfp_events[j].plm ? inp->pfp_events[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_thres = param ? param->pfp_ita2_counters[j].thres: 0;
|
|
Packit |
577717 |
reg.pmc_ism = param ? param->pfp_ita2_counters[j].ism : PFMLIB_ITA2_ISM_BOTH;
|
|
Packit |
577717 |
reg.pmc_umask = is_ear(e[j].event) ? 0x0 : itanium2_pe[e[j].event].pme_umask;
|
|
Packit |
577717 |
reg.pmc_es = itanium2_pe[e[j].event].pme_code;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Note that we don't force PMC4.pmc_ena = 1 because the kernel takes care of this for us.
|
|
Packit |
577717 |
* This way we don't have to program something in PMC4 even when we don't use it
|
|
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 = pc[j].reg_alt_addr = assign[j];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pd[j].reg_num = assign[j];
|
|
Packit |
577717 |
pd[j].reg_addr = pd[j].reg_alt_addr = assign[j];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[PMC%u(pmc%u)=0x%06lx thres=%d es=0x%02x plm=%d umask=0x%x pm=%d ism=0x%x oi=%d] %s\n",
|
|
Packit |
577717 |
assign[j],
|
|
Packit |
577717 |
assign[j],
|
|
Packit |
577717 |
reg.pmc_val,
|
|
Packit |
577717 |
reg.pmc_thres,
|
|
Packit |
577717 |
reg.pmc_es,reg.pmc_plm,
|
|
Packit |
577717 |
reg.pmc_umask, reg.pmc_pm,
|
|
Packit |
577717 |
reg.pmc_ism,
|
|
Packit |
577717 |
reg.pmc_oi,
|
|
Packit |
577717 |
itanium2_pe[e[j].event].pme_name);
|
|
Packit |
577717 |
__pfm_vbprintf("[PMD%u(pmd%u)]\n", pd[j].reg_num, pd[j].reg_num);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/* number of PMC registers 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_dispatch_iear(pfmlib_input_param_t *inp, pfmlib_ita2_input_param_t *mod_in, pfmlib_output_param_t *outp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_ita2_pmc_reg_t reg;
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t *param = mod_in;
|
|
Packit |
577717 |
pfmlib_reg_t *pc, *pd;
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t fake_param;
|
|
Packit |
577717 |
unsigned int pos1, pos2;
|
|
Packit |
577717 |
unsigned int i, count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc = outp->pfp_pmcs;
|
|
Packit |
577717 |
pd = outp->pfp_pmds;
|
|
Packit |
577717 |
pos1 = outp->pfp_pmc_count;
|
|
Packit |
577717 |
pos2 = outp->pfp_pmd_count;
|
|
Packit |
577717 |
count = inp->pfp_event_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i=0; i < count; i++) {
|
|
Packit |
577717 |
if (is_iear(inp->pfp_events[i].event)) break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param == NULL || param->pfp_ita2_iear.ear_used == 0) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* case 3: no I-EAR event, no (or nothing) in param->pfp_ita2_iear.ear_used
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (i == count) return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&fake_param, 0, sizeof(fake_param));
|
|
Packit |
577717 |
param = &fake_param;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* case 1: extract all information for event (name)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pfm_ita2_get_ear_mode(inp->pfp_events[i].event, ¶m->pfp_ita2_iear.ear_mode);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
param->pfp_ita2_iear.ear_umask = evt_umask(inp->pfp_events[i].event);
|
|
Packit |
577717 |
param->pfp_ita2_iear.ear_ism = PFMLIB_ITA2_ISM_BOTH; /* force both instruction sets */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("I-EAR event with no info\n");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* case 2: ear_used=1, event is defined, we use the param info as it is more precise
|
|
Packit |
577717 |
* case 4: ear_used=1, no event (free running I-EAR), use param info
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
reg.pmc_val = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param->pfp_ita2_iear.ear_mode == PFMLIB_ITA2_EAR_TLB_MODE) {
|
|
Packit |
577717 |
/* if plm is 0, then assume not specified per-event and use default */
|
|
Packit |
577717 |
reg.pmc10_ita2_tlb_reg.iear_plm = param->pfp_ita2_iear.ear_plm ? param->pfp_ita2_iear.ear_plm : inp->pfp_dfl_plm;
|
|
Packit |
577717 |
reg.pmc10_ita2_tlb_reg.iear_pm = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
|
|
Packit |
577717 |
reg.pmc10_ita2_tlb_reg.iear_ct = 0x0;
|
|
Packit |
577717 |
reg.pmc10_ita2_tlb_reg.iear_umask = param->pfp_ita2_iear.ear_umask;
|
|
Packit |
577717 |
reg.pmc10_ita2_tlb_reg.iear_ism = param->pfp_ita2_iear.ear_ism;
|
|
Packit |
577717 |
} else if (param->pfp_ita2_iear.ear_mode == PFMLIB_ITA2_EAR_CACHE_MODE) {
|
|
Packit |
577717 |
/* if plm is 0, then assume not specified per-event and use default */
|
|
Packit |
577717 |
reg.pmc10_ita2_cache_reg.iear_plm = param->pfp_ita2_iear.ear_plm ? param->pfp_ita2_iear.ear_plm : inp->pfp_dfl_plm;
|
|
Packit |
577717 |
reg.pmc10_ita2_cache_reg.iear_pm = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
|
|
Packit |
577717 |
reg.pmc10_ita2_cache_reg.iear_ct = 0x1;
|
|
Packit |
577717 |
reg.pmc10_ita2_cache_reg.iear_umask = param->pfp_ita2_iear.ear_umask;
|
|
Packit |
577717 |
reg.pmc10_ita2_cache_reg.iear_ism = param->pfp_ita2_iear.ear_ism;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
DPRINT("ALAT mode not supported in I-EAR mode\n");
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 10))
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pos1].reg_num = 10; /* PMC10 is I-EAR config register */
|
|
Packit |
577717 |
pc[pos1].reg_value = reg.pmc_val;
|
|
Packit |
577717 |
pc[pos1].reg_addr = pc[pos1].reg_alt_addr = 10;
|
|
Packit |
577717 |
pos1++;
|
|
Packit |
577717 |
pd[pos2].reg_num = 0;
|
|
Packit |
577717 |
pd[pos2].reg_addr = pd[pos2].reg_alt_addr= 0;
|
|
Packit |
577717 |
pos2++;
|
|
Packit |
577717 |
pd[pos2].reg_num = 1;
|
|
Packit |
577717 |
pd[pos2].reg_addr = pd[pos2].reg_alt_addr = 1;
|
|
Packit |
577717 |
pos2++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param->pfp_ita2_iear.ear_mode == PFMLIB_ITA2_EAR_TLB_MODE) {
|
|
Packit |
577717 |
__pfm_vbprintf("[PMC10(pmc10)=0x%lx ctb=tlb plm=%d pm=%d ism=0x%x umask=0x%x]\n",
|
|
Packit |
577717 |
reg.pmc_val,
|
|
Packit |
577717 |
reg.pmc10_ita2_tlb_reg.iear_plm,
|
|
Packit |
577717 |
reg.pmc10_ita2_tlb_reg.iear_pm,
|
|
Packit |
577717 |
reg.pmc10_ita2_tlb_reg.iear_ism,
|
|
Packit |
577717 |
reg.pmc10_ita2_tlb_reg.iear_umask);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
__pfm_vbprintf("[PMC10(pmc10)=0x%lx ctb=cache plm=%d pm=%d ism=0x%x umask=0x%x]\n",
|
|
Packit |
577717 |
reg.pmc_val,
|
|
Packit |
577717 |
reg.pmc10_ita2_cache_reg.iear_plm,
|
|
Packit |
577717 |
reg.pmc10_ita2_cache_reg.iear_pm,
|
|
Packit |
577717 |
reg.pmc10_ita2_cache_reg.iear_ism,
|
|
Packit |
577717 |
reg.pmc10_ita2_cache_reg.iear_umask);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
__pfm_vbprintf("[PMD0(pmd0)]\n[PMD1(pmd1)\n");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* update final number of entries used */
|
|
Packit |
577717 |
outp->pfp_pmc_count = pos1;
|
|
Packit |
577717 |
outp->pfp_pmd_count = pos2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_dispatch_dear(pfmlib_input_param_t *inp, pfmlib_ita2_input_param_t *mod_in, pfmlib_output_param_t *outp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_ita2_pmc_reg_t reg;
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t *param = mod_in;
|
|
Packit |
577717 |
pfmlib_reg_t *pc, *pd;
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t fake_param;
|
|
Packit |
577717 |
unsigned int pos1, pos2;
|
|
Packit |
577717 |
unsigned int i, count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc = outp->pfp_pmcs;
|
|
Packit |
577717 |
pd = outp->pfp_pmds;
|
|
Packit |
577717 |
pos1 = outp->pfp_pmc_count;
|
|
Packit |
577717 |
pos2 = outp->pfp_pmd_count;
|
|
Packit |
577717 |
count = inp->pfp_event_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i=0; i < count; i++) {
|
|
Packit |
577717 |
if (is_dear(inp->pfp_events[i].event)) break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param == NULL || param->pfp_ita2_dear.ear_used == 0) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* case 3: no D-EAR event, no (or nothing) in param->pfp_ita2_dear.ear_used
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (i == count) return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&fake_param, 0, sizeof(fake_param));
|
|
Packit |
577717 |
param = &fake_param;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* case 1: extract all information for event (name)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pfm_ita2_get_ear_mode(inp->pfp_events[i].event, ¶m->pfp_ita2_dear.ear_mode);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
param->pfp_ita2_dear.ear_umask = evt_umask(inp->pfp_events[i].event);
|
|
Packit |
577717 |
param->pfp_ita2_dear.ear_ism = PFMLIB_ITA2_ISM_BOTH; /* force both instruction sets */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("D-EAR event with no info\n");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* sanity check on the mode */
|
|
Packit |
577717 |
if ( param->pfp_ita2_dear.ear_mode != PFMLIB_ITA2_EAR_CACHE_MODE
|
|
Packit |
577717 |
&& param->pfp_ita2_dear.ear_mode != PFMLIB_ITA2_EAR_TLB_MODE
|
|
Packit |
577717 |
&& param->pfp_ita2_dear.ear_mode != PFMLIB_ITA2_EAR_ALAT_MODE)
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* case 2: ear_used=1, event is defined, we use the param info as it is more precise
|
|
Packit |
577717 |
* case 4: ear_used=1, no event (free running D-EAR), use param info
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
reg.pmc_val = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* if plm is 0, then assume not specified per-event and use default */
|
|
Packit |
577717 |
reg.pmc11_ita2_reg.dear_plm = param->pfp_ita2_dear.ear_plm ? param->pfp_ita2_dear.ear_plm : inp->pfp_dfl_plm;
|
|
Packit |
577717 |
reg.pmc11_ita2_reg.dear_pm = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
|
|
Packit |
577717 |
reg.pmc11_ita2_reg.dear_mode = param->pfp_ita2_dear.ear_mode;
|
|
Packit |
577717 |
reg.pmc11_ita2_reg.dear_umask = param->pfp_ita2_dear.ear_umask;
|
|
Packit |
577717 |
reg.pmc11_ita2_reg.dear_ism = param->pfp_ita2_dear.ear_ism;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 11))
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pos1].reg_num = 11; /* PMC11 is D-EAR config register */
|
|
Packit |
577717 |
pc[pos1].reg_value = reg.pmc_val;
|
|
Packit |
577717 |
pc[pos1].reg_addr = pc[pos1].reg_alt_addr = 11;
|
|
Packit |
577717 |
pos1++;
|
|
Packit |
577717 |
pd[pos2].reg_num = 2;
|
|
Packit |
577717 |
pd[pos2].reg_addr = pd[pos2].reg_alt_addr = 2;
|
|
Packit |
577717 |
pos2++;
|
|
Packit |
577717 |
pd[pos2].reg_num = 3;
|
|
Packit |
577717 |
pd[pos2].reg_addr = pd[pos2].reg_alt_addr = 3;
|
|
Packit |
577717 |
pos2++;
|
|
Packit |
577717 |
pd[pos2].reg_num = 17;
|
|
Packit |
577717 |
pd[pos2].reg_addr = pd[pos2].reg_alt_addr = 17;
|
|
Packit |
577717 |
pos2++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[PMC11(pmc11)=0x%lx mode=%s plm=%d pm=%d ism=0x%x umask=0x%x]\n",
|
|
Packit |
577717 |
reg.pmc_val,
|
|
Packit |
577717 |
reg.pmc11_ita2_reg.dear_mode == 0 ? "L1D" :
|
|
Packit |
577717 |
(reg.pmc11_ita2_reg.dear_mode == 1 ? "L1DTLB" : "ALAT"),
|
|
Packit |
577717 |
reg.pmc11_ita2_reg.dear_plm,
|
|
Packit |
577717 |
reg.pmc11_ita2_reg.dear_pm,
|
|
Packit |
577717 |
reg.pmc11_ita2_reg.dear_ism,
|
|
Packit |
577717 |
reg.pmc11_ita2_reg.dear_umask);
|
|
Packit |
577717 |
__pfm_vbprintf("[PMD2(pmd2)]\n[PMD3(pmd3)\nPMD17(pmd17)\n");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* update final number of entries used */
|
|
Packit |
577717 |
outp->pfp_pmc_count = pos1;
|
|
Packit |
577717 |
outp->pfp_pmd_count = pos2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_dispatch_opcm(pfmlib_input_param_t *inp, pfmlib_ita2_input_param_t *mod_in, pfmlib_output_param_t *outp, pfmlib_ita2_output_param_t *mod_out)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t *param = mod_in;
|
|
Packit |
577717 |
pfmlib_reg_t *pc = outp->pfp_pmcs;
|
|
Packit |
577717 |
pfm_ita2_pmc_reg_t reg, pmc15;
|
|
Packit |
577717 |
unsigned int i, has_1st_pair, has_2nd_pair, count;
|
|
Packit |
577717 |
unsigned int pos = outp->pfp_pmc_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param == NULL) return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* not constrained by PMC8 nor PMC9 */
|
|
Packit |
577717 |
pmc15.pmc_val = 0xffffffff; /* XXX: use PAL instead. PAL value is 0xfffffff0 */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param->pfp_ita2_irange.rr_used && mod_out == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param->pfp_ita2_pmc8.opcm_used || (param->pfp_ita2_irange.rr_used && mod_out->pfp_ita2_irange.rr_nbr_used!=0) ) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
reg.pmc_val = param->pfp_ita2_pmc8.opcm_used ? param->pfp_ita2_pmc8.pmc_val : 0xffffffff3fffffff;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param->pfp_ita2_irange.rr_used) {
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_ig_ad = 0;
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_inv = param->pfp_ita2_irange.rr_flags & PFMLIB_ITA2_RR_INV ? 1 : 0;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
/* clear range restriction fields when none is used */
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_ig_ad = 1;
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_inv = 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* force bit 2 to 1 */
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_bit2 = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 8))
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pos].reg_num = 8;
|
|
Packit |
577717 |
pc[pos].reg_value = reg.pmc_val;
|
|
Packit |
577717 |
pc[pos].reg_addr = pc[pos].reg_alt_addr = 8;
|
|
Packit |
577717 |
pos++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* will be constrained by PMC8
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (param->pfp_ita2_pmc8.opcm_used) {
|
|
Packit |
577717 |
has_1st_pair = has_2nd_pair = 0;
|
|
Packit |
577717 |
count = inp->pfp_event_count;
|
|
Packit |
577717 |
for(i=0; i < count; i++) {
|
|
Packit |
577717 |
if (inp->pfp_events[i].event == PME_ITA2_IA64_TAGGED_INST_RETIRED_IBRP0_PMC8) has_1st_pair=1;
|
|
Packit |
577717 |
if (inp->pfp_events[i].event == PME_ITA2_IA64_TAGGED_INST_RETIRED_IBRP2_PMC8) has_2nd_pair=1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (has_1st_pair || has_2nd_pair == 0) pmc15.pmc15_ita2_reg.opcmc_ibrp0_pmc8 = 0;
|
|
Packit |
577717 |
if (has_2nd_pair || has_1st_pair == 0) pmc15.pmc15_ita2_reg.opcmc_ibrp2_pmc8 = 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[PMC8(pmc8)=0x%lx m=%d i=%d f=%d b=%d match=0x%x mask=0x%x inv=%d ig_ad=%d]\n",
|
|
Packit |
577717 |
reg.pmc_val,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_m,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_i,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_f,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_b,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_match,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_mask,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_inv,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_ig_ad);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param->pfp_ita2_pmc9.opcm_used) {
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* PMC9 can only be used to qualify IA64_INST_RETIRED_* events
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (check_inst_retired_events(inp, NULL) != inp->pfp_event_count) return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
reg.pmc_val = param->pfp_ita2_pmc9.pmc_val;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* ig_ad, inv are ignored for PMC9, to avoid confusion we force default values */
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_ig_ad = 1;
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_inv = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* force bit 2 to 1 */
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_bit2 = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 9))
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pos].reg_num = 9;
|
|
Packit |
577717 |
pc[pos].reg_value = reg.pmc_val;
|
|
Packit |
577717 |
pc[pos].reg_addr = pc[pos].reg_alt_addr = 9;
|
|
Packit |
577717 |
pos++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* will be constrained by PMC9
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
has_1st_pair = has_2nd_pair = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
count = inp->pfp_event_count;
|
|
Packit |
577717 |
for(i=0; i < count; i++) {
|
|
Packit |
577717 |
if (inp->pfp_events[i].event == PME_ITA2_IA64_TAGGED_INST_RETIRED_IBRP1_PMC9) has_1st_pair=1;
|
|
Packit |
577717 |
if (inp->pfp_events[i].event == PME_ITA2_IA64_TAGGED_INST_RETIRED_IBRP3_PMC9) has_2nd_pair=1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (has_1st_pair || has_2nd_pair == 0) pmc15.pmc15_ita2_reg.opcmc_ibrp1_pmc9 = 0;
|
|
Packit |
577717 |
if (has_2nd_pair || has_1st_pair == 0) pmc15.pmc15_ita2_reg.opcmc_ibrp3_pmc9 = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[PMC9(pmc9)=0x%lx m=%d i=%d f=%d b=%d match=0x%x mask=0x%x]\n",
|
|
Packit |
577717 |
reg.pmc_val,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_m,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_i,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_f,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_b,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_match,
|
|
Packit |
577717 |
reg.pmc8_9_ita2_reg.opcm_mask);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 15))
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pos].reg_num = 15;
|
|
Packit |
577717 |
pc[pos].reg_value = pmc15.pmc_val;
|
|
Packit |
577717 |
pc[pos].reg_addr = pc[pos].reg_alt_addr = 15;
|
|
Packit |
577717 |
pos++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[PMC15(pmc15)=0x%lx ibrp0_pmc8=%d ibrp1_pmc9=%d ibrp2_pmc8=%d ibrp3_pmc9=%d]\n",
|
|
Packit |
577717 |
pmc15.pmc_val,
|
|
Packit |
577717 |
pmc15.pmc15_ita2_reg.opcmc_ibrp0_pmc8,
|
|
Packit |
577717 |
pmc15.pmc15_ita2_reg.opcmc_ibrp1_pmc9,
|
|
Packit |
577717 |
pmc15.pmc15_ita2_reg.opcmc_ibrp2_pmc8,
|
|
Packit |
577717 |
pmc15.pmc15_ita2_reg.opcmc_ibrp3_pmc9);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
outp->pfp_pmc_count = pos;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_dispatch_btb(pfmlib_input_param_t *inp, pfmlib_ita2_input_param_t *mod_in, pfmlib_output_param_t *outp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_event_t *e= inp->pfp_events;
|
|
Packit |
577717 |
pfm_ita2_pmc_reg_t reg;
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t *param = mod_in;
|
|
Packit |
577717 |
pfmlib_reg_t *pc, *pd;
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t fake_param;
|
|
Packit |
577717 |
int found_btb = 0, found_bad_dear = 0;
|
|
Packit |
577717 |
int has_btb_param;
|
|
Packit |
577717 |
unsigned int i, pos1, pos2;
|
|
Packit |
577717 |
unsigned int count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc = outp->pfp_pmcs;
|
|
Packit |
577717 |
pd = outp->pfp_pmds;
|
|
Packit |
577717 |
pos1 = outp->pfp_pmc_count;
|
|
Packit |
577717 |
pos2 = outp->pfp_pmd_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* explicit BTB settings
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
has_btb_param = param && param->pfp_ita2_btb.btb_used;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
reg.pmc_val = 0UL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we need to scan all events looking for DEAR ALAT/TLB due to incompatibility
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
count = inp->pfp_event_count;
|
|
Packit |
577717 |
for (i=0; i < count; i++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (is_btb(e[i].event)) found_btb = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* keep track of the first BTB event
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* look only for DEAR TLB */
|
|
Packit |
577717 |
if (is_dear(e[i].event) && (is_ear_tlb(e[i].event) || is_ear_alat(e[i].event))) {
|
|
Packit |
577717 |
found_bad_dear = 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("found_btb=%d found_bar_dear=%d\n", found_btb, found_bad_dear);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* did not find D-EAR TLB/ALAT event, need to check param structure
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (found_bad_dear == 0 && param && param->pfp_ita2_dear.ear_used == 1) {
|
|
Packit |
577717 |
if ( param->pfp_ita2_dear.ear_mode == PFMLIB_ITA2_EAR_TLB_MODE
|
|
Packit |
577717 |
|| param->pfp_ita2_dear.ear_mode == PFMLIB_ITA2_EAR_ALAT_MODE)
|
|
Packit |
577717 |
found_bad_dear = 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* no explicit BTB event and no special case to deal with (cover part of case 3)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (found_btb == 0 && has_btb_param == 0 && found_bad_dear == 0) return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (has_btb_param == 0) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* case 3: no BTB event, btb_used=0 but found_bad_dear=1, need to cleanup PMC12
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (found_btb == 0) goto assign_zero;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* case 1: we have a BTB event but no param, default setting is to capture
|
|
Packit |
577717 |
* all branches.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
memset(&fake_param, 0, sizeof(fake_param));
|
|
Packit |
577717 |
param = &fake_param;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
param->pfp_ita2_btb.btb_ds = 0; /* capture branch targets */
|
|
Packit |
577717 |
param->pfp_ita2_btb.btb_tm = 0x3; /* all branches */
|
|
Packit |
577717 |
param->pfp_ita2_btb.btb_ptm = 0x3; /* all branches */
|
|
Packit |
577717 |
param->pfp_ita2_btb.btb_ppm = 0x3; /* all branches */
|
|
Packit |
577717 |
param->pfp_ita2_btb.btb_brt = 0x0; /* all branches */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("BTB event with no info\n");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* case 2: BTB event in the list, param provided
|
|
Packit |
577717 |
* case 4: no BTB event, param provided (free running mode)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_plm = param->pfp_ita2_btb.btb_plm ? param->pfp_ita2_btb.btb_plm : inp->pfp_dfl_plm;
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_pm = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_ds = param->pfp_ita2_btb.btb_ds & 0x1;
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_tm = param->pfp_ita2_btb.btb_tm & 0x3;
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_ptm = param->pfp_ita2_btb.btb_ptm & 0x3;
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_ppm = param->pfp_ita2_btb.btb_ppm & 0x3;
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_brt = param->pfp_ita2_btb.btb_brt & 0x3;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* if DEAR-ALAT or DEAR-TLB is set then PMC12 must be set to zero (see documentation p. 87)
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* D-EAR ALAT/TLB and BTB cannot be used at the same time.
|
|
Packit |
577717 |
* From documentation: PMC12 must be zero in this mode; else the wrong IP for misses
|
|
Packit |
577717 |
* coming right after a mispredicted branch.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* D-EAR cache is fine.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
assign_zero:
|
|
Packit |
577717 |
if (found_bad_dear && reg.pmc_val != 0UL) return PFMLIB_ERR_EVTINCOMP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 12))
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(pc+pos1, 0, sizeof(pfmlib_reg_t));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pos1].reg_num = 12;
|
|
Packit |
577717 |
pc[pos1].reg_value = reg.pmc_val;
|
|
Packit |
577717 |
pc[pos1].reg_addr = pc[pos1].reg_alt_addr = 12;
|
|
Packit |
577717 |
pos1++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[PMC12(pmc12)=0x%lx plm=%d pm=%d ds=%d tm=%d ptm=%d ppm=%d brt=%d]\n",
|
|
Packit |
577717 |
reg.pmc_val,
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_plm,
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_pm,
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_ds,
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_tm,
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_ptm,
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_ppm,
|
|
Packit |
577717 |
reg.pmc12_ita2_reg.btbc_brt);
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* only add BTB PMD when actually using BTB.
|
|
Packit |
577717 |
* Not needed when dealing with D-EAR TLB and DEAR-ALAT
|
|
Packit |
577717 |
* PMC12 restriction
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (found_btb || has_btb_param) {
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* PMD16 is included in list of used PMD
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(i=8; i < 17; i++, pos2++) {
|
|
Packit |
577717 |
pd[pos2].reg_num = i;
|
|
Packit |
577717 |
pd[pos2].reg_addr = pd[pos2].reg_alt_addr = i;
|
|
Packit |
577717 |
__pfm_vbprintf("[PMD%u(pmd%u)]\n", pd[pos2].reg_num, pd[pos2].reg_num);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* update final number of entries used */
|
|
Packit |
577717 |
outp->pfp_pmc_count = pos1;
|
|
Packit |
577717 |
outp->pfp_pmd_count = pos2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
do_normal_rr(unsigned long start, unsigned long end,
|
|
Packit |
577717 |
pfmlib_reg_t *br, int nbr, int dir, int *idx, int *reg_idx, int plm)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned long size, l_addr, c;
|
|
Packit |
577717 |
unsigned long l_offs = 0, r_offs = 0;
|
|
Packit |
577717 |
unsigned long l_size, r_size;
|
|
Packit |
577717 |
dbreg_t db;
|
|
Packit |
577717 |
int p2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (nbr < 1 || end <= start) return;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
size = end - start;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("start=0x%016lx end=0x%016lx size=0x%lx bytes (%lu bundles) nbr=%d dir=%d\n",
|
|
Packit |
577717 |
start, end, size, size >> 4, nbr, dir);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
p2 = pfm_ia64_fls(size);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
c = ALIGN_DOWN(end, p2);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("largest power of two possible: 2^%d=0x%lx, crossing=0x%016lx\n",
|
|
Packit |
577717 |
p2,
|
|
Packit |
577717 |
1UL << p2, c);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((c - (1UL<<p2)) >= start) {
|
|
Packit |
577717 |
l_addr = c - (1UL << p2);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
p2--;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((c + (1UL<
|
|
Packit |
577717 |
l_addr = c;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
l_addr = c - (1UL << p2);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
l_size = l_addr - start;
|
|
Packit |
577717 |
r_size = end - l_addr-(1UL<
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_DEBUG()) {
|
|
Packit |
577717 |
printf("largest chunk: 2^%d=0x%lx @0x%016lx-0x%016lx\n", p2, 1UL<
|
|
Packit |
577717 |
if (l_size) printf("before: 0x%016lx-0x%016lx\n", start, l_addr);
|
|
Packit |
577717 |
if (r_size) printf("after : 0x%016lx-0x%016lx\n", l_addr+(1UL<
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (dir == 0 && l_size != 0 && nbr == 1) {
|
|
Packit |
577717 |
p2++;
|
|
Packit |
577717 |
l_addr = end - (1UL << p2);
|
|
Packit |
577717 |
if (PFMLIB_DEBUG()) {
|
|
Packit |
577717 |
l_offs = start - l_addr;
|
|
Packit |
577717 |
printf(">>l_offs: 0x%lx\n", l_offs);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else if (dir == 1 && r_size != 0 && nbr == 1) {
|
|
Packit |
577717 |
p2++;
|
|
Packit |
577717 |
l_addr = start;
|
|
Packit |
577717 |
if (PFMLIB_DEBUG()) {
|
|
Packit |
577717 |
r_offs = l_addr+(1UL<
|
|
Packit |
577717 |
printf(">>r_offs: 0x%lx\n", r_offs);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
l_size = l_addr - start;
|
|
Packit |
577717 |
r_size = end - l_addr-(1UL<
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_DEBUG()) {
|
|
Packit |
577717 |
printf(">>largest chunk: 2^%d @0x%016lx-0x%016lx\n", p2, l_addr, l_addr+(1UL<
|
|
Packit |
577717 |
if (l_size && !l_offs) printf(">>before: 0x%016lx-0x%016lx\n", start, l_addr);
|
|
Packit |
577717 |
if (r_size && !r_offs) printf(">>after : 0x%016lx-0x%016lx\n", l_addr+(1UL<
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we initialize the mask to full 0 and
|
|
Packit |
577717 |
* only update the mask field. the rest is left
|
|
Packit |
577717 |
* to zero, except for the plm.
|
|
Packit |
577717 |
* in the case of ibr, the x-field must be 0. For dbr
|
|
Packit |
577717 |
* the value of r-field and w-field is ignored.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
db.val = 0;
|
|
Packit |
577717 |
db.db.db_mask = ~((1UL << p2)-1);
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we always use default privilege level.
|
|
Packit |
577717 |
* plm is ignored for DBRs.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
db.db.db_plm = plm;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
br[*idx].reg_num = *reg_idx;
|
|
Packit |
577717 |
br[*idx].reg_value = l_addr;
|
|
Packit |
577717 |
br[*idx].reg_addr = br[*idx].reg_alt_addr = *reg_idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
br[*idx+1].reg_num = *reg_idx+1;
|
|
Packit |
577717 |
br[*idx+1].reg_value = db.val;
|
|
Packit |
577717 |
br[*idx+1].reg_addr = br[*idx+1].reg_alt_addr = *reg_idx+1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*idx += 2;
|
|
Packit |
577717 |
*reg_idx += 2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
nbr--;
|
|
Packit |
577717 |
if (nbr) {
|
|
Packit |
577717 |
int r_nbr, l_nbr;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
r_nbr = l_nbr = nbr >>1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (nbr & 0x1) {
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* our simple heuristic is:
|
|
Packit |
577717 |
* we assign the largest number of registers to the largest
|
|
Packit |
577717 |
* of the two chunks
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (l_size > r_size) {
|
|
Packit |
577717 |
l_nbr++;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
r_nbr++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
do_normal_rr(start, l_addr, br, l_nbr, 0, idx, reg_idx, plm);
|
|
Packit |
577717 |
do_normal_rr(l_addr+(1UL<
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
print_one_range(pfmlib_ita2_input_rr_desc_t *in_rr, pfmlib_ita2_output_rr_desc_t *out_rr, pfmlib_reg_t *dbr, int base_idx, int n_pairs, int fine_mode, unsigned int rr_flags)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int j;
|
|
Packit |
577717 |
dbreg_t d;
|
|
Packit |
577717 |
unsigned long r_end;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[0x%lx-0x%lx): %d register pair(s)%s%s\n",
|
|
Packit |
577717 |
in_rr->rr_start, in_rr->rr_end,
|
|
Packit |
577717 |
n_pairs,
|
|
Packit |
577717 |
fine_mode ? ", fine_mode" : "",
|
|
Packit |
577717 |
rr_flags & PFMLIB_ITA2_RR_INV ? ", inversed" : "");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("start offset: -0x%lx end_offset: +0x%lx\n", out_rr->rr_soff, out_rr->rr_eoff);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (j=0; j < n_pairs; j++, base_idx+=2) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
d.val = dbr[base_idx+1].reg_value;
|
|
Packit |
577717 |
r_end = dbr[base_idx].reg_value+((~(d.db.db_mask)) & ~(0xffUL << 56));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (fine_mode)
|
|
Packit |
577717 |
__pfm_vbprintf("brp%u: db%u: 0x%016lx db%u: plm=0x%x mask=0x%016lx\n",
|
|
Packit |
577717 |
dbr[base_idx].reg_num>>1,
|
|
Packit |
577717 |
dbr[base_idx].reg_num,
|
|
Packit |
577717 |
dbr[base_idx].reg_value,
|
|
Packit |
577717 |
dbr[base_idx+1].reg_num,
|
|
Packit |
577717 |
d.db.db_plm, d.db.db_mask);
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
__pfm_vbprintf("brp%u: db%u: 0x%016lx db%u: plm=0x%x mask=0x%016lx end=0x%016lx\n",
|
|
Packit |
577717 |
dbr[base_idx].reg_num>>1,
|
|
Packit |
577717 |
dbr[base_idx].reg_num,
|
|
Packit |
577717 |
dbr[base_idx].reg_value,
|
|
Packit |
577717 |
dbr[base_idx+1].reg_num,
|
|
Packit |
577717 |
d.db.db_plm, d.db.db_mask,
|
|
Packit |
577717 |
r_end);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* base_idx = base register index to use (for IBRP1, base_idx = 2)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
compute_fine_rr(pfmlib_ita2_input_rr_t *irr, int dfl_plm, int n, int *base_idx, pfmlib_ita2_output_rr_t *orr)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
pfmlib_reg_t *br;
|
|
Packit |
577717 |
pfmlib_ita2_input_rr_desc_t *in_rr;
|
|
Packit |
577717 |
pfmlib_ita2_output_rr_desc_t *out_rr;
|
|
Packit |
577717 |
unsigned long addr;
|
|
Packit |
577717 |
int reg_idx;
|
|
Packit |
577717 |
dbreg_t db;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
in_rr = irr->rr_limits;
|
|
Packit |
577717 |
out_rr = orr->rr_infos;
|
|
Packit |
577717 |
br = orr->rr_br+orr->rr_nbr_used;
|
|
Packit |
577717 |
reg_idx = *base_idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
db.val = 0;
|
|
Packit |
577717 |
db.db.db_mask = FINE_MODE_MASK;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (n > 2) return PFMLIB_ERR_IRRTOOMANY;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i=0; i < n; i++, reg_idx += 2, in_rr++, br+= 4) {
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* setup lower limit pair
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* because of the PMU bug, we must align down to the closest bundle-pair
|
|
Packit |
577717 |
* aligned address. 5 => 32-byte aligned address
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
addr = has_fine_mode_bug ? ALIGN_DOWN(in_rr->rr_start, 5) : in_rr->rr_start;
|
|
Packit |
577717 |
out_rr->rr_soff = in_rr->rr_start - addr;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* adjust plm for each range
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
db.db.db_plm = in_rr->rr_plm ? in_rr->rr_plm : (unsigned long)dfl_plm;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
br[0].reg_num = reg_idx;
|
|
Packit |
577717 |
br[0].reg_value = addr;
|
|
Packit |
577717 |
br[0].reg_addr = br[0].reg_alt_addr = reg_idx;
|
|
Packit |
577717 |
br[1].reg_num = reg_idx+1;
|
|
Packit |
577717 |
br[1].reg_value = db.val;
|
|
Packit |
577717 |
br[1].reg_addr = br[1].reg_alt_addr = reg_idx+1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* setup upper limit pair
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* In fine mode, the bundle address stored in the upper limit debug
|
|
Packit |
577717 |
* registers is included in the count, so we substract 0x10 to exclude it.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* because of the PMU bug, we align the (corrected) end to the nearest
|
|
Packit |
577717 |
* 32-byte aligned address + 0x10. With this correction and depending
|
|
Packit |
577717 |
* on the correction, we may count one
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
addr = in_rr->rr_end - 0x10;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (has_fine_mode_bug && (addr & 0x1f) == 0) addr += 0x10;
|
|
Packit |
577717 |
out_rr->rr_eoff = addr - in_rr->rr_end + 0x10;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
br[2].reg_num = reg_idx+4;
|
|
Packit |
577717 |
br[2].reg_value = addr;
|
|
Packit |
577717 |
br[2].reg_addr = br[2].reg_alt_addr = reg_idx+4;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
br[3].reg_num = reg_idx+5;
|
|
Packit |
577717 |
br[3].reg_value = db.val;
|
|
Packit |
577717 |
br[3].reg_addr = br[3].reg_alt_addr = reg_idx+5;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_VERBOSE()) print_one_range(in_rr, out_rr, br, 0, 2, 1, irr->rr_flags);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
orr->rr_nbr_used += i<<2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* update base_idx, for subsequent calls */
|
|
Packit |
577717 |
*base_idx = reg_idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* base_idx = base register index to use (for IBRP1, base_idx = 2)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
compute_single_rr(pfmlib_ita2_input_rr_t *irr, int dfl_plm, int *base_idx, pfmlib_ita2_output_rr_t *orr)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned long size, end, start;
|
|
Packit |
577717 |
unsigned long p_start, p_end;
|
|
Packit |
577717 |
pfmlib_ita2_input_rr_desc_t *in_rr;
|
|
Packit |
577717 |
pfmlib_ita2_output_rr_desc_t *out_rr;
|
|
Packit |
577717 |
pfmlib_reg_t *br;
|
|
Packit |
577717 |
dbreg_t db;
|
|
Packit |
577717 |
int reg_idx;
|
|
Packit |
577717 |
int l, m;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
in_rr = irr->rr_limits;
|
|
Packit |
577717 |
out_rr = orr->rr_infos;
|
|
Packit |
577717 |
br = orr->rr_br+orr->rr_nbr_used;
|
|
Packit |
577717 |
start = in_rr->rr_start;
|
|
Packit |
577717 |
end = in_rr->rr_end;
|
|
Packit |
577717 |
size = end - start;
|
|
Packit |
577717 |
reg_idx = *base_idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
l = pfm_ia64_fls(size);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
m = l;
|
|
Packit |
577717 |
if (size & ((1UL << l)-1)) {
|
|
Packit |
577717 |
if (l>62) {
|
|
Packit |
577717 |
printf("range: [0x%lx-0x%lx] too big\n", start, end);
|
|
Packit |
577717 |
return PFMLIB_ERR_IRRTOOBIG;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
m++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("size=%ld, l=%d m=%d, internal: 0x%lx full: 0x%lx\n",
|
|
Packit |
577717 |
size,
|
|
Packit |
577717 |
l, m,
|
|
Packit |
577717 |
1UL << l,
|
|
Packit |
577717 |
1UL << m);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (; m < 64; m++) {
|
|
Packit |
577717 |
p_start = ALIGN_DOWN(start, m);
|
|
Packit |
577717 |
p_end = p_start+(1UL<
|
|
Packit |
577717 |
if (p_end >= end) goto found;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_ERR_IRRINVAL;
|
|
Packit |
577717 |
found:
|
|
Packit |
577717 |
DPRINT("m=%d p_start=0x%lx p_end=0x%lx\n", m, p_start,p_end);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* when the event is not IA64_INST_RETIRED, then we MUST use ibrp0 */
|
|
Packit |
577717 |
br[0].reg_num = reg_idx;
|
|
Packit |
577717 |
br[0].reg_value = p_start;
|
|
Packit |
577717 |
br[0].reg_addr = br[0].reg_alt_addr = reg_idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
db.val = 0;
|
|
Packit |
577717 |
db.db.db_mask = ~((1UL << m)-1);
|
|
Packit |
577717 |
db.db.db_plm = in_rr->rr_plm ? in_rr->rr_plm : (unsigned long)dfl_plm;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
br[1].reg_num = reg_idx + 1;
|
|
Packit |
577717 |
br[1].reg_value = db.val;
|
|
Packit |
577717 |
br[1].reg_addr = br[1].reg_alt_addr = reg_idx + 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
out_rr->rr_soff = start - p_start;
|
|
Packit |
577717 |
out_rr->rr_eoff = p_end - end;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_VERBOSE()) print_one_range(in_rr, out_rr, br, 0, 1, 0, irr->rr_flags);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
orr->rr_nbr_used += 2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* update base_idx, for subsequent calls */
|
|
Packit |
577717 |
*base_idx = reg_idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
compute_normal_rr(pfmlib_ita2_input_rr_t *irr, int dfl_plm, int n, int *base_idx, pfmlib_ita2_output_rr_t *orr)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_ita2_input_rr_desc_t *in_rr;
|
|
Packit |
577717 |
pfmlib_ita2_output_rr_desc_t *out_rr;
|
|
Packit |
577717 |
unsigned long r_end;
|
|
Packit |
577717 |
pfmlib_reg_t *br;
|
|
Packit |
577717 |
dbreg_t d;
|
|
Packit |
577717 |
int i, j;
|
|
Packit |
577717 |
int br_index, reg_idx, prev_index;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
in_rr = irr->rr_limits;
|
|
Packit |
577717 |
out_rr = orr->rr_infos;
|
|
Packit |
577717 |
br = orr->rr_br+orr->rr_nbr_used;
|
|
Packit |
577717 |
reg_idx = *base_idx;
|
|
Packit |
577717 |
br_index = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i=0; i < n; i++, in_rr++, out_rr++) {
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* running out of registers
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (br_index == 8) break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
prev_index = br_index;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
do_normal_rr( in_rr->rr_start,
|
|
Packit |
577717 |
in_rr->rr_end,
|
|
Packit |
577717 |
br,
|
|
Packit |
577717 |
4 - (reg_idx>>1), /* how many pairs available */
|
|
Packit |
577717 |
0,
|
|
Packit |
577717 |
&br_index,
|
|
Packit |
577717 |
®_idx, in_rr->rr_plm ? in_rr->rr_plm : dfl_plm);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("br_index=%d reg_idx=%d\n", br_index, reg_idx);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* compute offsets
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
out_rr->rr_soff = out_rr->rr_eoff = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(j=prev_index; j < br_index; j+=2) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
d.val = br[j+1].reg_value;
|
|
Packit |
577717 |
r_end = br[j].reg_value+((~(d.db.db_mask)+1) & ~(0xffUL << 56));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (br[j].reg_value <= in_rr->rr_start)
|
|
Packit |
577717 |
out_rr->rr_soff = in_rr->rr_start - br[j].reg_value;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (r_end >= in_rr->rr_end)
|
|
Packit |
577717 |
out_rr->rr_eoff = r_end - in_rr->rr_end;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_VERBOSE()) print_one_range(in_rr, out_rr, br, prev_index, (br_index-prev_index)>>1, 0, irr->rr_flags);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* do not have enough registers to cover all the ranges */
|
|
Packit |
577717 |
if (br_index == 8 && i < n) return PFMLIB_ERR_TOOMANY;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
orr->rr_nbr_used += br_index;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* update base_idx, for subsequent calls */
|
|
Packit |
577717 |
*base_idx = reg_idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_dispatch_irange(pfmlib_input_param_t *inp, pfmlib_ita2_input_param_t *mod_in, pfmlib_output_param_t *outp, pfmlib_ita2_output_param_t *mod_out)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_ita2_pmc_reg_t reg;
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t *param = mod_in;
|
|
Packit |
577717 |
pfmlib_ita2_input_rr_t *irr;
|
|
Packit |
577717 |
pfmlib_ita2_output_rr_t *orr;
|
|
Packit |
577717 |
pfmlib_reg_t *pc = outp->pfp_pmcs;
|
|
Packit |
577717 |
unsigned int i, pos = outp->pfp_pmc_count, count;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
unsigned int retired_only, retired_count, fine_mode, prefetch_count;
|
|
Packit |
577717 |
unsigned int n_intervals;
|
|
Packit |
577717 |
int base_idx = 0;
|
|
Packit |
577717 |
unsigned long retired_mask;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param == NULL) return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param->pfp_ita2_irange.rr_used == 0) return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (mod_out == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
irr = ¶m->pfp_ita2_irange;
|
|
Packit |
577717 |
orr = &mod_out->pfp_ita2_irange;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = check_intervals(irr, 0, &n_intervals);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (n_intervals < 1) return PFMLIB_ERR_IRRINVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
retired_count = check_inst_retired_events(inp, &retired_mask);
|
|
Packit |
577717 |
retired_only = retired_count == inp->pfp_event_count;
|
|
Packit |
577717 |
prefetch_count = check_prefetch_events(inp);
|
|
Packit |
577717 |
fine_mode = irr->rr_flags & PFMLIB_ITA2_RR_NO_FINE_MODE ?
|
|
Packit |
577717 |
0 : check_fine_mode_possible(irr, n_intervals);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("n_intervals=%d retired_only=%d retired_count=%d prefetch_count=%d fine_mode=%d\n",
|
|
Packit |
577717 |
n_intervals, retired_only, retired_count, prefetch_count, fine_mode);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* On Itanium2, there are more constraints on what can be measured with irange.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* - The fine mode is the best because you directly set the lower and upper limits of
|
|
Packit |
577717 |
* the range. This uses 2 ibr pairs for range (ibrp0/ibrp2 and ibp1/ibrp3). Therefore
|
|
Packit |
577717 |
* at most 2 fine mode ranges can be defined. There is a limit on the size and alignment
|
|
Packit |
577717 |
* of the range to allow fine mode: the range must be less than 4KB in size AND the lower
|
|
Packit |
577717 |
* and upper limits must NOT cross a 4KB page boundary. The fine mode works will all events.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* - if the fine mode fails, then for all events, except IA64_TAGGED_INST_RETIRED_*, only
|
|
Packit |
577717 |
* the first pair of ibr is available: ibrp0. This imposes some severe restrictions on the
|
|
Packit |
577717 |
* size and alignement of the range. It can be bigger than 4KB and must be properly aligned
|
|
Packit |
577717 |
* on its size. The library relaxes these constraints by allowing the covered areas to be
|
|
Packit |
577717 |
* larger than the expected range. It may start before and end after. You can determine how
|
|
Packit |
577717 |
* far off the range is in either direction for each range by looking at the rr_soff (start
|
|
Packit |
577717 |
* offset) and rr_eoff (end offset).
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* - if the events include certain prefetch events then only IBRP1 can be used in fine mode
|
|
Packit |
577717 |
* See 10.3.5.1 Exception 1.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* - Finally, when the events are ONLY IA64_TAGGED_INST_RETIRED_* then all IBR pairs can be used
|
|
Packit |
577717 |
* to cover the range giving us more flexibility to approximate the range when it is not
|
|
Packit |
577717 |
* properly aligned on its size (see 10.3.5.2 Exception 2).
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (fine_mode == 0 && retired_only == 0 && n_intervals > 1) return PFMLIB_ERR_IRRTOOMANY;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* we do not default to non-fine mode to support more ranges */
|
|
Packit |
577717 |
if (n_intervals > 2 && fine_mode == 1) return PFMLIB_ERR_IRRTOOMANY;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (fine_mode == 0) {
|
|
Packit |
577717 |
if (retired_only) {
|
|
Packit |
577717 |
ret = compute_normal_rr(irr, inp->pfp_dfl_plm, n_intervals, &base_idx, orr);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
/* unless we have only prefetch and instruction retired events,
|
|
Packit |
577717 |
* we cannot satisfy the request because the other events cannot
|
|
Packit |
577717 |
* be measured on anything but IBRP0.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (prefetch_count && (prefetch_count+retired_count) != inp->pfp_event_count)
|
|
Packit |
577717 |
return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
base_idx = prefetch_count ? 2 : 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = compute_single_rr(irr, inp->pfp_dfl_plm, &base_idx, orr);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
if (prefetch_count && n_intervals != 1) return PFMLIB_ERR_IRRTOOMANY;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
base_idx = prefetch_count ? 2 : 0;
|
|
Packit |
577717 |
ret = compute_fine_rr(irr, inp->pfp_dfl_plm, n_intervals, &base_idx, orr);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) {
|
|
Packit |
577717 |
return ret == PFMLIB_ERR_TOOMANY ? PFMLIB_ERR_IRRTOOMANY : ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
reg.pmc_val = 0xdb6; /* default value */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
count = orr->rr_nbr_used;
|
|
Packit |
577717 |
for (i=0; i < count; i++) {
|
|
Packit |
577717 |
switch(orr->rr_br[i].reg_num) {
|
|
Packit |
577717 |
case 0:
|
|
Packit |
577717 |
reg.pmc14_ita2_reg.iarc_ibrp0 = 0;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 2:
|
|
Packit |
577717 |
reg.pmc14_ita2_reg.iarc_ibrp1 = 0;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 4:
|
|
Packit |
577717 |
reg.pmc14_ita2_reg.iarc_ibrp2 = 0;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 6:
|
|
Packit |
577717 |
reg.pmc14_ita2_reg.iarc_ibrp3 = 0;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (retired_only && (param->pfp_ita2_pmc8.opcm_used ||param->pfp_ita2_pmc9.opcm_used)) {
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* PMC8 + IA64_INST_RETIRED only works if irange on IBRP0 and/or IBRP2
|
|
Packit |
577717 |
* PMC9 + IA64_INST_RETIRED only works if irange on IBRP1 and/or IBRP3
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
count = orr->rr_nbr_used;
|
|
Packit |
577717 |
for (i=0; i < count; i++) {
|
|
Packit |
577717 |
if (orr->rr_br[i].reg_num == 0 && param->pfp_ita2_pmc9.opcm_used) return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
if (orr->rr_br[i].reg_num == 2 && param->pfp_ita2_pmc8.opcm_used) return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
if (orr->rr_br[i].reg_num == 4 && param->pfp_ita2_pmc9.opcm_used) return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
if (orr->rr_br[i].reg_num == 6 && param->pfp_ita2_pmc8.opcm_used) return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (fine_mode) {
|
|
Packit |
577717 |
reg.pmc14_ita2_reg.iarc_fine = 1;
|
|
Packit |
577717 |
} else if (retired_only) {
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we need to check that the user provided all the events needed to cover
|
|
Packit |
577717 |
* all the ibr pairs used to cover the range
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if ((retired_mask & 0x1) == 0 && reg.pmc14_ita2_reg.iarc_ibrp0 == 0) return PFMLIB_ERR_IRRINVAL;
|
|
Packit |
577717 |
if ((retired_mask & 0x2) == 0 && reg.pmc14_ita2_reg.iarc_ibrp1 == 0) return PFMLIB_ERR_IRRINVAL;
|
|
Packit |
577717 |
if ((retired_mask & 0x4) == 0 && reg.pmc14_ita2_reg.iarc_ibrp2 == 0) return PFMLIB_ERR_IRRINVAL;
|
|
Packit |
577717 |
if ((retired_mask & 0x8) == 0 && reg.pmc14_ita2_reg.iarc_ibrp3 == 0) return PFMLIB_ERR_IRRINVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* initialize pmc request slot */
|
|
Packit |
577717 |
memset(pc+pos, 0, sizeof(pfmlib_reg_t));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 14))
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pos].reg_num = 14;
|
|
Packit |
577717 |
pc[pos].reg_value = reg.pmc_val;
|
|
Packit |
577717 |
pc[pos].reg_addr = pc[pos].reg_alt_addr = 14;
|
|
Packit |
577717 |
pos++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[PMC14(pmc14)=0x%lx ibrp0=%d ibrp1=%d ibrp2=%d ibrp3=%d fine=%d]\n",
|
|
Packit |
577717 |
reg.pmc_val,
|
|
Packit |
577717 |
reg.pmc14_ita2_reg.iarc_ibrp0,
|
|
Packit |
577717 |
reg.pmc14_ita2_reg.iarc_ibrp1,
|
|
Packit |
577717 |
reg.pmc14_ita2_reg.iarc_ibrp2,
|
|
Packit |
577717 |
reg.pmc14_ita2_reg.iarc_ibrp3,
|
|
Packit |
577717 |
reg.pmc14_ita2_reg.iarc_fine);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
outp->pfp_pmc_count = pos;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static const unsigned long iod_tab[8]={
|
|
Packit |
577717 |
/* --- */ 3,
|
|
Packit |
577717 |
/* --D */ 2,
|
|
Packit |
577717 |
/* -O- */ 3, /* should not be used */
|
|
Packit |
577717 |
/* -OD */ 0, /* =IOD safe because default IBR is harmless */
|
|
Packit |
577717 |
/* I-- */ 1, /* =IO safe because by defaut OPC is turned off */
|
|
Packit |
577717 |
/* I-D */ 0, /* =IOD safe because by default opc is turned off */
|
|
Packit |
577717 |
/* IO- */ 1,
|
|
Packit |
577717 |
/* IOD */ 0
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* IMPORTANT: MUST BE CALLED *AFTER* pfm_dispatch_irange() to make sure we see
|
|
Packit |
577717 |
* the irange programming to adjust pmc13.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_dispatch_drange(pfmlib_input_param_t *inp, pfmlib_ita2_input_param_t *mod_in, pfmlib_output_param_t *outp, pfmlib_ita2_output_param_t *mod_out)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t *param = mod_in;
|
|
Packit |
577717 |
pfmlib_reg_t *pc = outp->pfp_pmcs;
|
|
Packit |
577717 |
pfmlib_ita2_input_rr_t *irr;
|
|
Packit |
577717 |
pfmlib_ita2_output_rr_t *orr, *orr2;
|
|
Packit |
577717 |
pfm_ita2_pmc_reg_t pmc13;
|
|
Packit |
577717 |
pfm_ita2_pmc_reg_t pmc14;
|
|
Packit |
577717 |
unsigned int i, pos = outp->pfp_pmc_count;
|
|
Packit |
577717 |
int iod_codes[4], dfl_val_pmc8, dfl_val_pmc9;
|
|
Packit |
577717 |
unsigned int n_intervals;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
int base_idx = 0;
|
|
Packit |
577717 |
int fine_mode = 0;
|
|
Packit |
577717 |
#define DR_USED 0x1 /* data range is used */
|
|
Packit |
577717 |
#define OP_USED 0x2 /* opcode matching is used */
|
|
Packit |
577717 |
#define IR_USED 0x4 /* code range is used */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param == NULL) return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* if only pmc8/pmc9 opcode matching is used, we do not need to change
|
|
Packit |
577717 |
* the default value of pmc13 regardless of the events being measured.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if ( param->pfp_ita2_drange.rr_used == 0
|
|
Packit |
577717 |
&& param->pfp_ita2_irange.rr_used == 0) return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* it seems like the ignored bits need to have special values
|
|
Packit |
577717 |
* otherwise this does not work.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pmc13.pmc_val = 0x2078fefefefe;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* initialize iod codes
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
iod_codes[0] = iod_codes[1] = iod_codes[2] = iod_codes[3] = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* setup default iod value, we need to separate because
|
|
Packit |
577717 |
* if drange is used we do not know in advance which DBR will be used
|
|
Packit |
577717 |
* therefore we need to apply dfl_val later
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
dfl_val_pmc8 = param->pfp_ita2_pmc8.opcm_used ? OP_USED : 0;
|
|
Packit |
577717 |
dfl_val_pmc9 = param->pfp_ita2_pmc9.opcm_used ? OP_USED : 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param->pfp_ita2_drange.rr_used == 1) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (mod_out == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
irr = ¶m->pfp_ita2_drange;
|
|
Packit |
577717 |
orr = &mod_out->pfp_ita2_drange;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = check_intervals(irr, 1, &n_intervals);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (n_intervals < 1) return PFMLIB_ERR_DRRINVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = compute_normal_rr(irr, inp->pfp_dfl_plm, n_intervals, &base_idx, orr);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) {
|
|
Packit |
577717 |
return ret == PFMLIB_ERR_TOOMANY ? PFMLIB_ERR_DRRTOOMANY : ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Update iod_codes to reflect the use of the DBR constraint.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (i=0; i < orr->rr_nbr_used; i++) {
|
|
Packit |
577717 |
if (orr->rr_br[i].reg_num == 0) iod_codes[0] |= DR_USED | dfl_val_pmc8;
|
|
Packit |
577717 |
if (orr->rr_br[i].reg_num == 2) iod_codes[1] |= DR_USED | dfl_val_pmc9;
|
|
Packit |
577717 |
if (orr->rr_br[i].reg_num == 4) iod_codes[2] |= DR_USED | dfl_val_pmc8;
|
|
Packit |
577717 |
if (orr->rr_br[i].reg_num == 6) iod_codes[3] |= DR_USED | dfl_val_pmc9;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* XXX: assume dispatch_irange executed before calling this function
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (param->pfp_ita2_irange.rr_used == 1) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
orr2 = &mod_out->pfp_ita2_irange;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (mod_out == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we need to find out whether or not the irange is using
|
|
Packit |
577717 |
* fine mode. If this is the case, then we only need to
|
|
Packit |
577717 |
* program pmc13 for the ibr pairs which designate the lower
|
|
Packit |
577717 |
* bounds of a range. For instance, if IBRP0/IBRP2 are used,
|
|
Packit |
577717 |
* then we only need to program pmc13.cfg_dbrp0 and pmc13.ena_dbrp0,
|
|
Packit |
577717 |
* the PMU will automatically use IBRP2, even though pmc13.ena_dbrp2=0.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(i=0; i <= pos; i++) {
|
|
Packit |
577717 |
if (pc[i].reg_num == 14) {
|
|
Packit |
577717 |
pmc14.pmc_val = pc[i].reg_value;
|
|
Packit |
577717 |
if (pmc14.pmc14_ita2_reg.iarc_fine == 1) fine_mode = 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Update to reflect the use of the IBR constraint
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (i=0; i < orr2->rr_nbr_used; i++) {
|
|
Packit |
577717 |
if (orr2->rr_br[i].reg_num == 0) iod_codes[0] |= IR_USED | dfl_val_pmc8;
|
|
Packit |
577717 |
if (orr2->rr_br[i].reg_num == 2) iod_codes[1] |= IR_USED | dfl_val_pmc9;
|
|
Packit |
577717 |
if (fine_mode == 0 && orr2->rr_br[i].reg_num == 4) iod_codes[2] |= IR_USED | dfl_val_pmc8;
|
|
Packit |
577717 |
if (fine_mode == 0 && orr2->rr_br[i].reg_num == 6) iod_codes[3] |= IR_USED | dfl_val_pmc9;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param->pfp_ita2_irange.rr_used == 0 && param->pfp_ita2_drange.rr_used ==0) {
|
|
Packit |
577717 |
iod_codes[0] = iod_codes[2] = dfl_val_pmc8;
|
|
Packit |
577717 |
iod_codes[1] = iod_codes[3] = dfl_val_pmc9;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* update the cfg dbrpX field. If we put a constraint on a cfg dbrp, then
|
|
Packit |
577717 |
* we must enable it in the corresponding ena_dbrpX
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_ena_dbrp0 = iod_codes[0] ? 1 : 0;
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_cfg_dbrp0 = iod_tab[iod_codes[0]];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_ena_dbrp1 = iod_codes[1] ? 1 : 0;
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_cfg_dbrp1 = iod_tab[iod_codes[1]];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_ena_dbrp2 = iod_codes[2] ? 1 : 0;
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_cfg_dbrp2 = iod_tab[iod_codes[2]];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_ena_dbrp3 = iod_codes[3] ? 1 : 0;
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_cfg_dbrp3 = iod_tab[iod_codes[3]];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 13))
|
|
Packit |
577717 |
return PFMLIB_ERR_NOASSIGN;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pc[pos].reg_num = 13;
|
|
Packit |
577717 |
pc[pos].reg_value = pmc13.pmc_val;
|
|
Packit |
577717 |
pc[pos].reg_addr = pc[pos].reg_alt_addr = 13;
|
|
Packit |
577717 |
pos++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[PMC13(pmc13)=0x%lx cfg_dbrp0=%d cfg_dbrp1=%d cfg_dbrp2=%d cfg_dbrp3=%d ena_dbrp0=%d ena_dbrp1=%d ena_dbrp2=%d ena_dbrp3=%d]\n",
|
|
Packit |
577717 |
pmc13.pmc_val,
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_cfg_dbrp0,
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_cfg_dbrp1,
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_cfg_dbrp2,
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_cfg_dbrp3,
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_ena_dbrp0,
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_ena_dbrp1,
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_ena_dbrp2,
|
|
Packit |
577717 |
pmc13.pmc13_ita2_reg.darc_ena_dbrp3);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
outp->pfp_pmc_count = pos;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
check_qualifier_constraints(pfmlib_input_param_t *inp, pfmlib_ita2_input_param_t *mod_in)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t *param = mod_in;
|
|
Packit |
577717 |
pfmlib_event_t *e = inp->pfp_events;
|
|
Packit |
577717 |
unsigned int i, count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
count = inp->pfp_event_count;
|
|
Packit |
577717 |
for(i=0; i < count; i++) {
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* skip check for counter which requested it. Use at your own risk.
|
|
Packit |
577717 |
* No all counters have necessarily been validated for use with
|
|
Packit |
577717 |
* qualifiers. Typically the event is counted as if no constraint
|
|
Packit |
577717 |
* existed.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (param->pfp_ita2_counters[i].flags & PFMLIB_ITA2_FL_EVT_NO_QUALCHECK) continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (evt_use_irange(param) && has_iarr(e[i].event) == 0) return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
if (evt_use_drange(param) && has_darr(e[i].event) == 0) return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
if (evt_use_opcm(param) && has_opcm(e[i].event) == 0) return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
check_range_plm(pfmlib_input_param_t *inp, pfmlib_ita2_input_param_t *mod_in)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t *param = mod_in;
|
|
Packit |
577717 |
unsigned int i, count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param->pfp_ita2_drange.rr_used == 0 && param->pfp_ita2_irange.rr_used == 0) return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* range restriction applies to all events, therefore we must have a consistent
|
|
Packit |
577717 |
* set of plm and they must match the pfp_dfl_plm which is used to setup the debug
|
|
Packit |
577717 |
* registers
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
count = inp->pfp_event_count;
|
|
Packit |
577717 |
for(i=0; i < count; i++) {
|
|
Packit |
577717 |
if (inp->pfp_events[i].plm && inp->pfp_events[i].plm != inp->pfp_dfl_plm) return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_ita2_dispatch_events(pfmlib_input_param_t *inp, void *model_in, pfmlib_output_param_t *outp, void *model_out)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
pfmlib_ita2_input_param_t *mod_in = (pfmlib_ita2_input_param_t *)model_in;
|
|
Packit |
577717 |
pfmlib_ita2_output_param_t *mod_out = (pfmlib_ita2_output_param_t *)model_out;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* nothing will come out of this combination
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (mod_out && mod_in == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* check opcode match, range restriction qualifiers */
|
|
Packit |
577717 |
if (mod_in && check_qualifier_constraints(inp, mod_in) != PFMLIB_SUCCESS) return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* check for problems with raneg restriction and per-event plm */
|
|
Packit |
577717 |
if (mod_in && check_range_plm(inp, mod_in) != PFMLIB_SUCCESS) return PFMLIB_ERR_FEATCOMB;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_ita2_dispatch_counters(inp, mod_in, outp);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* now check for I-EAR */
|
|
Packit |
577717 |
ret = pfm_dispatch_iear(inp, mod_in, outp);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* now check for D-EAR */
|
|
Packit |
577717 |
ret = pfm_dispatch_dear(inp, mod_in, outp);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* XXX: must be done before dispatch_opcm() and dispatch_drange() */
|
|
Packit |
577717 |
ret = pfm_dispatch_irange(inp, mod_in, outp, mod_out);;
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_dispatch_drange(inp, mod_in, outp, mod_out);;
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* now check for Opcode matchers */
|
|
Packit |
577717 |
ret = pfm_dispatch_opcm(inp, mod_in, outp, mod_out);
|
|
Packit |
577717 |
if (ret != PFMLIB_SUCCESS) return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_dispatch_btb(inp, mod_in, outp);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* XXX: return value is also error code */
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_get_event_maxincr(unsigned int i, unsigned int *maxincr)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (i >= PME_ITA2_EVENT_COUNT || maxincr == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
*maxincr = itanium2_pe[i].pme_maxincr;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_is_ear(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return i < PME_ITA2_EVENT_COUNT && is_ear(i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_is_dear(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return i < PME_ITA2_EVENT_COUNT && is_dear(i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_is_dear_tlb(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return i < PME_ITA2_EVENT_COUNT && is_dear(i) && is_ear_tlb(i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_is_dear_cache(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return i < PME_ITA2_EVENT_COUNT && is_dear(i) && is_ear_cache(i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_is_dear_alat(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return i < PME_ITA2_EVENT_COUNT && is_ear_alat(i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_is_iear(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return i < PME_ITA2_EVENT_COUNT && is_iear(i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_is_iear_tlb(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return i < PME_ITA2_EVENT_COUNT && is_iear(i) && is_ear_tlb(i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_is_iear_cache(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return i < PME_ITA2_EVENT_COUNT && is_iear(i) && is_ear_cache(i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_is_btb(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return i < PME_ITA2_EVENT_COUNT && is_btb(i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_support_iarr(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return i < PME_ITA2_EVENT_COUNT && has_iarr(i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_support_darr(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return i < PME_ITA2_EVENT_COUNT && has_darr(i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_support_opcm(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return i < PME_ITA2_EVENT_COUNT && has_opcm(i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_get_ear_mode(unsigned int i, pfmlib_ita2_ear_mode_t *m)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_ita2_ear_mode_t r;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!is_ear(i) || m == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
r = PFMLIB_ITA2_EAR_TLB_MODE;
|
|
Packit |
577717 |
if (is_ear_tlb(i)) goto done;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
r = PFMLIB_ITA2_EAR_CACHE_MODE;
|
|
Packit |
577717 |
if (is_ear_cache(i)) goto done;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
r = PFMLIB_ITA2_EAR_ALAT_MODE;
|
|
Packit |
577717 |
if (is_ear_alat(i)) goto done;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
done:
|
|
Packit |
577717 |
*m = r;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_ita2_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)itanium2_pe[i].pme_code;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* This function is accessible directly to the user
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_get_event_umask(unsigned int i, unsigned long *umask)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (i >= PME_ITA2_EVENT_COUNT || umask == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
*umask = evt_umask(i);
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_get_event_group(unsigned int i, int *grp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (i >= PME_ITA2_EVENT_COUNT || grp == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
*grp = evt_grp(i);
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_get_event_set(unsigned int i, int *set)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (i >= PME_ITA2_EVENT_COUNT || set == NULL) return PFMLIB_ERR_INVAL;
|
|
Packit |
577717 |
*set = evt_set(i) == 0xf ? PFMLIB_ITA2_EVT_NO_SET : evt_set(i);
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* external interface */
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_ita2_irange_is_fine(pfmlib_output_param_t *outp, pfmlib_ita2_output_param_t *mod_out)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_ita2_output_param_t *param = mod_out;
|
|
Packit |
577717 |
pfm_ita2_pmc_reg_t reg;
|
|
Packit |
577717 |
unsigned int i, count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* some sanity checks */
|
|
Packit |
577717 |
if (outp == NULL || param == NULL) return 0;
|
|
Packit |
577717 |
if (outp->pfp_pmc_count >= PFMLIB_MAX_PMCS) return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (param->pfp_ita2_irange.rr_nbr_used == 0) return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we look for pmc14 as it contains the bit indicating if fine mode is used
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
count = outp->pfp_pmc_count;
|
|
Packit |
577717 |
for(i=0; i < count; i++) {
|
|
Packit |
577717 |
if (outp->pfp_pmcs[i].reg_num == 14) goto found;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
found:
|
|
Packit |
577717 |
reg.pmc_val = outp->pfp_pmcs[i].reg_value;
|
|
Packit |
577717 |
return reg.pmc14_ita2_reg.iarc_fine ? 1 : 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static char *
|
|
Packit |
577717 |
pfm_ita2_get_event_name(unsigned int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return itanium2_pe[i].pme_name;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_ita2_get_event_counters(unsigned int j, pfmlib_regmask_t *counters)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
unsigned long m;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(counters, 0, sizeof(*counters));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
m =itanium2_pe[j].pme_counters;
|
|
Packit |
577717 |
for(i=0; m ; i++, m>>=1) {
|
|
Packit |
577717 |
if (m & 0x1)
|
|
Packit |
577717 |
pfm_regmask_set(counters, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_ita2_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* all pmcs are contiguous */
|
|
Packit |
577717 |
for(i=0; i < PMU_ITA2_NUM_PMCS; i++)
|
|
Packit |
577717 |
pfm_regmask_set(impl_pmcs, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_ita2_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* all pmds are contiguous */
|
|
Packit |
577717 |
for(i=0; i < PMU_ITA2_NUM_PMDS; i++)
|
|
Packit |
577717 |
pfm_regmask_set(impl_pmds, i);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_ita2_get_impl_counters(pfmlib_regmask_t *impl_counters)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int i = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* counting pmds are contiguous */
|
|
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_ita2_get_hw_counter_width(unsigned int *width)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
*width = PMU_ITA2_COUNTER_WIDTH;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_ita2_get_event_description(unsigned int ev, char **str)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *s;
|
|
Packit |
577717 |
s = itanium2_pe[ev].pme_desc;
|
|
Packit |
577717 |
if (s) {
|
|
Packit |
577717 |
*str = strdup(s);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
*str = NULL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_ita2_get_cycle_event(pfmlib_event_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
e->event = PME_ITA2_CPU_CYCLES;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_ita2_get_inst_retired(pfmlib_event_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
e->event = PME_ITA2_IA64_INST_RETIRED;
|
|
Packit |
577717 |
return PFMLIB_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_pmu_support_t itanium2_support={
|
|
Packit |
577717 |
.pmu_name = "itanium2",
|
|
Packit |
577717 |
.pmu_type = PFMLIB_ITANIUM2_PMU,
|
|
Packit |
577717 |
.pme_count = PME_ITA2_EVENT_COUNT,
|
|
Packit |
577717 |
.pmc_count = PMU_ITA2_NUM_PMCS,
|
|
Packit |
577717 |
.pmd_count = PMU_ITA2_NUM_PMDS,
|
|
Packit |
577717 |
.num_cnt = PMU_ITA2_NUM_COUNTERS,
|
|
Packit |
577717 |
.get_event_code = pfm_ita2_get_event_code,
|
|
Packit |
577717 |
.get_event_name = pfm_ita2_get_event_name,
|
|
Packit |
577717 |
.get_event_counters = pfm_ita2_get_event_counters,
|
|
Packit |
577717 |
.dispatch_events = pfm_ita2_dispatch_events,
|
|
Packit |
577717 |
.pmu_detect = pfm_ita2_detect,
|
|
Packit |
577717 |
.get_impl_pmcs = pfm_ita2_get_impl_pmcs,
|
|
Packit |
577717 |
.get_impl_pmds = pfm_ita2_get_impl_pmds,
|
|
Packit |
577717 |
.get_impl_counters = pfm_ita2_get_impl_counters,
|
|
Packit |
577717 |
.get_hw_counter_width = pfm_ita2_get_hw_counter_width,
|
|
Packit |
577717 |
.get_event_desc = pfm_ita2_get_event_description,
|
|
Packit |
577717 |
.get_cycle_event = pfm_ita2_get_cycle_event,
|
|
Packit |
577717 |
.get_inst_retired_event = pfm_ita2_get_inst_retired
|
|
Packit |
577717 |
};
|