Blame src/libpfm4/lib/pfmlib_montecito.c

Packit 577717
/*
Packit 577717
 * pfmlib_montecito.c : support for the Dual-Core Itanium2 processor
Packit 577717
 *
Packit 577717
 * Copyright (c) 2005-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
#include <stdlib.h>
Packit 577717
Packit 577717
/* public headers */
Packit 577717
#include <perfmon/pfmlib_montecito.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_montecito_priv.h"	/* PMU private */
Packit 577717
#include "montecito_events.h"		/* PMU private */
Packit 577717
Packit 577717
#define is_ear(i)	event_is_ear(montecito_pe+(i))
Packit 577717
#define is_ear_tlb(i)	event_is_ear_tlb(montecito_pe+(i))
Packit 577717
#define is_ear_alat(i)	event_is_ear_alat(montecito_pe+(i))
Packit 577717
#define is_ear_cache(i)	event_is_ear_cache(montecito_pe+(i))
Packit 577717
#define is_iear(i)	event_is_iear(montecito_pe+(i))
Packit 577717
#define is_dear(i)	event_is_dear(montecito_pe+(i))
Packit 577717
#define is_etb(i)	event_is_etb(montecito_pe+(i))
Packit 577717
#define has_opcm(i)	event_opcm_ok(montecito_pe+(i))
Packit 577717
#define has_iarr(i)	event_iarr_ok(montecito_pe+(i))
Packit 577717
#define has_darr(i)	event_darr_ok(montecito_pe+(i))
Packit 577717
#define has_all(i)	event_all_ok(montecito_pe+(i))
Packit 577717
#define has_mesi(i)	event_mesi_ok(montecito_pe+(i))
Packit 577717
Packit 577717
#define evt_use_opcm(e)		((e)->pfp_mont_opcm1.opcm_used != 0 || (e)->pfp_mont_opcm2.opcm_used !=0)
Packit 577717
#define evt_use_irange(e)	((e)->pfp_mont_irange.rr_used)
Packit 577717
#define evt_use_drange(e)	((e)->pfp_mont_drange.rr_used)
Packit 577717
Packit 577717
#define evt_grp(e)	(int)montecito_pe[e].pme_qualifiers.pme_qual.pme_group
Packit 577717
#define evt_set(e)	(int)montecito_pe[e].pme_qualifiers.pme_qual.pme_set
Packit 577717
#define evt_umask(e)	montecito_pe[e].pme_umask
Packit 577717
#define evt_type(e)	(int)montecito_pe[e].pme_type
Packit 577717
#define evt_caf(e)	(int)montecito_pe[e].pme_caf
Packit 577717
Packit 577717
#define FINE_MODE_BOUNDARY_BITS	16
Packit 577717
#define FINE_MODE_MASK		~((1U<
Packit 577717
Packit 577717
/* let's define some handy shortcuts! */
Packit 577717
#define pmc_plm		pmc_mont_counter_reg.pmc_plm
Packit 577717
#define pmc_ev		pmc_mont_counter_reg.pmc_ev
Packit 577717
#define pmc_oi		pmc_mont_counter_reg.pmc_oi
Packit 577717
#define pmc_pm		pmc_mont_counter_reg.pmc_pm
Packit 577717
#define pmc_es		pmc_mont_counter_reg.pmc_es
Packit 577717
#define pmc_umask	pmc_mont_counter_reg.pmc_umask
Packit 577717
#define pmc_thres	pmc_mont_counter_reg.pmc_thres
Packit 577717
#define pmc_all		pmc_mont_counter_reg.pmc_all
Packit 577717
#define pmc_ism		pmc_mont_counter_reg.pmc_ism
Packit 577717
#define pmc_m		pmc_mont_counter_reg.pmc_m
Packit 577717
#define pmc_e		pmc_mont_counter_reg.pmc_e
Packit 577717
#define pmc_s		pmc_mont_counter_reg.pmc_s
Packit 577717
#define pmc_i		pmc_mont_counter_reg.pmc_i
Packit 577717
Packit 577717
#define UNEXISTING_SET	0xff
Packit 577717
Packit 577717
static char * pfm_mont_get_event_name(unsigned int i);
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
static int
Packit 577717
pfm_mont_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 == 0x20) {
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 L1D and L2D related events. Due to wire limitations,
Packit 577717
 * some caches events are separated into sets. There
Packit 577717
 * are 6 sets for the L1D cache group and 8 sets for L2D group.
Packit 577717
 * It is NOT possible to simultaneously measure events from
Packit 577717
 * differents sets for L1D. For instance, you cannot
Packit 577717
 * measure events from set0 and set1 in L1D cache group. The L2D
Packit 577717
 * group allows up to two different sets to be active at the same
Packit 577717
 * time. The first set is selected by the event in PMC4 and the second
Packit 577717
 * set by the event in PMC6. Once the set is selected for PMC4,
Packit 577717
 * the same set is locked for PMC5 and PMC8. Similarly, once the
Packit 577717
 * set is selected for PMC6, the same set is locked for PMC7 and 
Packit 577717
 * PMC9.
Packit 577717
 *
Packit 577717
 * This function verifies that only one set of L1D is selected
Packit 577717
 * and that no more than 2 sets are selected for L2D
Packit 577717
 */
Packit 577717
static int
Packit 577717
check_cross_groups(pfmlib_input_param_t *inp, unsigned int *l1d_event, 
Packit 577717
		unsigned long *l2d_set1_mask, unsigned long *l2d_set2_mask)
Packit 577717
{
Packit 577717
	int g, s, s1, s2;
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
	unsigned long l2d_mask1 = 0, l2d_mask2 = 0;
Packit 577717
	unsigned int l1d_event_idx = UNEXISTING_SET;
Packit 577717
Packit 577717
	/*
Packit 577717
	 * Let check the L1D constraint first
Packit 577717
	 *
Packit 577717
	 * There is no umask restriction for this group
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_MONT_EVT_L1D_CACHE_GRP) continue;
Packit 577717
		DPRINT("i=%u g=%d s=%d\n", i, g, s);
Packit 577717
		l1d_event_idx = i;
Packit 577717
		for (j=i+1; j < cnt; j++) {
Packit 577717
			if (evt_grp(e[j].event) != g) continue;
Packit 577717
			/*
Packit 577717
			 * if there is another event from the same group
Packit 577717
			 * but with a different set, then we return an error
Packit 577717
			 */
Packit 577717
			if (evt_set(e[j].event) != s) return PFMLIB_ERR_EVTSET;
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
	/*
Packit 577717
	 * Check that we have only up to two distinct 
Packit 577717
	 * sets for L2D
Packit 577717
	 */
Packit 577717
	s1 = s2 = -1;
Packit 577717
	for (i=0; i < cnt; i++) {
Packit 577717
		g = evt_grp(e[i].event);
Packit 577717
Packit 577717
		if (g != PFMLIB_MONT_EVT_L2D_CACHE_GRP) continue;
Packit 577717
Packit 577717
		s = evt_set(e[i].event); 
Packit 577717
Packit 577717
		/*
Packit 577717
		 * we have seen this set before, continue
Packit 577717
		 */
Packit 577717
		if (s1 == s) {
Packit 577717
			l2d_mask1 |= 1UL << i;
Packit 577717
			continue;
Packit 577717
		}
Packit 577717
		if (s2 == s) {
Packit 577717
			l2d_mask2 |= 1UL << i;
Packit 577717
			continue;
Packit 577717
		}
Packit 577717
		/*
Packit 577717
		 * record first of second set seen
Packit 577717
		 */
Packit 577717
		if (s1 == -1) {
Packit 577717
			s1 = s;
Packit 577717
			l2d_mask1 |= 1UL << i;
Packit 577717
		} else if (s2 == -1) {
Packit 577717
			s2 = s;
Packit 577717
			l2d_mask2 |= 1UL << i;
Packit 577717
		} else {
Packit 577717
			/* 
Packit 577717
			 * found a third set, that's not possible
Packit 577717
			 */
Packit 577717
			return PFMLIB_ERR_EVTSET;
Packit 577717
		}
Packit 577717
	}
Packit 577717
	*l1d_event     = l1d_event_idx;
Packit 577717
	*l2d_set1_mask = l2d_mask1;
Packit 577717
	*l2d_set2_mask = l2d_mask2;
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 used 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
 *
Packit 577717
 * Events which can be qualified by the two pairs depending on their tag:
Packit 577717
 * 	- ISB_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
static int prefetch_events[]={
Packit 577717
	PME_MONT_L1I_PREFETCHES,
Packit 577717
	PME_MONT_L1I_STRM_PREFETCHES,
Packit 577717
	PME_MONT_L2I_PREFETCHES
Packit 577717
};
Packit 577717
#define NPREFETCH_EVENTS	sizeof(prefetch_events)/sizeof(int)
Packit 577717
Packit 577717
static int prefetch_dual_events[]=
Packit 577717
{
Packit 577717
 PME_MONT_ISB_BUNPAIRS_IN,
Packit 577717
 PME_MONT_L1I_FETCH_RAB_HIT,
Packit 577717
 PME_MONT_L1I_FETCH_ISB_HIT,
Packit 577717
 PME_MONT_L1I_FILLS
Packit 577717
};
Packit 577717
#define NPREFETCH_DUAL_EVENTS	sizeof(prefetch_dual_events)/sizeof(int)
Packit 577717
Packit 577717
/*
Packit 577717
 * prefetch events must use IBRP1, unless they are dual and the user specified
Packit 577717
 * PFMLIB_MONT_IRR_DEMAND_FETCH in rr_flags
Packit 577717
 */
Packit 577717
static int
Packit 577717
check_prefetch_events(pfmlib_input_param_t *inp, pfmlib_mont_input_rr_t *irr, unsigned int *count, int *base_idx, int *dup)
Packit 577717
{
Packit 577717
	int code;
Packit 577717
	int prefetch_codes[NPREFETCH_EVENTS];
Packit 577717
	int prefetch_dual_codes[NPREFETCH_DUAL_EVENTS];
Packit 577717
	unsigned int i, j;
Packit 577717
	int c, flags;
Packit 577717
	int found = 0, found_ibrp0 = 0, found_ibrp1 = 0;
Packit 577717
Packit 577717
	flags = irr->rr_flags & (PFMLIB_MONT_IRR_DEMAND_FETCH|PFMLIB_MONT_IRR_PREFETCH_MATCH);
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
Packit 577717
	for(i=0; i < NPREFETCH_DUAL_EVENTS; i++) {
Packit 577717
		pfm_get_event_code(prefetch_dual_events[i], &code);
Packit 577717
		prefetch_dual_codes[i] = code;
Packit 577717
	}
Packit 577717
Packit 577717
	for(i=0; i < inp->pfp_event_count; i++) {
Packit 577717
		pfm_get_event_code(inp->pfp_events[i].event, &c);
Packit 577717
Packit 577717
		for(j=0; j < NPREFETCH_EVENTS; j++) {
Packit 577717
			if (c == prefetch_codes[j]) {
Packit 577717
				found++;
Packit 577717
				found_ibrp1++;
Packit 577717
			}
Packit 577717
		}
Packit 577717
		/*
Packit 577717
		 * for the dual events, users must specify one or both of the
Packit 577717
		 * PFMLIB_MONT_IRR_DEMAND_FETCH or PFMLIB_MONT_IRR_PREFETCH_MATCH
Packit 577717
		 */
Packit 577717
		for(j=0; j < NPREFETCH_DUAL_EVENTS; j++) {
Packit 577717
			if (c == prefetch_dual_codes[j]) {
Packit 577717
				found++;
Packit 577717
				if (flags == 0)
Packit 577717
					return PFMLIB_ERR_IRRFLAGS;
Packit 577717
				if (flags & PFMLIB_MONT_IRR_DEMAND_FETCH)
Packit 577717
					found_ibrp0++;
Packit 577717
				if (flags & PFMLIB_MONT_IRR_PREFETCH_MATCH)
Packit 577717
					found_ibrp1++;
Packit 577717
			}
Packit 577717
		}
Packit 577717
	}
Packit 577717
	*count =  found;
Packit 577717
	*dup   = 0;
Packit 577717
Packit 577717
	/*
Packit 577717
	 * if both found_ibrp0 and found_ibrp1 > 0, then we need to duplicate
Packit 577717
	 * the range in ibrp0 to ibrp1.
Packit 577717
	 */
Packit 577717
	if (found) {
Packit 577717
		*base_idx = found_ibrp0 ? 0 : 2;
Packit 577717
		if (found_ibrp1 && found_ibrp0)
Packit 577717
			*dup = 1;
Packit 577717
	}
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
/*
Packit 577717
 * look for CPU_OP_CYCLES_QUAL
Packit 577717
 * Return:
Packit 577717
 * 	1 if found
Packit 577717
 * 	0 otherwise
Packit 577717
 */
Packit 577717
static int
Packit 577717
has_cpu_cycles_qual(pfmlib_input_param_t *inp)
Packit 577717
{
Packit 577717
	unsigned int i;
Packit 577717
	int code, c;
Packit 577717
Packit 577717
	pfm_get_event_code(PME_MONT_CPU_OP_CYCLES_QUAL, &code);
Packit 577717
Packit 577717
	for(i=0; i < inp->pfp_event_count; i++) {
Packit 577717
		pfm_get_event_code(inp->pfp_events[i].event, &c);
Packit 577717
		if (c == code)
Packit 577717
			return 1;
Packit 577717
	}
Packit 577717
	return 0;
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 match the IA64_INST_RETIRED code
Packit 577717
 * 	- in retired_mask to 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;
Packit 577717
	unsigned int i, count, found = 0;
Packit 577717
	unsigned long umask, mask;
Packit 577717
Packit 577717
	pfm_get_event_code(PME_MONT_IA64_INST_RETIRED, &code);
Packit 577717
Packit 577717
	count = inp->pfp_event_count;
Packit 577717
	mask  = 0;
Packit 577717
	for(i=0; i < count; i++) {
Packit 577717
		pfm_get_event_code(inp->pfp_events[i].event, &c);
Packit 577717
		if (c == code)  {
Packit 577717
			pfm_mont_get_event_umask(inp->pfp_events[i].event, &umask);
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_mont_input_rr_t *rr, int n)
Packit 577717
{
Packit 577717
	pfmlib_mont_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_mont_input_rr_t *irr, int mode, unsigned int *n_intervals)
Packit 577717
{
Packit 577717
	unsigned int i;
Packit 577717
	pfmlib_mont_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
 * It is not possible to measure more than one of the
Packit 577717
 * L2D_OZQ_CANCELS0, L2D_OZQ_CANCELS1 at the same time.
Packit 577717
 */
Packit 577717
Packit 577717
static int cancel_events[]=
Packit 577717
{
Packit 577717
	PME_MONT_L2D_OZQ_CANCELS0_ACQ,
Packit 577717
	PME_MONT_L2D_OZQ_CANCELS1_ANY
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
 */
Packit 577717
static unsigned int l2d_set1_cnts[]={ 4, 5, 8 };
Packit 577717
static unsigned int l2d_set2_cnts[]={ 6, 7, 9 };
Packit 577717
Packit 577717
static int
Packit 577717
pfm_mont_dispatch_counters(pfmlib_input_param_t *inp, pfmlib_mont_input_param_t *mod_in, pfmlib_output_param_t *outp)
Packit 577717
{
Packit 577717
	pfmlib_mont_input_param_t *param = mod_in;
Packit 577717
	pfm_mont_pmc_reg_t reg;
Packit 577717
	pfmlib_event_t *e;
Packit 577717
	pfmlib_reg_t *pc, *pd;
Packit 577717
	pfmlib_regmask_t avail_cntrs, impl_cntrs;
Packit 577717
	unsigned int i,j, k, max_cnt;
Packit 577717
	unsigned int assign[PMU_MONT_NUM_COUNTERS];
Packit 577717
	unsigned int m, cnt;
Packit 577717
	unsigned int l1d_set;
Packit 577717
	unsigned long l2d_set1_mask, l2d_set2_mask, evt_mask, mesi;
Packit 577717
	unsigned long not_assigned_events, cnt_mask;
Packit 577717
	int l2d_set1_p, l2d_set2_p;
Packit 577717
	int ret;
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
Packit 577717
	if (PFMLIB_DEBUG())
Packit 577717
		for (m=0; m < cnt; m++) {
Packit 577717
			DPRINT("ev[%d]=%s counters=0x%lx\n", m, montecito_pe[e[m].event].pme_name,
Packit 577717
				montecito_pe[e[m].event].pme_counters);
Packit 577717
		}
Packit 577717
Packit 577717
	if (cnt > PMU_MONT_NUM_COUNTERS) return PFMLIB_ERR_TOOMANY;
Packit 577717
Packit 577717
	l1d_set = UNEXISTING_SET;
Packit 577717
	ret = check_cross_groups(inp, &l1d_set, &l2d_set1_mask, &l2d_set2_mask);
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
	/*
Packit 577717
	 * at this point, we know that:
Packit 577717
	 * 	- we have at most 1 L1D set
Packit 577717
	 * 	- we have at most 2 L2D sets
Packit 577717
	 * 	- cancel events are compatible
Packit 577717
	 */
Packit 577717
Packit 577717
	DPRINT("l1d_set=%u l2d_set1_mask=0x%lx l2d_set2_mask=0x%lx\n", l1d_set, l2d_set1_mask, l2d_set2_mask);
Packit 577717
Packit 577717
	/*
Packit 577717
	 * first, place L1D cache event in PMC5
Packit 577717
	 *
Packit 577717
	 * this is the strongest constraint
Packit 577717
	 */
Packit 577717
	pfm_get_impl_counters(&impl_cntrs);
Packit 577717
	pfm_regmask_andnot(&avail_cntrs, &impl_cntrs, &inp->pfp_unavail_pmcs);
Packit 577717
	not_assigned_events = 0;
Packit 577717
Packit 577717
	DPRINT("avail_cntrs=0x%lx\n", avail_cntrs.bits[0]);
Packit 577717
Packit 577717
	/*
Packit 577717
	 * we do not check ALL_THRD here because at least
Packit 577717
	 * one event has to be in PMC5 for this group
Packit 577717
	 */
Packit 577717
	if (l1d_set != UNEXISTING_SET) {
Packit 577717
Packit 577717
		if (!pfm_regmask_isset(&avail_cntrs, 5))
Packit 577717
			return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
		assign[l1d_set] = 5;
Packit 577717
Packit 577717
		pfm_regmask_clr(&avail_cntrs, 5);
Packit 577717
	}
Packit 577717
Packit 577717
	l2d_set1_p = l2d_set2_p = 0;
Packit 577717
Packit 577717
	/*
Packit 577717
	 * assign L2D set1 and set2 counters
Packit 577717
	 */
Packit 577717
	for (i=0; i < cnt ; i++) {
Packit 577717
			evt_mask = 1UL << i;
Packit 577717
			/*
Packit 577717
			 * place l2d set1 events. First 3 go to designated
Packit 577717
			 * counters, the rest is placed elsewhere in the final
Packit 577717
			 * pass
Packit 577717
			 */
Packit 577717
			if (l2d_set1_p < 3 && (l2d_set1_mask & evt_mask)) {
Packit 577717
				assign[i] = l2d_set1_cnts[l2d_set1_p];
Packit 577717
Packit 577717
				if (!pfm_regmask_isset(&avail_cntrs, assign[i]))
Packit 577717
					return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
				pfm_regmask_clr(&avail_cntrs, assign[i]);
Packit 577717
				l2d_set1_p++;
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
			/*
Packit 577717
			 * same as above but for l2d set2
Packit 577717
			 */
Packit 577717
			if (l2d_set2_p  < 3 && (l2d_set2_mask & evt_mask)) {
Packit 577717
				assign[i] = l2d_set2_cnts[l2d_set2_p];
Packit 577717
Packit 577717
				if (!pfm_regmask_isset(&avail_cntrs, assign[i]))
Packit 577717
					return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
				pfm_regmask_clr(&avail_cntrs, assign[i]);
Packit 577717
				l2d_set2_p++;
Packit 577717
				continue;
Packit 577717
			}
Packit 577717
			/*
Packit 577717
			 * if not l2d nor l1d, then defer placement until final pass
Packit 577717
			 */
Packit 577717
			if (i != l1d_set)
Packit 577717
				not_assigned_events |= evt_mask;
Packit 577717
Packit 577717
			DPRINT("phase 1: i=%u avail_cntrs=0x%lx l2d_set1_p=%d l2d_set2_p=%d not_assigned=0x%lx\n", 
Packit 577717
				i,
Packit 577717
				avail_cntrs.bits[0],
Packit 577717
				l2d_set1_p,
Packit 577717
				l2d_set2_p,
Packit 577717
				not_assigned_events);
Packit 577717
	}
Packit 577717
	/*
Packit 577717
	 * assign BUS_* ER_* events (work only in PMC4-PMC9)
Packit 577717
	 */
Packit 577717
	evt_mask = not_assigned_events;
Packit 577717
	for (i=0; evt_mask ; i++, evt_mask >>=1) {
Packit 577717
Packit 577717
		if ((evt_mask & 0x1) == 0)
Packit 577717
			continue;
Packit 577717
Packit 577717
		cnt_mask = montecito_pe[e[i].event].pme_counters;
Packit 577717
		/*
Packit 577717
		 * only interested in events with restricted set of counters
Packit 577717
		 */
Packit 577717
		if (cnt_mask == 0xfff0)
Packit 577717
			continue;
Packit 577717
Packit 577717
		for(j=0; cnt_mask; j++, cnt_mask >>=1) {
Packit 577717
			if ((cnt_mask & 0x1) == 0) 
Packit 577717
				continue;
Packit 577717
Packit 577717
			DPRINT("phase 2: i=%d j=%d cnt_mask=0x%lx avail_cntrs=0x%lx not_assigned_evnts=0x%lx\n",
Packit 577717
				i, j, cnt_mask, avail_cntrs.bits[0], not_assigned_events);
Packit 577717
Packit 577717
			if (!pfm_regmask_isset(&avail_cntrs, j))
Packit 577717
				continue;
Packit 577717
Packit 577717
			assign[i] = j;
Packit 577717
			not_assigned_events &= ~(1UL << i);
Packit 577717
			pfm_regmask_clr(&avail_cntrs, j);
Packit 577717
			break;
Packit 577717
		}
Packit 577717
		if (cnt_mask == 0)
Packit 577717
			return PFMLIB_ERR_NOASSIGN;
Packit 577717
	}
Packit 577717
	/*
Packit 577717
	 * assign the rest of the events (no constraints)
Packit 577717
	 */
Packit 577717
	evt_mask = not_assigned_events;
Packit 577717
	max_cnt = PMU_MONT_FIRST_COUNTER + PMU_MONT_NUM_COUNTERS;
Packit 577717
	for (i=0, j=0; evt_mask ; i++, evt_mask >>=1) {
Packit 577717
Packit 577717
		DPRINT("phase 3a: i=%d j=%d evt_mask=0x%lx avail_cntrs=0x%lx not_assigned_evnts=0x%lx\n",
Packit 577717
			i, j, evt_mask, avail_cntrs.bits[0], not_assigned_events);
Packit 577717
		if ((evt_mask & 0x1) == 0)
Packit 577717
			continue;
Packit 577717
Packit 577717
		while(j < max_cnt && !pfm_regmask_isset(&avail_cntrs, j)) {
Packit 577717
			DPRINT("phase 3: i=%d j=%d evt_mask=0x%lx avail_cntrs=0x%lx not_assigned_evnts=0x%lx\n",
Packit 577717
				i, j, evt_mask, avail_cntrs.bits[0], not_assigned_events);
Packit 577717
			j++;
Packit 577717
		}
Packit 577717
Packit 577717
		if (j == max_cnt)
Packit 577717
			return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
		assign[i] = j;
Packit 577717
		j++;
Packit 577717
	}
Packit 577717
Packit 577717
	for (j=0; j < cnt ; j++ ) {
Packit 577717
		mesi = 0;
Packit 577717
Packit 577717
		/*
Packit 577717
		 * XXX: we do not support .all placement just yet
Packit 577717
		 */
Packit 577717
		if (param && param->pfp_mont_counters[j].flags & PFMLIB_MONT_FL_EVT_ALL_THRD) {
Packit 577717
			DPRINT(".all mode is not yet supported by libpfm\n");
Packit 577717
			return PFMLIB_ERR_NOTSUPP;
Packit 577717
		}
Packit 577717
Packit 577717
		if (has_mesi(e[j].event)) {
Packit 577717
			for(k=0;k< e[j].num_masks; k++) {
Packit 577717
				mesi |= 1UL << e[j].unit_masks[k];
Packit 577717
			}
Packit 577717
			/* by default we capture everything */
Packit 577717
			if (mesi == 0)
Packit 577717
				mesi = 0xf;
Packit 577717
		}
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     = 0; /* let the user/OS deal with this field */
Packit 577717
		reg.pmc_pm     = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
Packit 577717
		reg.pmc_thres  = param ? param->pfp_mont_counters[j].thres: 0;
Packit 577717
		reg.pmc_ism    = 0x2; /* force IA-64 mode */
Packit 577717
		reg.pmc_umask  = is_ear(e[j].event) ? 0x0 : montecito_pe[e[j].event].pme_umask;
Packit 577717
		reg.pmc_es     = montecito_pe[e[j].event].pme_code;
Packit 577717
		reg.pmc_all    = 0; /* XXX force self for now */
Packit 577717
		reg.pmc_m      = (mesi>>3) & 0x1;
Packit 577717
		reg.pmc_e      = (mesi>>2) & 0x1;
Packit 577717
		reg.pmc_s      = (mesi>>1) & 0x1;
Packit 577717
		reg.pmc_i      =  mesi     & 0x1;
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 m=%d e=%d s=%d i=%d thres=%d all=%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_m,
Packit 577717
				reg.pmc_e,
Packit 577717
				reg.pmc_s,
Packit 577717
				reg.pmc_i,
Packit 577717
				reg.pmc_thres,
Packit 577717
				reg.pmc_all,
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
				montecito_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_mont_input_param_t *mod_in, pfmlib_output_param_t *outp)
Packit 577717
{
Packit 577717
	pfm_mont_pmc_reg_t reg;
Packit 577717
	pfmlib_mont_input_param_t *param = mod_in;
Packit 577717
	pfmlib_reg_t *pc, *pd;
Packit 577717
	pfmlib_mont_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_mont_iear.ear_used == 0) {
Packit 577717
Packit 577717
		/*
Packit 577717
		 * case 3: no I-EAR event, no (or nothing) in param->pfp_mont_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_mont_get_ear_mode(inp->pfp_events[i].event, &param->pfp_mont_iear.ear_mode);
Packit 577717
Packit 577717
		param->pfp_mont_iear.ear_umask = evt_umask(inp->pfp_events[i].event);
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_mont_iear.ear_mode == PFMLIB_MONT_EAR_TLB_MODE) {
Packit 577717
		/* if plm is 0, then assume not specified per-event and use default */
Packit 577717
		reg.pmc37_mont_tlb_reg.iear_plm     = param->pfp_mont_iear.ear_plm ? param->pfp_mont_iear.ear_plm : inp->pfp_dfl_plm;
Packit 577717
		reg.pmc37_mont_tlb_reg.iear_pm      = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
Packit 577717
		reg.pmc37_mont_tlb_reg.iear_ct      = 0x0;
Packit 577717
		reg.pmc37_mont_tlb_reg.iear_umask   = param->pfp_mont_iear.ear_umask;
Packit 577717
	} else if (param->pfp_mont_iear.ear_mode == PFMLIB_MONT_EAR_CACHE_MODE) {
Packit 577717
		/* if plm is 0, then assume not specified per-event and use default */
Packit 577717
		reg.pmc37_mont_cache_reg.iear_plm   = param->pfp_mont_iear.ear_plm ? param->pfp_mont_iear.ear_plm : inp->pfp_dfl_plm;
Packit 577717
		reg.pmc37_mont_cache_reg.iear_pm    = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
Packit 577717
		reg.pmc37_mont_cache_reg.iear_ct    = 0x1;
Packit 577717
		reg.pmc37_mont_cache_reg.iear_umask = param->pfp_mont_iear.ear_umask;
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
	if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 37))
Packit 577717
		return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
	pc[pos1].reg_num     = 37; /* PMC37 is I-EAR config register */
Packit 577717
	pc[pos1].reg_value   = reg.pmc_val;
Packit 577717
	pc[pos1].reg_addr  = pc[pos1].reg_addr = 37;
Packit 577717
	pos1++;
Packit 577717
Packit 577717
	pd[pos2].reg_num  = 34;
Packit 577717
	pd[pos2].reg_addr = pd[pos2].reg_alt_addr = 34; 
Packit 577717
	pos2++;
Packit 577717
	pd[pos2].reg_num  = 35;
Packit 577717
	pd[pos2].reg_addr = pd[pos2].reg_alt_addr = 35; 
Packit 577717
	pos2++;
Packit 577717
Packit 577717
	if (param->pfp_mont_iear.ear_mode == PFMLIB_MONT_EAR_TLB_MODE) {
Packit 577717
		__pfm_vbprintf("[PMC37(pmc37)=0x%lx ctb=tlb plm=%d pm=%d umask=0x%x]\n",
Packit 577717
			reg.pmc_val,
Packit 577717
			reg.pmc37_mont_tlb_reg.iear_plm,
Packit 577717
			reg.pmc37_mont_tlb_reg.iear_pm,
Packit 577717
			reg.pmc37_mont_tlb_reg.iear_umask);
Packit 577717
	} else {
Packit 577717
		__pfm_vbprintf("[PMC37(pmc37)=0x%lx ctb=cache plm=%d pm=%d umask=0x%x]\n",
Packit 577717
			reg.pmc_val,
Packit 577717
			reg.pmc37_mont_cache_reg.iear_plm,
Packit 577717
			reg.pmc37_mont_cache_reg.iear_pm,
Packit 577717
			reg.pmc37_mont_cache_reg.iear_umask);
Packit 577717
	}
Packit 577717
	__pfm_vbprintf("[PMD34(pmd34)]\n[PMD35(pmd35)\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_mont_input_param_t *mod_in, pfmlib_output_param_t *outp)
Packit 577717
{
Packit 577717
	pfm_mont_pmc_reg_t reg;
Packit 577717
	pfmlib_mont_input_param_t *param = mod_in;
Packit 577717
	pfmlib_reg_t *pc, *pd;
Packit 577717
	pfmlib_mont_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
Packit 577717
	count = inp->pfp_event_count;
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_mont_dear.ear_used == 0) {
Packit 577717
Packit 577717
		/*
Packit 577717
		 * case 3: no D-EAR event, no (or nothing) in param->pfp_mont_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_mont_get_ear_mode(inp->pfp_events[i].event, &param->pfp_mont_dear.ear_mode);
Packit 577717
Packit 577717
		param->pfp_mont_dear.ear_umask = evt_umask(inp->pfp_events[i].event);
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_mont_dear.ear_mode != PFMLIB_MONT_EAR_CACHE_MODE
Packit 577717
	    && param->pfp_mont_dear.ear_mode != PFMLIB_MONT_EAR_TLB_MODE
Packit 577717
	    && param->pfp_mont_dear.ear_mode != PFMLIB_MONT_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.pmc40_mont_reg.dear_plm   = param->pfp_mont_dear.ear_plm ? param->pfp_mont_dear.ear_plm : inp->pfp_dfl_plm;
Packit 577717
	reg.pmc40_mont_reg.dear_pm    = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
Packit 577717
	reg.pmc40_mont_reg.dear_mode  = param->pfp_mont_dear.ear_mode;
Packit 577717
	reg.pmc40_mont_reg.dear_umask = param->pfp_mont_dear.ear_umask;
Packit 577717
	reg.pmc40_mont_reg.dear_ism   = 0x2; /* force IA-64 mode */
Packit 577717
Packit 577717
	if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 40))
Packit 577717
		return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
	pc[pos1].reg_num     = 40;  /* 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 = 40;
Packit 577717
	pos1++;
Packit 577717
Packit 577717
	pd[pos2].reg_num  = 32;
Packit 577717
	pd[pos2].reg_addr = pd[pos2].reg_alt_addr = 32; 
Packit 577717
	pos2++;
Packit 577717
	pd[pos2].reg_num  = 33;
Packit 577717
	pd[pos2].reg_addr = pd[pos2].reg_alt_addr = 33; 
Packit 577717
	pos2++;
Packit 577717
	pd[pos2].reg_num  = 36;
Packit 577717
	pd[pos2].reg_addr = pd[pos2].reg_alt_addr = 36; 
Packit 577717
	pos2++;
Packit 577717
Packit 577717
	__pfm_vbprintf("[PMC40(pmc40)=0x%lx mode=%s plm=%d pm=%d ism=0x%x umask=0x%x]\n",
Packit 577717
			reg.pmc_val,
Packit 577717
			reg.pmc40_mont_reg.dear_mode == 0 ? "L1D" :
Packit 577717
			(reg.pmc40_mont_reg.dear_mode == 1 ? "L1DTLB" : "ALAT"),
Packit 577717
			reg.pmc40_mont_reg.dear_plm,	
Packit 577717
			reg.pmc40_mont_reg.dear_pm,
Packit 577717
			reg.pmc40_mont_reg.dear_ism,
Packit 577717
			reg.pmc40_mont_reg.dear_umask);
Packit 577717
	__pfm_vbprintf("[PMD32(pmd32)]\n[PMD33(pmd33)\nPMD36(pmd36)\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_opcm(pfmlib_input_param_t *inp, pfmlib_mont_input_param_t *mod_in, pfmlib_output_param_t *outp, pfmlib_mont_output_param_t *mod_out)
Packit 577717
{
Packit 577717
	pfmlib_mont_input_param_t *param = mod_in;
Packit 577717
	pfmlib_reg_t *pc = outp->pfp_pmcs;
Packit 577717
	pfm_mont_pmc_reg_t reg1, reg2, pmc36;
Packit 577717
	unsigned int i, has_1st_pair, has_2nd_pair, count;
Packit 577717
	unsigned int pos = outp->pfp_pmc_count;
Packit 577717
	int used_pmc32, used_pmc34;
Packit 577717
Packit 577717
	if (param == NULL) return PFMLIB_SUCCESS;
Packit 577717
Packit 577717
#define PMC36_DFL_VAL 0xfffffff0
Packit 577717
Packit 577717
Packit 577717
	/* 
Packit 577717
	 * mandatory default value for PMC36 as described in the documentation
Packit 577717
	 * all monitoring is opcode constrained. Better make sure the match/mask
Packit 577717
	 * is set to match everything! It looks weird for the default value!
Packit 577717
	 */
Packit 577717
	pmc36.pmc_val = PMC36_DFL_VAL;
Packit 577717
Packit 577717
	reg1.pmc_val = 0x030f01ffffffffff;
Packit 577717
	reg2.pmc_val = 0;
Packit 577717
Packit 577717
	used_pmc32 = param->pfp_mont_opcm1.opcm_used;
Packit 577717
	used_pmc34 = param->pfp_mont_opcm2.opcm_used;
Packit 577717
Packit 577717
	/*
Packit 577717
	 * check in any feature is used.
Packit 577717
	 * PMC36 must be setup when opcode matching is used OR when code range restriction is used
Packit 577717
	 */
Packit 577717
	if (used_pmc32 == 0 && used_pmc34 == 0 && param->pfp_mont_irange.rr_used == 0)
Packit 577717
		return 0;
Packit 577717
Packit 577717
	/*
Packit 577717
	 * check for rr_nbr_used to make sure that the range request produced something on output
Packit 577717
	 */
Packit 577717
	if (used_pmc32 || (param->pfp_mont_irange.rr_used && mod_out->pfp_mont_irange.rr_nbr_used) ) {
Packit 577717
		/*
Packit 577717
		 * if not used, ignore all bits
Packit 577717
		 */
Packit 577717
		if (used_pmc32) {
Packit 577717
			reg1.pmc32_34_mont_reg.opcm_mask  = param->pfp_mont_opcm1.opcm_mask;
Packit 577717
			reg1.pmc32_34_mont_reg.opcm_b     = param->pfp_mont_opcm1.opcm_b;
Packit 577717
			reg1.pmc32_34_mont_reg.opcm_f     = param->pfp_mont_opcm1.opcm_f;
Packit 577717
			reg1.pmc32_34_mont_reg.opcm_i     = param->pfp_mont_opcm1.opcm_i;
Packit 577717
			reg1.pmc32_34_mont_reg.opcm_m     = param->pfp_mont_opcm1.opcm_m;
Packit 577717
Packit 577717
			reg2.pmc33_35_mont_reg.opcm_match = param->pfp_mont_opcm1.opcm_match;
Packit 577717
		} 
Packit 577717
Packit 577717
		if (param->pfp_mont_irange.rr_used) {
Packit 577717
			reg1.pmc32_34_mont_reg.opcm_ig_ad = 0;
Packit 577717
			reg1.pmc32_34_mont_reg.opcm_inv   = param->pfp_mont_irange.rr_flags & PFMLIB_MONT_RR_INV ? 1 : 0;
Packit 577717
		} else {
Packit 577717
			/* clear range restriction fields when none is used */
Packit 577717
			reg1.pmc32_34_mont_reg.opcm_ig_ad = 1;
Packit 577717
			reg1.pmc32_34_mont_reg.opcm_inv   = 0;
Packit 577717
		}
Packit 577717
Packit 577717
		if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 32))
Packit 577717
			return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
		pc[pos].reg_num     = 32;
Packit 577717
		pc[pos].reg_value   = reg1.pmc_val;
Packit 577717
		pc[pos].reg_addr  = pc[pos].reg_alt_addr = 32;
Packit 577717
		pos++;
Packit 577717
Packit 577717
		/*
Packit 577717
		 * will be constrained by PMC32
Packit 577717
		 */
Packit 577717
		if (used_pmc32) {
Packit 577717
			if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 33))
Packit 577717
				return PFMLIB_ERR_NOASSIGN;
Packit 577717
			/*
Packit 577717
			 * used pmc33 only when we have active opcode matching
Packit 577717
			 */
Packit 577717
			pc[pos].reg_num     = 33;
Packit 577717
			pc[pos].reg_value   = reg2.pmc_val;
Packit 577717
			pc[pos].reg_addr  = pc[pos].reg_alt_addr = 33;
Packit 577717
			pos++;
Packit 577717
Packit 577717
			has_1st_pair = has_2nd_pair = 0;
Packit 577717
			count        = inp->pfp_event_count;
Packit 577717
Packit 577717
			for(i=0; i < count; i++) {
Packit 577717
				if (inp->pfp_events[i].event == PME_MONT_IA64_TAGGED_INST_RETIRED_IBRP0_PMC32_33) has_1st_pair=1;
Packit 577717
				if (inp->pfp_events[i].event == PME_MONT_IA64_TAGGED_INST_RETIRED_IBRP2_PMC32_33) has_2nd_pair=1;
Packit 577717
			}
Packit 577717
			if (has_1st_pair || has_2nd_pair == 0) pmc36.pmc36_mont_reg.opcm_ch0_ig_opcm = 0;
Packit 577717
			if (has_2nd_pair || has_1st_pair == 0) pmc36.pmc36_mont_reg.opcm_ch2_ig_opcm = 0;
Packit 577717
		}
Packit 577717
Packit 577717
		__pfm_vbprintf("[PMC32(pmc32)=0x%lx m=%d i=%d f=%d b=%d mask=0x%lx inv=%d ig_ad=%d]\n",
Packit 577717
				reg1.pmc_val,
Packit 577717
				reg1.pmc32_34_mont_reg.opcm_m,
Packit 577717
				reg1.pmc32_34_mont_reg.opcm_i,
Packit 577717
				reg1.pmc32_34_mont_reg.opcm_f,
Packit 577717
				reg1.pmc32_34_mont_reg.opcm_b,
Packit 577717
				reg1.pmc32_34_mont_reg.opcm_mask,
Packit 577717
				reg1.pmc32_34_mont_reg.opcm_inv,
Packit 577717
				reg1.pmc32_34_mont_reg.opcm_ig_ad);
Packit 577717
		if (used_pmc32)
Packit 577717
			__pfm_vbprintf("[PMC33(pmc33)=0x%lx match=0x%lx]\n",
Packit 577717
					reg2.pmc_val,
Packit 577717
					reg2.pmc33_35_mont_reg.opcm_match);
Packit 577717
	}
Packit 577717
Packit 577717
	/*
Packit 577717
	 * will be constrained by PMC34
Packit 577717
	 */
Packit 577717
	if (used_pmc34) {
Packit 577717
		reg1.pmc_val = 0x01ffffffffff; /* pmc34 default value */
Packit 577717
		reg2.pmc_val = 0;
Packit 577717
Packit 577717
		reg1.pmc32_34_mont_reg.opcm_mask  = param->pfp_mont_opcm2.opcm_mask;
Packit 577717
		reg1.pmc32_34_mont_reg.opcm_b     = param->pfp_mont_opcm2.opcm_b;
Packit 577717
		reg1.pmc32_34_mont_reg.opcm_f     = param->pfp_mont_opcm2.opcm_f;
Packit 577717
		reg1.pmc32_34_mont_reg.opcm_i     = param->pfp_mont_opcm2.opcm_i;
Packit 577717
		reg1.pmc32_34_mont_reg.opcm_m     = param->pfp_mont_opcm2.opcm_m;
Packit 577717
Packit 577717
		reg2.pmc33_35_mont_reg.opcm_match = param->pfp_mont_opcm2.opcm_match;
Packit 577717
Packit 577717
		if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 34))
Packit 577717
			return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
		if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 35))
Packit 577717
			return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
		pc[pos].reg_num     = 34;
Packit 577717
		pc[pos].reg_value   = reg1.pmc_val;
Packit 577717
		pc[pos].reg_addr    = pc[pos].reg_alt_addr = 34;
Packit 577717
		pos++;
Packit 577717
		pc[pos].reg_num     = 35;
Packit 577717
		pc[pos].reg_value   = reg2.pmc_val;
Packit 577717
		pc[pos].reg_addr    = pc[pos].reg_alt_addr = 35;
Packit 577717
		pos++;
Packit 577717
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_MONT_IA64_TAGGED_INST_RETIRED_IBRP1_PMC34_35) has_1st_pair=1;
Packit 577717
			if (inp->pfp_events[i].event == PME_MONT_IA64_TAGGED_INST_RETIRED_IBRP3_PMC34_35) has_2nd_pair=1;
Packit 577717
		}
Packit 577717
		if (has_1st_pair || has_2nd_pair == 0) pmc36.pmc36_mont_reg.opcm_ch1_ig_opcm = 0;
Packit 577717
		if (has_2nd_pair || has_1st_pair == 0) pmc36.pmc36_mont_reg.opcm_ch3_ig_opcm = 0;
Packit 577717
Packit 577717
		__pfm_vbprintf("[PMC34(pmc34)=0x%lx m=%d i=%d f=%d b=%d mask=0x%lx]\n",
Packit 577717
				reg1.pmc_val,
Packit 577717
				reg1.pmc32_34_mont_reg.opcm_m,
Packit 577717
				reg1.pmc32_34_mont_reg.opcm_i,
Packit 577717
				reg1.pmc32_34_mont_reg.opcm_f,
Packit 577717
				reg1.pmc32_34_mont_reg.opcm_b,
Packit 577717
				reg1.pmc32_34_mont_reg.opcm_mask);
Packit 577717
Packit 577717
		__pfm_vbprintf("[PMC35(pmc35)=0x%lx match=0x%lx]\n",
Packit 577717
				reg2.pmc_val,
Packit 577717
				reg2.pmc33_35_mont_reg.opcm_match);
Packit 577717
Packit 577717
	}
Packit 577717
	if (pmc36.pmc_val != PMC36_DFL_VAL) {
Packit 577717
Packit 577717
		if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 36))
Packit 577717
			return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
		pc[pos].reg_num     = 36;
Packit 577717
		pc[pos].reg_value   = pmc36.pmc_val;
Packit 577717
		pc[pos].reg_addr  = pc[pos].reg_alt_addr = 36;
Packit 577717
		pos++;
Packit 577717
Packit 577717
		__pfm_vbprintf("[PMC36(pmc36)=0x%lx ch0_ig_op=%d ch1_ig_op=%d ch2_ig_op=%d ch3_ig_op=%d]\n",
Packit 577717
				pmc36.pmc_val,
Packit 577717
				pmc36.pmc36_mont_reg.opcm_ch0_ig_opcm,
Packit 577717
				pmc36.pmc36_mont_reg.opcm_ch1_ig_opcm,
Packit 577717
				pmc36.pmc36_mont_reg.opcm_ch2_ig_opcm,
Packit 577717
				pmc36.pmc36_mont_reg.opcm_ch3_ig_opcm);
Packit 577717
	}
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
pfm_dispatch_etb(pfmlib_input_param_t *inp, pfmlib_mont_input_param_t *mod_in, pfmlib_output_param_t *outp)
Packit 577717
{
Packit 577717
	pfmlib_event_t *e= inp->pfp_events;
Packit 577717
	pfm_mont_pmc_reg_t reg;
Packit 577717
	pfmlib_mont_input_param_t *param = mod_in;
Packit 577717
	pfmlib_reg_t *pc, *pd;
Packit 577717
	pfmlib_mont_input_param_t fake_param;
Packit 577717
	int found_etb = 0, found_bad_dear = 0;
Packit 577717
	int has_etb_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
	 * explicit ETB settings
Packit 577717
	 */
Packit 577717
	has_etb_param = param && param->pfp_mont_etb.etb_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
	 * In this case PMC39 must be forced to zero
Packit 577717
	 */
Packit 577717
	count = inp->pfp_event_count;
Packit 577717
	for (i=0; i < count; i++) {
Packit 577717
Packit 577717
		if (is_etb(e[i].event)) found_etb = 1;
Packit 577717
Packit 577717
		/*
Packit 577717
		 * keep track of the first ETB 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_etb=%d found_bar_dear=%d\n", found_etb, 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_mont_dear.ear_used == 1) {
Packit 577717
		if (   param->pfp_mont_dear.ear_mode == PFMLIB_MONT_EAR_TLB_MODE
Packit 577717
		    || param->pfp_mont_dear.ear_mode == PFMLIB_MONT_EAR_ALAT_MODE)
Packit 577717
			found_bad_dear = 1;
Packit 577717
	}
Packit 577717
Packit 577717
	/*
Packit 577717
	 * no explicit ETB event and no special case to deal with (cover part of case 3)
Packit 577717
	 */
Packit 577717
	if (found_etb == 0 && has_etb_param == 0 && found_bad_dear == 0) return PFMLIB_SUCCESS;
Packit 577717
Packit 577717
	if (has_etb_param == 0) {
Packit 577717
Packit 577717
		/*
Packit 577717
		 * case 3: no ETB event, etb_used=0 but found_bad_dear=1, need to cleanup PMC12
Packit 577717
		 */
Packit 577717
		 if (found_etb == 0) goto assign_zero;
Packit 577717
Packit 577717
		/*
Packit 577717
		 * case 1: we have a ETB 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_mont_etb.etb_tm  = 0x3; 	/* all branches */
Packit 577717
		param->pfp_mont_etb.etb_ptm = 0x3; 	/* all branches */
Packit 577717
		param->pfp_mont_etb.etb_ppm = 0x3; 	/* all branches */
Packit 577717
		param->pfp_mont_etb.etb_brt = 0x0; 	/* all branches */
Packit 577717
Packit 577717
		DPRINT("ETB event with no info\n");
Packit 577717
	}
Packit 577717
Packit 577717
	/*
Packit 577717
	 * case 2: ETB event in the list, param provided
Packit 577717
	 * case 4: no ETB event, param provided (free running mode)
Packit 577717
	 */
Packit 577717
	reg.pmc39_mont_reg.etbc_plm = param->pfp_mont_etb.etb_plm ? param->pfp_mont_etb.etb_plm : inp->pfp_dfl_plm;
Packit 577717
	reg.pmc39_mont_reg.etbc_pm  = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
Packit 577717
	reg.pmc39_mont_reg.etbc_ds  = 0; /* 1 is reserved */
Packit 577717
	reg.pmc39_mont_reg.etbc_tm  = param->pfp_mont_etb.etb_tm & 0x3;
Packit 577717
	reg.pmc39_mont_reg.etbc_ptm = param->pfp_mont_etb.etb_ptm & 0x3;
Packit 577717
	reg.pmc39_mont_reg.etbc_ppm = param->pfp_mont_etb.etb_ppm & 0x3;
Packit 577717
	reg.pmc39_mont_reg.etbc_brt = param->pfp_mont_etb.etb_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 ETB 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, 39))
Packit 577717
		return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
	pc[pos1].reg_num     = 39;
Packit 577717
	pc[pos1].reg_value   = reg.pmc_val;
Packit 577717
	pc[pos1].reg_addr    = pc[pos1].reg_alt_addr = 39;
Packit 577717
	pos1++;
Packit 577717
Packit 577717
	__pfm_vbprintf("[PMC39(pmc39)=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.pmc39_mont_reg.etbc_plm,
Packit 577717
				reg.pmc39_mont_reg.etbc_pm,
Packit 577717
				reg.pmc39_mont_reg.etbc_ds,
Packit 577717
				reg.pmc39_mont_reg.etbc_tm,
Packit 577717
				reg.pmc39_mont_reg.etbc_ptm,
Packit 577717
				reg.pmc39_mont_reg.etbc_ppm,
Packit 577717
				reg.pmc39_mont_reg.etbc_brt);
Packit 577717
Packit 577717
	/*
Packit 577717
	 * only add ETB PMDs when actually using BTB.
Packit 577717
	 * Not needed when dealing with D-EAR TLB and DEAR-ALAT
Packit 577717
	 * PMC39 restriction
Packit 577717
	 */
Packit 577717
	if (found_etb || has_etb_param) {
Packit 577717
		pd[pos2].reg_num = 38;
Packit 577717
		pd[pos2].reg_addr = pd[pos2].reg_alt_addr = 38;
Packit 577717
		pos2++;
Packit 577717
		pd[pos2].reg_num = 39;
Packit 577717
		pd[pos2].reg_addr = pd[pos2].reg_alt_addr  = 39;
Packit 577717
		pos2++;
Packit 577717
		__pfm_vbprintf("[PMD38(pmd38)]\n[PMD39(pmd39)\n");
Packit 577717
Packit 577717
Packit 577717
		for(i=48; i < 64; 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
	/* 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_mont_input_rr_desc_t *in_rr, pfmlib_mont_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_MONT_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
 * base_idx = base register index to use (for IBRP1, base_idx = 2)
Packit 577717
 */
Packit 577717
static int
Packit 577717
compute_fine_rr(pfmlib_mont_input_rr_t *irr, int dfl_plm, int n, int *base_idx, pfmlib_mont_output_rr_t *orr)
Packit 577717
{
Packit 577717
	int i;
Packit 577717
	pfmlib_reg_t *br;
Packit 577717
	pfmlib_mont_input_rr_desc_t *in_rr;
Packit 577717
	pfmlib_mont_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 can only see addresses on a 2-bundle boundary, we must align 
Packit 577717
		 * down to the closest bundle-pair aligned address. 5 => 32-byte aligned address
Packit 577717
		 */
Packit 577717
		addr            = ALIGN_DOWN(in_rr->rr_start, 5);
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 = 1+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 = 1+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 ((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 = 1+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 = 1+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_mont_input_rr_t *irr, int dfl_plm, int *base_idx, pfmlib_mont_output_rr_t *orr)
Packit 577717
{
Packit 577717
	unsigned long size, end, start;
Packit 577717
	unsigned long p_start, p_end;
Packit 577717
	pfmlib_mont_input_rr_desc_t *in_rr;
Packit 577717
	pfmlib_mont_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 = 1+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 = 1+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_mont_input_rr_t *irr, int dfl_plm, int n, int *base_idx, pfmlib_mont_output_rr_t *orr)
Packit 577717
{
Packit 577717
	pfmlib_mont_input_rr_desc_t *in_rr;
Packit 577717
	pfmlib_mont_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
				&reg_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_mont_input_param_t *mod_in, pfmlib_output_param_t *outp, pfmlib_mont_output_param_t *mod_out)
Packit 577717
{
Packit 577717
	pfm_mont_pmc_reg_t reg;
Packit 577717
	pfmlib_mont_input_param_t *param = mod_in;
Packit 577717
	pfmlib_mont_input_rr_t *irr;
Packit 577717
	pfmlib_mont_output_rr_t *orr;
Packit 577717
	pfmlib_reg_t *pc = outp->pfp_pmcs;
Packit 577717
	unsigned long retired_mask;
Packit 577717
	unsigned int i, pos = outp->pfp_pmc_count, count;
Packit 577717
	unsigned int retired_only, retired_count, fine_mode, prefetch_count;
Packit 577717
	unsigned int n_intervals;
Packit 577717
	int base_idx = 0, dup = 0;
Packit 577717
	int ret;
Packit 577717
Packit 577717
	if (param == NULL) return PFMLIB_SUCCESS;
Packit 577717
Packit 577717
	if (param->pfp_mont_irange.rr_used == 0) return PFMLIB_SUCCESS;
Packit 577717
Packit 577717
	if (mod_out == NULL) return PFMLIB_ERR_INVAL;
Packit 577717
Packit 577717
	irr = &param->pfp_mont_irange;
Packit 577717
	orr = &mod_out->pfp_mont_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
Packit 577717
	retired_count  = check_inst_retired_events(inp, &retired_mask);
Packit 577717
	retired_only   = retired_count == inp->pfp_event_count;
Packit 577717
	fine_mode      = irr->rr_flags & PFMLIB_MONT_RR_NO_FINE_MODE ?
Packit 577717
		         0 : check_fine_mode_possible(irr, n_intervals);
Packit 577717
Packit 577717
Packit 577717
	DPRINT("n_intervals=%d retired_only=%d retired_count=%d fine_mode=%d\n",
Packit 577717
		n_intervals, retired_only, retired_count, fine_mode);
Packit 577717
	/*
Packit 577717
	 * On montecito, 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. The boundaries of the range must be in the
Packit 577717
	 *   same 64KB page. 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 64KB 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 the requested range. 
Packit 577717
	 *   You can determine the amount of overrun in either direction for each range by looking at 
Packit 577717
	 *   the rr_soff (start offset) and rr_eoff (end offset).
Packit 577717
	 *
Packit 577717
	 * - if the events include certain prefetch events then only IBRP1 can be used.
Packit 577717
	 *   See 3.3.5.2 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). But the corresponding 
Packit 577717
	 *   IA64_TAGGED_INST_RETIRED_* must be present.
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
	ret = check_prefetch_events(inp, irr, &prefetch_count, &base_idx, &dup;;
Packit 577717
	if (ret)
Packit 577717
		return ret;
Packit 577717
Packit 577717
	DPRINT("prefetch_count=%u base_idx=%d dup=%d\n", prefetch_count, base_idx, dup);
Packit 577717
Packit 577717
	/*
Packit 577717
	 * CPU_OP_CYCLES.QUAL supports code range restrictions but it returns
Packit 577717
	 * meaningful values (fine/coarse mode) only when IBRP1 is not used. 
Packit 577717
	 */
Packit 577717
	if ((base_idx > 0 || dup) && has_cpu_cycles_qual(inp))
Packit 577717
		return PFMLIB_ERR_FEATCOMB;
Packit 577717
Packit 577717
	if (fine_mode == 0) {
Packit 577717
		if (retired_only) {
Packit 577717
			/* can take multiple intervals */
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+retired_count) != inp->pfp_event_count)
Packit 577717
				return PFMLIB_ERR_FEATCOMB;
Packit 577717
Packit 577717
			ret = compute_single_rr(irr, inp->pfp_dfl_plm, &base_idx, orr);
Packit 577717
			if (ret == PFMLIB_SUCCESS && dup)
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
		/* except is retired_only, can take only one interval */
Packit 577717
		ret = compute_fine_rr(irr, inp->pfp_dfl_plm, n_intervals, &base_idx, orr);
Packit 577717
Packit 577717
		if (ret == PFMLIB_SUCCESS && dup)
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
	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.pmc38_mont_reg.iarc_ig_ibrp0 = 0;
Packit 577717
				break;
Packit 577717
			case 2:
Packit 577717
				reg.pmc38_mont_reg.iarc_ig_ibrp1 = 0;
Packit 577717
				break;
Packit 577717
			case 4: 
Packit 577717
				reg.pmc38_mont_reg.iarc_ig_ibrp2 = 0;
Packit 577717
				break;
Packit 577717
			case 6:
Packit 577717
				reg.pmc38_mont_reg.iarc_ig_ibrp3 = 0;
Packit 577717
				break;
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
	if (fine_mode) {
Packit 577717
		reg.pmc38_mont_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.pmc38_mont_reg.iarc_ig_ibrp0 == 0) return PFMLIB_ERR_IRRINVAL;
Packit 577717
		if ((retired_mask & 0x2) == 0 &&  reg.pmc38_mont_reg.iarc_ig_ibrp1 == 0) return PFMLIB_ERR_IRRINVAL;
Packit 577717
		if ((retired_mask & 0x4) == 0 &&  reg.pmc38_mont_reg.iarc_ig_ibrp2 == 0) return PFMLIB_ERR_IRRINVAL;
Packit 577717
		if ((retired_mask & 0x8) == 0 &&  reg.pmc38_mont_reg.iarc_ig_ibrp3 == 0) return PFMLIB_ERR_IRRINVAL;
Packit 577717
	}
Packit 577717
Packit 577717
	if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 38))
Packit 577717
		return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
	pc[pos].reg_num     = 38;
Packit 577717
	pc[pos].reg_value   = reg.pmc_val;
Packit 577717
	pc[pos].reg_addr    = pc[pos].reg_alt_addr = 38;
Packit 577717
	pos++;
Packit 577717
Packit 577717
	__pfm_vbprintf("[PMC38(pmc38)=0x%lx ig_ibrp0=%d ig_ibrp1=%d ig_ibrp2=%d ig_ibrp3=%d fine=%d]\n",
Packit 577717
			reg.pmc_val,
Packit 577717
			reg.pmc38_mont_reg.iarc_ig_ibrp0,
Packit 577717
			reg.pmc38_mont_reg.iarc_ig_ibrp1,
Packit 577717
			reg.pmc38_mont_reg.iarc_ig_ibrp2,
Packit 577717
			reg.pmc38_mont_reg.iarc_ig_ibrp3,
Packit 577717
			reg.pmc38_mont_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 pmc41.
Packit 577717
 */
Packit 577717
static int
Packit 577717
pfm_dispatch_drange(pfmlib_input_param_t *inp, pfmlib_mont_input_param_t *mod_in, pfmlib_output_param_t *outp, pfmlib_mont_output_param_t *mod_out)
Packit 577717
{
Packit 577717
	pfmlib_mont_input_param_t *param = mod_in;
Packit 577717
	pfmlib_reg_t *pc = outp->pfp_pmcs;
Packit 577717
	pfmlib_mont_input_rr_t *irr;
Packit 577717
	pfmlib_mont_output_rr_t *orr, *orr2;
Packit 577717
	pfm_mont_pmc_reg_t pmc38;
Packit 577717
	pfm_mont_pmc_reg_t reg;
Packit 577717
	unsigned int i, pos = outp->pfp_pmc_count;
Packit 577717
	int iod_codes[4], dfl_val_pmc32, dfl_val_pmc34;
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 pmc32/pmc33 opcode matching is used, we do not need to change
Packit 577717
	 * the default value of pmc41 regardless of the events being measured.
Packit 577717
	 */
Packit 577717
	if (  param->pfp_mont_drange.rr_used == 0
Packit 577717
	   && param->pfp_mont_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
	reg.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_pmc32 = param->pfp_mont_opcm1.opcm_used ? OP_USED : 0;
Packit 577717
	dfl_val_pmc34 = param->pfp_mont_opcm2.opcm_used ? OP_USED : 0;
Packit 577717
Packit 577717
	if (param->pfp_mont_drange.rr_used == 1) {
Packit 577717
Packit 577717
		if (mod_out == NULL) return PFMLIB_ERR_INVAL;
Packit 577717
Packit 577717
		irr = &param->pfp_mont_drange;
Packit 577717
		orr = &mod_out->pfp_mont_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_pmc32;
Packit 577717
			if (orr->rr_br[i].reg_num == 2) iod_codes[1] |= DR_USED | dfl_val_pmc34;
Packit 577717
			if (orr->rr_br[i].reg_num == 4) iod_codes[2] |= DR_USED | dfl_val_pmc32;
Packit 577717
			if (orr->rr_br[i].reg_num == 6) iod_codes[3] |= DR_USED | dfl_val_pmc34;
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_mont_irange.rr_used == 1) {
Packit 577717
Packit 577717
		orr2 = &mod_out->pfp_mont_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 pmc41 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 == 38) {
Packit 577717
				pmc38.pmc_val = pc[i].reg_value;
Packit 577717
				if (pmc38.pmc38_mont_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_pmc32;
Packit 577717
			if (orr2->rr_br[i].reg_num == 2) iod_codes[1] |= IR_USED | dfl_val_pmc34;
Packit 577717
			if (fine_mode == 0 && orr2->rr_br[i].reg_num == 4) iod_codes[2] |= IR_USED | dfl_val_pmc32;
Packit 577717
			if (fine_mode == 0 && orr2->rr_br[i].reg_num == 6) iod_codes[3] |= IR_USED | dfl_val_pmc34;
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
	if (param->pfp_mont_irange.rr_used == 0 && param->pfp_mont_drange.rr_used ==0) {
Packit 577717
		iod_codes[0] = iod_codes[2] = dfl_val_pmc32;
Packit 577717
		iod_codes[1] = iod_codes[3] = dfl_val_pmc34;
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
	reg.pmc41_mont_reg.darc_ena_dbrp0 = iod_codes[0] ? 1 : 0;
Packit 577717
	reg.pmc41_mont_reg.darc_cfg_dtag0 = iod_tab[iod_codes[0]];
Packit 577717
Packit 577717
	reg.pmc41_mont_reg.darc_ena_dbrp1 = iod_codes[1] ? 1 : 0;
Packit 577717
	reg.pmc41_mont_reg.darc_cfg_dtag1 = iod_tab[iod_codes[1]];
Packit 577717
Packit 577717
	reg.pmc41_mont_reg.darc_ena_dbrp2 = iod_codes[2] ? 1 : 0;
Packit 577717
	reg.pmc41_mont_reg.darc_cfg_dtag2 = iod_tab[iod_codes[2]];
Packit 577717
Packit 577717
	reg.pmc41_mont_reg.darc_ena_dbrp3 = iod_codes[3] ? 1 : 0;
Packit 577717
	reg.pmc41_mont_reg.darc_cfg_dtag3 = iod_tab[iod_codes[3]];
Packit 577717
Packit 577717
	if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 41))
Packit 577717
		return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
	pc[pos].reg_num     = 41;
Packit 577717
	pc[pos].reg_value   = reg.pmc_val;
Packit 577717
	pc[pos].reg_addr    = pc[pos].reg_alt_addr = 41;
Packit 577717
	pos++;
Packit 577717
Packit 577717
	__pfm_vbprintf("[PMC41(pmc41)=0x%lx cfg_dtag0=%d cfg_dtag1=%d cfg_dtag2=%d cfg_dtag3=%d ena_dbrp0=%d ena_dbrp1=%d ena_dbrp2=%d ena_dbrp3=%d]\n",
Packit 577717
			reg.pmc_val,
Packit 577717
			reg.pmc41_mont_reg.darc_cfg_dtag0,
Packit 577717
			reg.pmc41_mont_reg.darc_cfg_dtag1,
Packit 577717
			reg.pmc41_mont_reg.darc_cfg_dtag2,
Packit 577717
			reg.pmc41_mont_reg.darc_cfg_dtag3,
Packit 577717
			reg.pmc41_mont_reg.darc_ena_dbrp0,
Packit 577717
			reg.pmc41_mont_reg.darc_ena_dbrp1,
Packit 577717
			reg.pmc41_mont_reg.darc_ena_dbrp2,
Packit 577717
			reg.pmc41_mont_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_mont_input_param_t *mod_in)
Packit 577717
{
Packit 577717
	pfmlib_mont_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_mont_counters[i].flags & PFMLIB_MONT_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_mont_input_param_t *mod_in)
Packit 577717
{
Packit 577717
	pfmlib_mont_input_param_t *param = mod_in;
Packit 577717
	unsigned int i, count;
Packit 577717
Packit 577717
	if (param->pfp_mont_drange.rr_used == 0 && param->pfp_mont_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
static int
Packit 577717
pfm_dispatch_ipear(pfmlib_input_param_t *inp, pfmlib_mont_input_param_t *mod_in, pfmlib_output_param_t *outp)
Packit 577717
{
Packit 577717
	pfm_mont_pmc_reg_t reg;
Packit 577717
	pfmlib_mont_input_param_t *param = mod_in;
Packit 577717
	pfmlib_event_t *e = inp->pfp_events;
Packit 577717
	pfmlib_reg_t *pc, *pd;
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
	/*
Packit 577717
	 * check if there is something to do
Packit 577717
	 */
Packit 577717
	if (param == NULL || param->pfp_mont_ipear.ipear_used == 0) return PFMLIB_SUCCESS;
Packit 577717
Packit 577717
	/*
Packit 577717
	 * we need to look for use of ETB, because IP-EAR and ETB cannot be used at the
Packit 577717
	 * same time
Packit 577717
	 */
Packit 577717
	if (param->pfp_mont_etb.etb_used) return PFMLIB_ERR_FEATCOMB;
Packit 577717
Packit 577717
	/*
Packit 577717
	 * look for implicit ETB used because of BRANCH_EVENT
Packit 577717
	 */
Packit 577717
	count = inp->pfp_event_count;
Packit 577717
	for (i=0; i < count; i++) {
Packit 577717
		if (is_etb(e[i].event)) return PFMLIB_ERR_FEATCOMB;
Packit 577717
	}
Packit 577717
	reg.pmc_val = 0;
Packit 577717
Packit 577717
	reg.pmc42_mont_reg.ipear_plm   = param->pfp_mont_ipear.ipear_plm ? param->pfp_mont_ipear.ipear_plm : inp->pfp_dfl_plm;
Packit 577717
	reg.pmc42_mont_reg.ipear_pm    = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
Packit 577717
	reg.pmc42_mont_reg.ipear_mode  = 4;
Packit 577717
	reg.pmc42_mont_reg.ipear_delay = param->pfp_mont_ipear.ipear_delay;
Packit 577717
Packit 577717
	if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 42))
Packit 577717
		return PFMLIB_ERR_NOASSIGN;
Packit 577717
Packit 577717
	pc[pos1].reg_num     = 42;
Packit 577717
	pc[pos1].reg_value   = reg.pmc_val;
Packit 577717
	pc[pos1].reg_addr    = pc[pos1].reg_alt_addr = 42;
Packit 577717
	pos1++;
Packit 577717
Packit 577717
	__pfm_vbprintf("[PMC42(pmc42)=0x%lx plm=%d pm=%d mode=%d delay=%d]\n",
Packit 577717
			reg.pmc_val,
Packit 577717
			reg.pmc42_mont_reg.ipear_plm,
Packit 577717
			reg.pmc42_mont_reg.ipear_pm,
Packit 577717
			reg.pmc42_mont_reg.ipear_mode,
Packit 577717
			reg.pmc42_mont_reg.ipear_delay);
Packit 577717
Packit 577717
	pd[pos2].reg_num = 38;
Packit 577717
	pd[pos2].reg_addr = pd[pos2].reg_alt_addr = 38;
Packit 577717
	pos2++;
Packit 577717
	pd[pos2].reg_num = 39;
Packit 577717
	pd[pos2].reg_addr = pd[pos2].reg_alt_addr = 39;
Packit 577717
	pos2++;
Packit 577717
	__pfm_vbprintf("[PMD38(pmd38)]\n[PMD39(pmd39)\n");
Packit 577717
Packit 577717
	for(i=48; i < 64; 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
	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_mont_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_mont_input_param_t *mod_in  = (pfmlib_mont_input_param_t *)model_in;
Packit 577717
	pfmlib_mont_output_param_t *mod_out = (pfmlib_mont_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 range 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_mont_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
	/* now check for ETB */
Packit 577717
	ret = pfm_dispatch_etb(inp, mod_in, outp);
Packit 577717
	if (ret != PFMLIB_SUCCESS) return ret;
Packit 577717
Packit 577717
	/* now check for IP-EAR */
Packit 577717
	ret = pfm_dispatch_ipear(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_mont_get_event_maxincr(unsigned int i, unsigned int *maxincr)
Packit 577717
{
Packit 577717
	if (i >= PME_MONT_EVENT_COUNT || maxincr == NULL) return PFMLIB_ERR_INVAL;
Packit 577717
	*maxincr = montecito_pe[i].pme_maxincr;
Packit 577717
	return PFMLIB_SUCCESS;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
pfm_mont_is_ear(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT && is_ear(i);
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
pfm_mont_is_dear(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT && is_dear(i);
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
pfm_mont_is_dear_tlb(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT && is_dear(i) && is_ear_tlb(i);
Packit 577717
}
Packit 577717
	
Packit 577717
int
Packit 577717
pfm_mont_is_dear_cache(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT && is_dear(i) && is_ear_cache(i);
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
pfm_mont_is_dear_alat(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT && is_ear_alat(i);
Packit 577717
}
Packit 577717
	
Packit 577717
int
Packit 577717
pfm_mont_is_iear(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT && is_iear(i);
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
pfm_mont_is_iear_tlb(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT && is_iear(i) && is_ear_tlb(i);
Packit 577717
}
Packit 577717
	
Packit 577717
int
Packit 577717
pfm_mont_is_iear_cache(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT && is_iear(i) && is_ear_cache(i);
Packit 577717
}
Packit 577717
	
Packit 577717
int
Packit 577717
pfm_mont_is_etb(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT && is_etb(i);
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
pfm_mont_support_iarr(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT && has_iarr(i);
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
int
Packit 577717
pfm_mont_support_darr(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT  && has_darr(i);
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
int
Packit 577717
pfm_mont_support_opcm(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT && has_opcm(i);
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
pfm_mont_support_all(unsigned int i)
Packit 577717
{
Packit 577717
	return i < PME_MONT_EVENT_COUNT && has_all(i);
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
int
Packit 577717
pfm_mont_get_ear_mode(unsigned int i, pfmlib_mont_ear_mode_t *m)
Packit 577717
{
Packit 577717
	pfmlib_mont_ear_mode_t r;
Packit 577717
Packit 577717
	if (!is_ear(i) || m == NULL) return PFMLIB_ERR_INVAL;
Packit 577717
Packit 577717
	r = PFMLIB_MONT_EAR_TLB_MODE;
Packit 577717
	if (is_ear_tlb(i))  goto done;
Packit 577717
Packit 577717
	r = PFMLIB_MONT_EAR_CACHE_MODE;
Packit 577717
	if (is_ear_cache(i))  goto done;
Packit 577717
Packit 577717
	r = PFMLIB_MONT_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_mont_get_event_code(unsigned int i, unsigned int cnt, int *code)
Packit 577717
{
Packit 577717
	if (cnt != PFMLIB_CNT_FIRST && (cnt < 4 || cnt > 15))
Packit 577717
		return PFMLIB_ERR_INVAL;
Packit 577717
Packit 577717
	*code = (int)montecito_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_mont_get_event_umask(unsigned int i, unsigned long *umask)
Packit 577717
{
Packit 577717
	if (i >= PME_MONT_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_mont_get_event_group(unsigned int i, int *grp)
Packit 577717
{
Packit 577717
	if (i >= PME_MONT_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_mont_get_event_set(unsigned int i, int *set)
Packit 577717
{
Packit 577717
	if (i >= PME_MONT_EVENT_COUNT || set == NULL) return PFMLIB_ERR_INVAL;
Packit 577717
	*set = evt_set(i) == 0xf ? PFMLIB_MONT_EVT_NO_SET : evt_set(i);
Packit 577717
	return PFMLIB_SUCCESS;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
pfm_mont_get_event_type(unsigned int i, int *type)
Packit 577717
{
Packit 577717
	if (i >= PME_MONT_EVENT_COUNT || type == NULL) return PFMLIB_ERR_INVAL;
Packit 577717
	*type = evt_caf(i);
Packit 577717
	return PFMLIB_SUCCESS;
Packit 577717
}
Packit 577717
Packit 577717
/* external interface */
Packit 577717
int
Packit 577717
pfm_mont_irange_is_fine(pfmlib_output_param_t *outp, pfmlib_mont_output_param_t *mod_out)
Packit 577717
{
Packit 577717
	pfmlib_mont_output_param_t *param = mod_out;
Packit 577717
	pfm_mont_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_mont_irange.rr_nbr_used == 0) return 0;
Packit 577717
Packit 577717
	/*
Packit 577717
	 * we look for pmc38 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 == 38) 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.pmc38_mont_reg.iarc_fine ? 1 : 0;
Packit 577717
}
Packit 577717
Packit 577717
static char *
Packit 577717
pfm_mont_get_event_name(unsigned int i)
Packit 577717
{
Packit 577717
	return montecito_pe[i].pme_name;
Packit 577717
}
Packit 577717
Packit 577717
static void
Packit 577717
pfm_mont_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 =montecito_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_mont_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
Packit 577717
{
Packit 577717
	unsigned int i = 0;
Packit 577717
Packit 577717
	for(i=0; i < 16; i++)
Packit 577717
		pfm_regmask_set(impl_pmcs, i);
Packit 577717
Packit 577717
	for(i=32; i < 43; i++)
Packit 577717
		pfm_regmask_set(impl_pmcs, i);
Packit 577717
}
Packit 577717
Packit 577717
static void
Packit 577717
pfm_mont_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
Packit 577717
{
Packit 577717
	unsigned int i = 0;
Packit 577717
Packit 577717
	for(i=4; i < 16; i++)
Packit 577717
		pfm_regmask_set(impl_pmds, i);
Packit 577717
	for(i=32; i < 40; i++)
Packit 577717
		pfm_regmask_set(impl_pmds, i);
Packit 577717
	for(i=48; i < 64; i++)
Packit 577717
		pfm_regmask_set(impl_pmds, i);
Packit 577717
}
Packit 577717
Packit 577717
static void
Packit 577717
pfm_mont_get_impl_counters(pfmlib_regmask_t *impl_counters)
Packit 577717
{
Packit 577717
	unsigned int i = 0;
Packit 577717
Packit 577717
	/* counter pmds are contiguous */
Packit 577717
	for(i=4; i < 16; i++)
Packit 577717
		pfm_regmask_set(impl_counters, i);
Packit 577717
}
Packit 577717
Packit 577717
static void
Packit 577717
pfm_mont_get_hw_counter_width(unsigned int *width)
Packit 577717
{
Packit 577717
	*width = PMU_MONT_COUNTER_WIDTH;
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
pfm_mont_get_event_description(unsigned int ev, char **str)
Packit 577717
{
Packit 577717
	char *s;
Packit 577717
	s = montecito_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_mont_get_cycle_event(pfmlib_event_t *e)
Packit 577717
{
Packit 577717
	e->event = PME_MONT_CPU_OP_CYCLES_ALL;
Packit 577717
	return PFMLIB_SUCCESS;
Packit 577717
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
pfm_mont_get_inst_retired(pfmlib_event_t *e)
Packit 577717
{
Packit 577717
	e->event = PME_MONT_IA64_INST_RETIRED;
Packit 577717
	return PFMLIB_SUCCESS;
Packit 577717
}
Packit 577717
Packit 577717
static unsigned int
Packit 577717
pfm_mont_get_num_event_masks(unsigned int event)
Packit 577717
{
Packit 577717
	return has_mesi(event) ? 4 : 0;
Packit 577717
}
Packit 577717
Packit 577717
static char *
Packit 577717
pfm_mont_get_event_mask_name(unsigned int event, unsigned int mask)
Packit 577717
{
Packit 577717
	switch(mask) {
Packit 577717
		case 0: return "I";
Packit 577717
		case 1: return "S";
Packit 577717
		case 2: return "E";
Packit 577717
		case 3: return "M";	
Packit 577717
	}
Packit 577717
	return NULL;
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
pfm_mont_get_event_mask_desc(unsigned int event, unsigned int mask, char **desc)
Packit 577717
{
Packit 577717
	switch(mask) {
Packit 577717
		case 0: *desc = strdup("invalid");
Packit 577717
			break;
Packit 577717
		case 1: *desc = strdup("shared");
Packit 577717
			break;
Packit 577717
		case 2: *desc = strdup("exclusive");
Packit 577717
			break;
Packit 577717
		case 3: *desc = strdup("modified");	
Packit 577717
			break;
Packit 577717
		default:
Packit 577717
			return PFMLIB_ERR_INVAL;
Packit 577717
	}
Packit 577717
	return PFMLIB_SUCCESS;
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
pfm_mont_get_event_mask_code(unsigned int event,
Packit 577717
		 	     unsigned int mask, unsigned int *code)
Packit 577717
{
Packit 577717
	*code = mask;
Packit 577717
	return PFMLIB_SUCCESS;
Packit 577717
}
Packit 577717
Packit 577717
pfm_pmu_support_t montecito_support={
Packit 577717
	.pmu_name		= "dual-core Itanium 2",
Packit 577717
	.pmu_type		= PFMLIB_MONTECITO_PMU,
Packit 577717
	.pme_count		= PME_MONT_EVENT_COUNT,
Packit 577717
	.pmc_count		= PMU_MONT_NUM_PMCS,
Packit 577717
	.pmd_count		= PMU_MONT_NUM_PMDS,
Packit 577717
	.num_cnt		= PMU_MONT_NUM_COUNTERS,
Packit 577717
	.get_event_code		= pfm_mont_get_event_code,
Packit 577717
	.get_event_name		= pfm_mont_get_event_name,
Packit 577717
	.get_event_counters	= pfm_mont_get_event_counters,
Packit 577717
	.dispatch_events	= pfm_mont_dispatch_events,
Packit 577717
	.pmu_detect		= pfm_mont_detect,
Packit 577717
	.get_impl_pmcs		= pfm_mont_get_impl_pmcs,
Packit 577717
	.get_impl_pmds		= pfm_mont_get_impl_pmds,
Packit 577717
	.get_impl_counters	= pfm_mont_get_impl_counters,
Packit 577717
	.get_hw_counter_width	= pfm_mont_get_hw_counter_width,
Packit 577717
	.get_event_desc         = pfm_mont_get_event_description,
Packit 577717
	.get_cycle_event	= pfm_mont_get_cycle_event,
Packit 577717
	.get_inst_retired_event = pfm_mont_get_inst_retired,
Packit 577717
	.get_num_event_masks	= pfm_mont_get_num_event_masks,
Packit 577717
	.get_event_mask_name	= pfm_mont_get_event_mask_name,
Packit 577717
	.get_event_mask_desc	= pfm_mont_get_event_mask_desc,
Packit 577717
	.get_event_mask_code	= pfm_mont_get_event_mask_code
Packit 577717
};