Blame src/libpfm-3.y/lib/pfmlib_itanium.c

Packit Service a1973e
/*
Packit Service a1973e
 * pfmlib_itanium.c : support for Itanium-family PMU
Packit Service a1973e
 *
Packit Service a1973e
 * Copyright (c) 2001-2006 Hewlett-Packard Development Company, L.P.
Packit Service a1973e
 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
Packit Service a1973e
 *
Packit Service a1973e
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit Service a1973e
 * of this software and associated documentation files (the "Software"), to deal
Packit Service a1973e
 * in the Software without restriction, including without limitation the rights
Packit Service a1973e
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
Packit Service a1973e
 * of the Software, and to permit persons to whom the Software is furnished to do so,
Packit Service a1973e
 * subject to the following conditions:
Packit Service a1973e
 *
Packit Service a1973e
 * The above copyright notice and this permission notice shall be included in all
Packit Service a1973e
 * copies or substantial portions of the Software.
Packit Service a1973e
 *
Packit Service a1973e
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
Packit Service a1973e
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
Packit Service a1973e
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
Packit Service a1973e
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
Packit Service a1973e
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
Packit Service a1973e
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit Service a1973e
 */
Packit Service a1973e
#include <sys/types.h>
Packit Service a1973e
#include <ctype.h>
Packit Service a1973e
#include <string.h>
Packit Service a1973e
#include <stdio.h>
Packit Service a1973e
Packit Service a1973e
/* public headers */
Packit Service a1973e
#include <perfmon/pfmlib_itanium.h>
Packit Service a1973e
Packit Service a1973e
/* private headers */
Packit Service a1973e
#include "pfmlib_priv.h"		/* library private */
Packit Service a1973e
#include "pfmlib_priv_ia64.h"		/* architecture private */
Packit Service a1973e
#include "pfmlib_itanium_priv.h"	/* PMU private */
Packit Service a1973e
#include "itanium_events.h"		/* PMU private */
Packit Service a1973e
Packit Service a1973e
#define is_ear(i)	event_is_ear(itanium_pe+(i))
Packit Service a1973e
#define is_ear_tlb(i)	event_is_tlb_ear(itanium_pe+(i))
Packit Service a1973e
#define is_iear(i)	event_is_iear(itanium_pe+(i))
Packit Service a1973e
#define is_dear(i)	event_is_dear(itanium_pe+(i))
Packit Service a1973e
#define is_btb(i)	event_is_btb(itanium_pe+(i))
Packit Service a1973e
#define has_opcm(i)	event_opcm_ok(itanium_pe+(i))
Packit Service a1973e
#define has_iarr(i)	event_iarr_ok(itanium_pe+(i))
Packit Service a1973e
#define has_darr(i)	event_darr_ok(itanium_pe+(i))
Packit Service a1973e
Packit Service a1973e
#define evt_use_opcm(e)		((e)->pfp_ita_pmc8.opcm_used != 0 || (e)->pfp_ita_pmc9.opcm_used !=0)
Packit Service a1973e
#define evt_use_irange(e)	((e)->pfp_ita_irange.rr_used)
Packit Service a1973e
#define evt_use_drange(e)	((e)->pfp_ita_drange.rr_used)
Packit Service a1973e
Packit Service a1973e
#define evt_umask(e)		itanium_pe[(e)].pme_umask
Packit Service a1973e
Packit Service a1973e
/* let's define some handy shortcuts! */
Packit Service a1973e
#define pmc_plm		pmc_ita_count_reg.pmc_plm
Packit Service a1973e
#define pmc_ev		pmc_ita_count_reg.pmc_ev
Packit Service a1973e
#define pmc_oi		pmc_ita_count_reg.pmc_oi
Packit Service a1973e
#define pmc_pm		pmc_ita_count_reg.pmc_pm
Packit Service a1973e
#define pmc_es		pmc_ita_count_reg.pmc_es
Packit Service a1973e
#define pmc_umask	pmc_ita_count_reg.pmc_umask
Packit Service a1973e
#define pmc_thres	pmc_ita_count_reg.pmc_thres
Packit Service a1973e
#define pmc_ism		pmc_ita_count_reg.pmc_ism
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * Description of the PMC register mappings use by
Packit Service a1973e
 * this module (as reported in pfmlib_reg_t.reg_num):
Packit Service a1973e
 *
Packit Service a1973e
 * 0 -> PMC0
Packit Service a1973e
 * 1 -> PMC1
Packit Service a1973e
 * n -> PMCn
Packit Service a1973e
 *
Packit Service a1973e
 * The following are in the model specific rr_br[]:
Packit Service a1973e
 * IBR0 -> 0
Packit Service a1973e
 * IBR1 -> 1
Packit Service a1973e
 * ...
Packit Service a1973e
 * IBR7 -> 7
Packit Service a1973e
 * DBR0 -> 0
Packit Service a1973e
 * DBR1 -> 1
Packit Service a1973e
 * ...
Packit Service a1973e
 * DBR7 -> 7
Packit Service a1973e
 *
Packit Service a1973e
 * We do not use a mapping table, instead we make up the
Packit Service a1973e
 * values on the fly given the base.
Packit Service a1973e
 */
Packit Service a1973e
#define PFMLIB_ITA_PMC_BASE 0
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
pfm_ita_detect(void)
Packit Service a1973e
{
Packit Service a1973e
	int ret = PFMLIB_ERR_NOTSUPP;
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * we support all chips (there is only one!) in the Itanium family
Packit Service a1973e
	 */
Packit Service a1973e
	if (pfm_ia64_get_cpu_family() == 0x07) ret = PFMLIB_SUCCESS;
Packit Service a1973e
	return ret;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * Part of the following code will eventually go into a perfmon library
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
valid_assign(unsigned int *as, pfmlib_regmask_t *r_pmcs, unsigned int cnt)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int i;
Packit Service a1973e
	for(i=0; i < cnt; i++) {
Packit Service a1973e
		if (as[i]==0) return PFMLIB_ERR_NOASSIGN;
Packit Service a1973e
		/*
Packit Service a1973e
		 * take care of restricted PMC registers
Packit Service a1973e
		 */
Packit Service a1973e
		if (pfm_regmask_isset(r_pmcs, as[i]))
Packit Service a1973e
			return PFMLIB_ERR_NOASSIGN;
Packit Service a1973e
	}
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * Automatically dispatch events to corresponding counters following constraints.
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
pfm_ita_dispatch_counters(pfmlib_input_param_t *inp, pfmlib_ita_input_param_t *mod_in, pfmlib_output_param_t *outp)
Packit Service a1973e
{
Packit Service a1973e
#define	has_counter(e,b)	(itanium_pe[e].pme_counters & (1 << (b)) ? (b) : 0)
Packit Service a1973e
	pfmlib_ita_input_param_t *param = mod_in;
Packit Service a1973e
	pfm_ita_pmc_reg_t reg;
Packit Service a1973e
	pfmlib_event_t *e;
Packit Service a1973e
	pfmlib_reg_t *pc, *pd;
Packit Service a1973e
	pfmlib_regmask_t *r_pmcs;
Packit Service a1973e
	unsigned int i,j,k,l, m;
Packit Service a1973e
	unsigned int max_l0, max_l1, max_l2, max_l3;
Packit Service a1973e
	unsigned int assign[PMU_ITA_NUM_COUNTERS];
Packit Service a1973e
	unsigned int cnt;
Packit Service a1973e
Packit Service a1973e
	e      = inp->pfp_events;
Packit Service a1973e
	pc     = outp->pfp_pmcs;
Packit Service a1973e
	pd     = outp->pfp_pmds;
Packit Service a1973e
	cnt    = inp->pfp_event_count;
Packit Service a1973e
	r_pmcs = &inp->pfp_unavail_pmcs;
Packit Service a1973e
Packit Service a1973e
	if (PFMLIB_DEBUG()) {
Packit Service a1973e
		for (m=0; m < cnt; m++) {
Packit Service a1973e
			DPRINT("ev[%d]=%s counters=0x%lx\n", m, itanium_pe[e[m].event].pme_name,
Packit Service a1973e
				itanium_pe[e[m].event].pme_counters);
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
	if (cnt > PMU_ITA_NUM_COUNTERS) return PFMLIB_ERR_TOOMANY;
Packit Service a1973e
Packit Service a1973e
	max_l0 = PMU_ITA_FIRST_COUNTER + PMU_ITA_NUM_COUNTERS;
Packit Service a1973e
	max_l1 = PMU_ITA_FIRST_COUNTER + PMU_ITA_NUM_COUNTERS*(cnt>1);
Packit Service a1973e
	max_l2 = PMU_ITA_FIRST_COUNTER + PMU_ITA_NUM_COUNTERS*(cnt>2);
Packit Service a1973e
	max_l3 = PMU_ITA_FIRST_COUNTER + PMU_ITA_NUM_COUNTERS*(cnt>3);
Packit Service a1973e
Packit Service a1973e
	DPRINT("max_l0=%u max_l1=%u max_l2=%u max_l3=%u\n", max_l0, max_l1, max_l2, max_l3);
Packit Service a1973e
	/*
Packit Service a1973e
	 *  This code needs fixing. It is not very pretty and
Packit Service a1973e
	 *  won't handle more than 4 counters if more become
Packit Service a1973e
	 *  available !
Packit Service a1973e
	 *  For now, worst case in the loop nest: 4! (factorial)
Packit Service a1973e
	 */
Packit Service a1973e
	for (i=PMU_ITA_FIRST_COUNTER; i < max_l0; i++) {
Packit Service a1973e
Packit Service a1973e
		assign[0]= has_counter(e[0].event,i);
Packit Service a1973e
Packit Service a1973e
		if (max_l1 == PMU_ITA_FIRST_COUNTER && valid_assign(assign, r_pmcs, cnt) == PFMLIB_SUCCESS) goto done;
Packit Service a1973e
Packit Service a1973e
		for (j=PMU_ITA_FIRST_COUNTER; j < max_l1; j++) {
Packit Service a1973e
Packit Service a1973e
			if (j == i) continue;
Packit Service a1973e
Packit Service a1973e
			assign[1] = has_counter(e[1].event,j);
Packit Service a1973e
Packit Service a1973e
			if (max_l2 == PMU_ITA_FIRST_COUNTER && valid_assign(assign, r_pmcs, cnt) == PFMLIB_SUCCESS) goto done;
Packit Service a1973e
Packit Service a1973e
			for (k=PMU_ITA_FIRST_COUNTER; k < max_l2; k++) {
Packit Service a1973e
Packit Service a1973e
				if(k == i || k == j) continue;
Packit Service a1973e
Packit Service a1973e
				assign[2] = has_counter(e[2].event,k);
Packit Service a1973e
Packit Service a1973e
				if (max_l3 == PMU_ITA_FIRST_COUNTER && valid_assign(assign, r_pmcs, cnt) == PFMLIB_SUCCESS) goto done;
Packit Service a1973e
				for (l=PMU_ITA_FIRST_COUNTER; l < max_l3; l++) {
Packit Service a1973e
Packit Service a1973e
					if(l == i || l == j || l == k) continue;
Packit Service a1973e
Packit Service a1973e
					assign[3] = has_counter(e[3].event,l);
Packit Service a1973e
Packit Service a1973e
					if (valid_assign(assign, r_pmcs, cnt) == PFMLIB_SUCCESS) goto done;
Packit Service a1973e
				}
Packit Service a1973e
			}
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
	/* we cannot satisfy the constraints */
Packit Service a1973e
	return PFMLIB_ERR_NOASSIGN;
Packit Service a1973e
done:
Packit Service a1973e
	for (j=0; j < cnt ; j++ ) {
Packit Service a1973e
		reg.pmc_val = 0; /* clear all */
Packit Service a1973e
		/* if plm is 0, then assume not specified per-event and use default */
Packit Service a1973e
		reg.pmc_plm    = e[j].plm ? e[j].plm : inp->pfp_dfl_plm;
Packit Service a1973e
		reg.pmc_oi     = 1; /* overflow interrupt */
Packit Service a1973e
		reg.pmc_pm     = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
Packit Service a1973e
		reg.pmc_thres  = param ? param->pfp_ita_counters[j].thres: 0;
Packit Service a1973e
		reg.pmc_ism    = param ? param->pfp_ita_counters[j].ism : PFMLIB_ITA_ISM_BOTH;
Packit Service a1973e
		reg.pmc_umask  = is_ear(e[j].event) ? 0x0 : evt_umask(e[j].event);
Packit Service a1973e
		reg.pmc_es     = itanium_pe[e[j].event].pme_code;
Packit Service a1973e
Packit Service a1973e
		pc[j].reg_num     = assign[j];
Packit Service a1973e
		pc[j].reg_value   = reg.pmc_val;
Packit Service a1973e
		pc[j].reg_addr    = assign[j];
Packit Service a1973e
		pc[j].reg_alt_addr= assign[j];
Packit Service a1973e
Packit Service a1973e
		pd[j].reg_num = assign[j];
Packit Service a1973e
		pd[j].reg_addr = assign[j];
Packit Service a1973e
		pd[j].reg_alt_addr = assign[j];
Packit Service a1973e
Packit Service a1973e
		__pfm_vbprintf("[PMC%u(pmc%u)=0x%06lx thres=%d es=0x%02x plm=%d umask=0x%x pm=%d ism=0x%x oi=%d] %s\n",
Packit Service a1973e
				assign[j],
Packit Service a1973e
				assign[j],
Packit Service a1973e
				reg.pmc_val,
Packit Service a1973e
				reg.pmc_thres,
Packit Service a1973e
				reg.pmc_es,reg.pmc_plm,
Packit Service a1973e
				reg.pmc_umask, reg.pmc_pm,
Packit Service a1973e
				reg.pmc_ism,
Packit Service a1973e
				reg.pmc_oi,
Packit Service a1973e
				itanium_pe[e[j].event].pme_name);
Packit Service a1973e
		__pfm_vbprintf("[PMD%u(pmd%u)]\n", pd[j].reg_num, pd[j].reg_num);
Packit Service a1973e
	}
Packit Service a1973e
	/* number of PMC registers programmed */
Packit Service a1973e
	outp->pfp_pmc_count = cnt;
Packit Service a1973e
	outp->pfp_pmd_count = cnt;
Packit Service a1973e
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
pfm_dispatch_iear(pfmlib_input_param_t *inp, pfmlib_ita_input_param_t *mod_in, pfmlib_output_param_t *outp)
Packit Service a1973e
{
Packit Service a1973e
	pfm_ita_pmc_reg_t reg;
Packit Service a1973e
	pfmlib_ita_input_param_t *param = mod_in;
Packit Service a1973e
	pfmlib_ita_input_param_t fake_param;
Packit Service a1973e
	pfmlib_reg_t *pc, *pd;
Packit Service a1973e
	unsigned int pos1, pos2;
Packit Service a1973e
	int iear_idx = -1;
Packit Service a1973e
	unsigned int i, count;
Packit Service a1973e
Packit Service a1973e
	pc = outp->pfp_pmcs;
Packit Service a1973e
	pd = outp->pfp_pmds;
Packit Service a1973e
	pos1 = outp->pfp_pmc_count;
Packit Service a1973e
	pos2 = outp->pfp_pmd_count;
Packit Service a1973e
	count = inp->pfp_event_count;
Packit Service a1973e
Packit Service a1973e
	for (i=0; i < count; i++) {
Packit Service a1973e
		if (is_iear(inp->pfp_events[i].event)) iear_idx = i;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	if (param == NULL || mod_in->pfp_ita_iear.ear_used == 0) {
Packit Service a1973e
Packit Service a1973e
		/*
Packit Service a1973e
		 * case 3: no I-EAR event, no (or nothing) in param->pfp_ita2_iear.ear_used
Packit Service a1973e
		 */
Packit Service a1973e
		if (iear_idx == -1) return PFMLIB_SUCCESS;
Packit Service a1973e
Packit Service a1973e
		memset(&fake_param, 0, sizeof(fake_param));
Packit Service a1973e
		param = &fake_param;
Packit Service a1973e
Packit Service a1973e
		pfm_ita_get_ear_mode(inp->pfp_events[iear_idx].event, &param->pfp_ita_iear.ear_mode);
Packit Service a1973e
Packit Service a1973e
		param->pfp_ita_iear.ear_umask = evt_umask(inp->pfp_events[iear_idx].event);
Packit Service a1973e
		param->pfp_ita_iear.ear_ism   = PFMLIB_ITA_ISM_BOTH; /* force both instruction sets */
Packit Service a1973e
Packit Service a1973e
		DPRINT("I-EAR event with no info\n");
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	/* sanity check on the mode */
Packit Service a1973e
	if (param->pfp_ita_iear.ear_mode < 0 || param->pfp_ita_iear.ear_mode > 2) return PFMLIB_ERR_INVAL;
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * case 2: ear_used=1, event is defined, we use the param info as it is more precise
Packit Service a1973e
	 * case 4: ear_used=1, no event (free running I-EAR), use param info
Packit Service a1973e
	 */
Packit Service a1973e
	reg.pmc_val = 0;
Packit Service a1973e
Packit Service a1973e
	/* if plm is 0, then assume not specified per-event and use default */
Packit Service a1973e
	reg.pmc10_ita_reg.iear_plm   = param->pfp_ita_iear.ear_plm ? param->pfp_ita_iear.ear_plm : inp->pfp_dfl_plm;
Packit Service a1973e
	reg.pmc10_ita_reg.iear_pm    = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
Packit Service a1973e
	reg.pmc10_ita_reg.iear_tlb   = param->pfp_ita_iear.ear_mode;
Packit Service a1973e
	reg.pmc10_ita_reg.iear_umask = param->pfp_ita_iear.ear_umask;
Packit Service a1973e
	reg.pmc10_ita_reg.iear_ism   = param->pfp_ita_iear.ear_ism;
Packit Service a1973e
Packit Service a1973e
	if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 10))
Packit Service a1973e
		return PFMLIB_ERR_NOASSIGN;
Packit Service a1973e
Packit Service a1973e
	pc[pos1].reg_num     = 10;  /* PMC10 is I-EAR config register */
Packit Service a1973e
	pc[pos1].reg_value   = reg.pmc_val;
Packit Service a1973e
	pc[pos1].reg_addr    = 10;
Packit Service a1973e
	pc[pos1].reg_alt_addr= 10;
Packit Service a1973e
	pos1++;
Packit Service a1973e
	pd[pos2].reg_num     = 0; 
Packit Service a1973e
	pd[pos2].reg_addr    = 0;
Packit Service a1973e
	pd[pos2].reg_alt_addr  = 0;
Packit Service a1973e
	pos2++;
Packit Service a1973e
	pd[pos2].reg_num     = 1; 
Packit Service a1973e
	pd[pos2].reg_addr    = 1;
Packit Service a1973e
	pd[pos2].reg_alt_addr  = 1;
Packit Service a1973e
	pos2++;
Packit Service a1973e
Packit Service a1973e
	__pfm_vbprintf("[PMC10(pmc10)=0x%lx tlb=%s plm=%d pm=%d ism=0x%x umask=0x%x]\n",
Packit Service a1973e
			reg.pmc_val,
Packit Service a1973e
			reg.pmc10_ita_reg.iear_tlb ? "Yes" : "No",
Packit Service a1973e
			reg.pmc10_ita_reg.iear_plm,
Packit Service a1973e
			reg.pmc10_ita_reg.iear_pm,
Packit Service a1973e
			reg.pmc10_ita_reg.iear_ism,
Packit Service a1973e
			reg.pmc10_ita_reg.iear_umask);
Packit Service a1973e
	__pfm_vbprintf("[PMD0(pmd0)]\n[PMD1(pmd1)\n");
Packit Service a1973e
Packit Service a1973e
	/* update final number of entries used */
Packit Service a1973e
	outp->pfp_pmc_count = pos1;
Packit Service a1973e
	outp->pfp_pmd_count = pos2;
Packit Service a1973e
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
pfm_dispatch_dear(pfmlib_input_param_t *inp, pfmlib_ita_input_param_t *mod_in, pfmlib_output_param_t *outp)
Packit Service a1973e
{
Packit Service a1973e
	pfm_ita_pmc_reg_t reg;
Packit Service a1973e
	pfmlib_ita_input_param_t *param = mod_in;
Packit Service a1973e
	pfmlib_ita_input_param_t fake_param;
Packit Service a1973e
	pfmlib_reg_t *pc, *pd;
Packit Service a1973e
	unsigned int pos1, pos2;
Packit Service a1973e
	int dear_idx = -1;
Packit Service a1973e
	unsigned int i, count;
Packit Service a1973e
Packit Service a1973e
	pc = outp->pfp_pmcs;
Packit Service a1973e
	pd = outp->pfp_pmds;
Packit Service a1973e
	pos1 = outp->pfp_pmc_count;
Packit Service a1973e
	pos2 = outp->pfp_pmd_count;
Packit Service a1973e
	count = inp->pfp_event_count;
Packit Service a1973e
Packit Service a1973e
	for (i=0; i < count; i++) {
Packit Service a1973e
		if (is_dear(inp->pfp_events[i].event)) dear_idx = i;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	if (param == NULL || param->pfp_ita_dear.ear_used == 0) {
Packit Service a1973e
Packit Service a1973e
		/*
Packit Service a1973e
		 * case 3: no D-EAR event, no (or nothing) in param->pfp_ita2_dear.ear_used
Packit Service a1973e
		 */
Packit Service a1973e
		if (dear_idx == -1) return PFMLIB_SUCCESS;
Packit Service a1973e
Packit Service a1973e
		memset(&fake_param, 0, sizeof(fake_param));
Packit Service a1973e
		param = &fake_param;
Packit Service a1973e
Packit Service a1973e
		pfm_ita_get_ear_mode(inp->pfp_events[dear_idx].event, &param->pfp_ita_dear.ear_mode);
Packit Service a1973e
Packit Service a1973e
		param->pfp_ita_dear.ear_umask = evt_umask(inp->pfp_events[dear_idx].event);
Packit Service a1973e
		param->pfp_ita_dear.ear_ism   = PFMLIB_ITA_ISM_BOTH; /* force both instruction sets */
Packit Service a1973e
Packit Service a1973e
		DPRINT("D-EAR event with no info\n");
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
	/* sanity check on the mode */
Packit Service a1973e
	if (param->pfp_ita_dear.ear_mode > 2) return PFMLIB_ERR_INVAL;
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * case 2: ear_used=1, event is defined, we use the param info as it is more precise
Packit Service a1973e
	 * case 4: ear_used=1, no event (free running D-EAR), use param info
Packit Service a1973e
	 */
Packit Service a1973e
	reg.pmc_val = 0;
Packit Service a1973e
Packit Service a1973e
	/* if plm is 0, then assume not specified per-event and use default */
Packit Service a1973e
	reg.pmc11_ita_reg.dear_plm   = param->pfp_ita_dear.ear_plm ? param->pfp_ita_dear.ear_plm : inp->pfp_dfl_plm;
Packit Service a1973e
	reg.pmc11_ita_reg.dear_pm    = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
Packit Service a1973e
	reg.pmc11_ita_reg.dear_tlb   = param->pfp_ita_dear.ear_mode;
Packit Service a1973e
	reg.pmc11_ita_reg.dear_ism   = param->pfp_ita_dear.ear_ism;
Packit Service a1973e
	reg.pmc11_ita_reg.dear_umask = param->pfp_ita_dear.ear_umask;
Packit Service a1973e
	reg.pmc11_ita_reg.dear_pt    = param->pfp_ita_drange.rr_used ? 0: 1;
Packit Service a1973e
Packit Service a1973e
	if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 11))
Packit Service a1973e
		return PFMLIB_ERR_NOASSIGN;
Packit Service a1973e
Packit Service a1973e
	pc[pos1].reg_num     = 11;  /* PMC11 is D-EAR config register */
Packit Service a1973e
	pc[pos1].reg_value   = reg.pmc_val;
Packit Service a1973e
	pc[pos1].reg_addr    = 11;
Packit Service a1973e
	pos1++;
Packit Service a1973e
	pd[pos2].reg_num     = 2; 
Packit Service a1973e
	pd[pos2].reg_addr    = 2;
Packit Service a1973e
	pd[pos2].reg_alt_addr  = 2;
Packit Service a1973e
	pos2++;
Packit Service a1973e
	pd[pos2].reg_num     = 3; 
Packit Service a1973e
	pd[pos2].reg_addr    = 3;
Packit Service a1973e
	pd[pos2].reg_alt_addr  = 3;
Packit Service a1973e
	pos2++;
Packit Service a1973e
	pd[pos2].reg_num     = 17; 
Packit Service a1973e
	pd[pos2].reg_addr    = 17;
Packit Service a1973e
	pd[pos2].reg_alt_addr  = 17;
Packit Service a1973e
	pos2++;
Packit Service a1973e
Packit Service a1973e
	__pfm_vbprintf("[PMC11(pmc11)=0x%lx tlb=%s plm=%d pm=%d ism=0x%x umask=0x%x pt=%d]\n",
Packit Service a1973e
			reg.pmc_val,
Packit Service a1973e
			reg.pmc11_ita_reg.dear_tlb ? "Yes" : "No",
Packit Service a1973e
			reg.pmc11_ita_reg.dear_plm,	
Packit Service a1973e
			reg.pmc11_ita_reg.dear_pm,
Packit Service a1973e
			reg.pmc11_ita_reg.dear_ism,
Packit Service a1973e
			reg.pmc11_ita_reg.dear_umask,
Packit Service a1973e
			reg.pmc11_ita_reg.dear_pt);
Packit Service a1973e
	__pfm_vbprintf("[PMD2(pmd2)]\n[PMD3(pmd3)\nPMD17(pmd17)\n");
Packit Service a1973e
Packit Service a1973e
	/* update final number of entries used */
Packit Service a1973e
	outp->pfp_pmc_count = pos1;
Packit Service a1973e
	outp->pfp_pmd_count = pos2;
Packit Service a1973e
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
pfm_dispatch_opcm(pfmlib_input_param_t *inp, pfmlib_ita_input_param_t *mod_in, pfmlib_output_param_t *outp)
Packit Service a1973e
{
Packit Service a1973e
	pfmlib_ita_input_param_t *param = mod_in;
Packit Service a1973e
	pfm_ita_pmc_reg_t reg;
Packit Service a1973e
	pfmlib_reg_t *pc = outp->pfp_pmcs;
Packit Service a1973e
	int pos = outp->pfp_pmc_count;
Packit Service a1973e
Packit Service a1973e
	if (param == NULL) return PFMLIB_SUCCESS;
Packit Service a1973e
Packit Service a1973e
	if (param->pfp_ita_pmc8.opcm_used) {
Packit Service a1973e
Packit Service a1973e
		reg.pmc_val = param->pfp_ita_pmc8.pmc_val;
Packit Service a1973e
Packit Service a1973e
		if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 8))
Packit Service a1973e
			return PFMLIB_ERR_NOASSIGN;
Packit Service a1973e
Packit Service a1973e
		pc[pos].reg_num     = 8;
Packit Service a1973e
		pc[pos].reg_value   = reg.pmc_val;
Packit Service a1973e
		pc[pos].reg_addr  = 8;
Packit Service a1973e
		pc[pos].reg_alt_addr  = 8;
Packit Service a1973e
		pos++;
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
		__pfm_vbprintf("[PMC8(pmc8)=0x%lx m=%d i=%d f=%d b=%d match=0x%x mask=0x%x]\n",
Packit Service a1973e
				reg.pmc_val,
Packit Service a1973e
				reg.pmc8_9_ita_reg.m,
Packit Service a1973e
				reg.pmc8_9_ita_reg.i,
Packit Service a1973e
				reg.pmc8_9_ita_reg.f,
Packit Service a1973e
				reg.pmc8_9_ita_reg.b,
Packit Service a1973e
				reg.pmc8_9_ita_reg.match,
Packit Service a1973e
				reg.pmc8_9_ita_reg.mask);
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	if (param->pfp_ita_pmc9.opcm_used) {
Packit Service a1973e
Packit Service a1973e
		reg.pmc_val = param->pfp_ita_pmc9.pmc_val;
Packit Service a1973e
Packit Service a1973e
		if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 9))
Packit Service a1973e
			return PFMLIB_ERR_NOASSIGN;
Packit Service a1973e
Packit Service a1973e
		pc[pos].reg_num     = 9;
Packit Service a1973e
		pc[pos].reg_value   = reg.pmc_val;
Packit Service a1973e
		pc[pos].reg_addr  = 9;
Packit Service a1973e
		pc[pos].reg_alt_addr  = 9;
Packit Service a1973e
		pos++;
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
		__pfm_vbprintf("[PMC9(pmc9)=0x%lx m=%d i=%d f=%d b=%d match=0x%x mask=0x%x]\n",
Packit Service a1973e
				reg.pmc_val,
Packit Service a1973e
				reg.pmc8_9_ita_reg.m,
Packit Service a1973e
				reg.pmc8_9_ita_reg.i,
Packit Service a1973e
				reg.pmc8_9_ita_reg.f,
Packit Service a1973e
				reg.pmc8_9_ita_reg.b,
Packit Service a1973e
				reg.pmc8_9_ita_reg.match,
Packit Service a1973e
				reg.pmc8_9_ita_reg.mask);
Packit Service a1973e
	}
Packit Service a1973e
	outp->pfp_pmc_count = pos;
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
pfm_dispatch_btb(pfmlib_input_param_t *inp, pfmlib_ita_input_param_t *mod_in, pfmlib_output_param_t *outp)
Packit Service a1973e
{
Packit Service a1973e
	pfm_ita_pmc_reg_t reg;
Packit Service a1973e
	pfmlib_ita_input_param_t *param = mod_in;
Packit Service a1973e
	pfmlib_ita_input_param_t fake_param;
Packit Service a1973e
	pfmlib_reg_t *pc, *pd;
Packit Service a1973e
	int found_btb=0;
Packit Service a1973e
	unsigned int i, count;
Packit Service a1973e
	unsigned int  pos1, pos2;
Packit Service a1973e
Packit Service a1973e
	reg.pmc_val = 0;
Packit Service a1973e
Packit Service a1973e
	pc = outp->pfp_pmcs;
Packit Service a1973e
	pd = outp->pfp_pmds;
Packit Service a1973e
	pos1 = outp->pfp_pmc_count;
Packit Service a1973e
	pos2 = outp->pfp_pmd_count;
Packit Service a1973e
Packit Service a1973e
	count = inp->pfp_event_count;
Packit Service a1973e
	for (i=0; i < count; i++) {
Packit Service a1973e
		if (is_btb(inp->pfp_events[i].event)) found_btb = 1;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	if (param == NULL || param->pfp_ita_btb.btb_used == 0) {
Packit Service a1973e
Packit Service a1973e
		/*
Packit Service a1973e
		 * case 3: no BTB event, no param
Packit Service a1973e
		 */
Packit Service a1973e
		if (found_btb  == 0) return PFMLIB_SUCCESS;
Packit Service a1973e
Packit Service a1973e
		/*
Packit Service a1973e
		 * case 1: BTB event, no param, capture all branches
Packit Service a1973e
		 */
Packit Service a1973e
		memset(&fake_param, 0, sizeof(fake_param));
Packit Service a1973e
		param = &fake_param;
Packit Service a1973e
Packit Service a1973e
		param->pfp_ita_btb.btb_tar = 0x1; 	/* capture TAR  */
Packit Service a1973e
		param->pfp_ita_btb.btb_tm  = 0x3; 	/* all branches */
Packit Service a1973e
		param->pfp_ita_btb.btb_ptm = 0x3; 	/* all branches */
Packit Service a1973e
		param->pfp_ita_btb.btb_ppm = 0x3; 	/* all branches */
Packit Service a1973e
		param->pfp_ita_btb.btb_tac = 0x1; 	/* capture TAC  */
Packit Service a1973e
		param->pfp_ita_btb.btb_bac = 0x1; 	/* capture BAC  */
Packit Service a1973e
Packit Service a1973e
		DPRINT("BTB event with no info\n");
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * case 2: BTB event, param
Packit Service a1973e
	 * case 4: no BTB event, param (free running mode)
Packit Service a1973e
	 */
Packit Service a1973e
Packit Service a1973e
	/* if plm is 0, then assume not specified per-event and use default */
Packit Service a1973e
	reg.pmc12_ita_reg.btbc_plm = param->pfp_ita_btb.btb_plm ? param->pfp_ita_btb.btb_plm : inp->pfp_dfl_plm;
Packit Service a1973e
	reg.pmc12_ita_reg.btbc_pm  = inp->pfp_flags & PFMLIB_PFP_SYSTEMWIDE ? 1 : 0;
Packit Service a1973e
	reg.pmc12_ita_reg.btbc_tar = param->pfp_ita_btb.btb_tar & 0x1;
Packit Service a1973e
	reg.pmc12_ita_reg.btbc_tm  = param->pfp_ita_btb.btb_tm  & 0x3;
Packit Service a1973e
	reg.pmc12_ita_reg.btbc_ptm = param->pfp_ita_btb.btb_ptm & 0x3;
Packit Service a1973e
	reg.pmc12_ita_reg.btbc_ppm = param->pfp_ita_btb.btb_ppm & 0x3;
Packit Service a1973e
	reg.pmc12_ita_reg.btbc_bpt = param->pfp_ita_btb.btb_tac & 0x1;
Packit Service a1973e
	reg.pmc12_ita_reg.btbc_bac = param->pfp_ita_btb.btb_bac & 0x1;
Packit Service a1973e
Packit Service a1973e
	if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 12))
Packit Service a1973e
		return PFMLIB_ERR_NOASSIGN;
Packit Service a1973e
Packit Service a1973e
	pc[pos1].reg_num   = 12;
Packit Service a1973e
	pc[pos1].reg_value = reg.pmc_val;
Packit Service a1973e
	pc[pos1].reg_value = 12;
Packit Service a1973e
	pos1++;
Packit Service a1973e
Packit Service a1973e
	__pfm_vbprintf("[PMC12(pmc12)=0x%lx plm=%d pm=%d tar=%d tm=%d ptm=%d ppm=%d bpt=%d bac=%d]\n",
Packit Service a1973e
			reg.pmc_val,
Packit Service a1973e
			reg.pmc12_ita_reg.btbc_plm,
Packit Service a1973e
			reg.pmc12_ita_reg.btbc_pm,
Packit Service a1973e
			reg.pmc12_ita_reg.btbc_tar,
Packit Service a1973e
			reg.pmc12_ita_reg.btbc_tm,
Packit Service a1973e
			reg.pmc12_ita_reg.btbc_ptm,
Packit Service a1973e
			reg.pmc12_ita_reg.btbc_ppm,
Packit Service a1973e
			reg.pmc12_ita_reg.btbc_bpt,
Packit Service a1973e
			reg.pmc12_ita_reg.btbc_bac);
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * PMD16 is included in list of used PMD
Packit Service a1973e
	 */
Packit Service a1973e
	for(i=8; i < 17; i++, pos2++) {
Packit Service a1973e
		pd[pos2].reg_num = i;
Packit Service a1973e
		pd[pos2].reg_addr = i;
Packit Service a1973e
		pd[pos2].reg_alt_addr = i;
Packit Service a1973e
		__pfm_vbprintf("[PMD%u(pmd%u)]\n", pd[pos2].reg_num, pd[pos2].reg_num);
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	/* update final number of entries used */
Packit Service a1973e
	outp->pfp_pmc_count = pos1;
Packit Service a1973e
	outp->pfp_pmd_count = pos2;
Packit Service a1973e
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * mode = 0 -> check code (enforce bundle alignment)
Packit Service a1973e
 * mode = 1 -> check data
Packit Service a1973e
 */
Packit Service a1973e
static int
Packit Service a1973e
check_intervals(pfmlib_ita_input_rr_t *irr, int mode, int *n_intervals)
Packit Service a1973e
{
Packit Service a1973e
	int i;
Packit Service a1973e
	pfmlib_ita_input_rr_desc_t *lim = irr->rr_limits;
Packit Service a1973e
Packit Service a1973e
	for(i=0; i < 4; i++) {
Packit Service a1973e
		/* end marker */
Packit Service a1973e
		if (lim[i].rr_start == 0 && lim[i].rr_end == 0) break;
Packit Service a1973e
Packit Service a1973e
		/* invalid entry */
Packit Service a1973e
		if (lim[i].rr_start >= lim[i].rr_end) return PFMLIB_ERR_IRRINVAL;
Packit Service a1973e
Packit Service a1973e
		if (mode == 0 && (lim[i].rr_start & 0xf || lim[i].rr_end & 0xf))
Packit Service a1973e
			return PFMLIB_ERR_IRRALIGN;
Packit Service a1973e
	}
Packit Service a1973e
	*n_intervals = i;
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void
Packit Service a1973e
do_normal_rr(unsigned long start, unsigned long end,
Packit Service a1973e
			     pfmlib_reg_t *br, int nbr, int dir, int *idx, int *reg_idx, int plm)
Packit Service a1973e
{
Packit Service a1973e
	unsigned long size, l_addr, c;
Packit Service a1973e
	unsigned long l_offs = 0, r_offs = 0;
Packit Service a1973e
	unsigned long l_size, r_size;
Packit Service a1973e
	dbreg_t db;
Packit Service a1973e
	int p2;
Packit Service a1973e
Packit Service a1973e
	if (nbr < 1 || end <= start) return;
Packit Service a1973e
Packit Service a1973e
	size = end - start;
Packit Service a1973e
Packit Service a1973e
	DPRINT("start=0x%016lx end=0x%016lx size=0x%lx bytes (%lu bundles) nbr=%d dir=%d\n",
Packit Service a1973e
			start, end, size, size >> 4, nbr, dir);
Packit Service a1973e
Packit Service a1973e
	p2 = pfm_ia64_fls(size);
Packit Service a1973e
Packit Service a1973e
	c = ALIGN_DOWN(end, p2);
Packit Service a1973e
Packit Service a1973e
	DPRINT("largest power of two possible: 2^%d=0x%lx, crossing=0x%016lx\n",
Packit Service a1973e
				p2,
Packit Service a1973e
				1UL << p2, c);
Packit Service a1973e
Packit Service a1973e
	if ((c - (1UL<<p2)) >= start) {
Packit Service a1973e
		l_addr = c - (1UL << p2);
Packit Service a1973e
	} else {
Packit Service a1973e
		p2--;
Packit Service a1973e
Packit Service a1973e
		if ((c + (1UL<
Packit Service a1973e
			l_addr = c;
Packit Service a1973e
		} else {
Packit Service a1973e
			l_addr = c - (1UL << p2);
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
	l_size = l_addr - start;
Packit Service a1973e
	r_size = end - l_addr-(1UL<
Packit Service a1973e
Packit Service a1973e
	DPRINT("largest chunk: 2^%d=0x%lx @0x%016lx-0x%016lx\n", p2, 1UL<
Packit Service a1973e
	if (l_size) DPRINT("before: 0x%016lx-0x%016lx\n", start, l_addr);
Packit Service a1973e
	if (r_size) DPRINT("after : 0x%016lx-0x%016lx\n", l_addr+(1UL<
Packit Service a1973e
Packit Service a1973e
	if (dir == 0 && l_size != 0 && nbr == 1) {
Packit Service a1973e
		p2++;
Packit Service a1973e
		l_addr = end - (1UL << p2);
Packit Service a1973e
		if (PFMLIB_DEBUG()) {
Packit Service a1973e
			l_offs = start - l_addr;
Packit Service a1973e
			DPRINT(">>l_offs: 0x%lx\n", l_offs);
Packit Service a1973e
		}
Packit Service a1973e
	} else if (dir == 1 && r_size != 0 && nbr == 1) {
Packit Service a1973e
		p2++;
Packit Service a1973e
		l_addr = start;
Packit Service a1973e
		if (PFMLIB_DEBUG()) {
Packit Service a1973e
			r_offs = l_addr+(1UL<
Packit Service a1973e
			DPRINT(">>r_offs: 0x%lx\n", r_offs);
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
	l_size = l_addr - start;
Packit Service a1973e
	r_size = end - l_addr-(1UL<
Packit Service a1973e
	
Packit Service a1973e
	DPRINT(">>largest chunk: 2^%d @0x%016lx-0x%016lx\n", p2, l_addr, l_addr+(1UL<
Packit Service a1973e
	if (l_size && !l_offs) DPRINT(">>before: 0x%016lx-0x%016lx\n", start, l_addr);
Packit Service a1973e
	if (r_size && !r_offs) DPRINT(">>after : 0x%016lx-0x%016lx\n", l_addr+(1UL<
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * we initialize the mask to full 0 and
Packit Service a1973e
	 * only update the mask field. the rest is left
Packit Service a1973e
	 * to zero, except for the plm.
Packit Service a1973e
	 * in the case of ibr, the x-field must be 0. For dbr
Packit Service a1973e
	 * the value of r-field and w-field is ignored.
Packit Service a1973e
	 */
Packit Service a1973e
Packit Service a1973e
	db.val        = 0;
Packit Service a1973e
	db.db.db_mask = ~((1UL << p2)-1);
Packit Service a1973e
	/*
Packit Service a1973e
	 * we always use default privilege level.
Packit Service a1973e
	 * plm is ignored for DBRs.
Packit Service a1973e
	 */
Packit Service a1973e
	db.db.db_plm  = plm;
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
	br[*idx].reg_num     = *reg_idx;
Packit Service a1973e
	br[*idx].reg_value   = l_addr;
Packit Service a1973e
	br[*idx].reg_addr    = *reg_idx;
Packit Service a1973e
	br[*idx].reg_alt_addr= *reg_idx;
Packit Service a1973e
Packit Service a1973e
	br[*idx+1].reg_num   = *reg_idx+1;
Packit Service a1973e
	br[*idx+1].reg_value = db.val;
Packit Service a1973e
	br[*idx+1].reg_addr  = *reg_idx+1;
Packit Service a1973e
	br[*idx+1].reg_alt_addr = *reg_idx+1;
Packit Service a1973e
Packit Service a1973e
	*idx     += 2;
Packit Service a1973e
	*reg_idx += 2;
Packit Service a1973e
Packit Service a1973e
	nbr--;
Packit Service a1973e
	if (nbr) {
Packit Service a1973e
		int r_nbr, l_nbr;
Packit Service a1973e
Packit Service a1973e
		r_nbr = l_nbr = nbr >>1;
Packit Service a1973e
Packit Service a1973e
		if (nbr & 0x1) {
Packit Service a1973e
			/*
Packit Service a1973e
			 * our simple heuristic is:
Packit Service a1973e
			 * we assign the largest number of registers to the largest
Packit Service a1973e
			 * of the two chunks
Packit Service a1973e
			 */
Packit Service a1973e
			if (l_size > r_size) {
Packit Service a1973e
				l_nbr++;
Packit Service a1973e
			} else {
Packit Service a1973e
				r_nbr++;
Packit Service a1973e
			}
Packit Service a1973e
Packit Service a1973e
		}
Packit Service a1973e
		do_normal_rr(start, l_addr, br, l_nbr, 0, idx, reg_idx, plm);
Packit Service a1973e
		do_normal_rr(l_addr+(1UL<
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static void
Packit Service a1973e
print_one_range(pfmlib_ita_input_rr_desc_t *in_rr, pfmlib_ita_output_rr_desc_t *out_rr, pfmlib_reg_t *dbr, int base_idx, int n_pairs)
Packit Service a1973e
{
Packit Service a1973e
	int j;
Packit Service a1973e
	dbreg_t d;
Packit Service a1973e
	unsigned long r_end;
Packit Service a1973e
Packit Service a1973e
	__pfm_vbprintf("[0x%lx-0x%lx): %d register pair(s)\n", in_rr->rr_start, in_rr->rr_end, n_pairs);
Packit Service a1973e
	__pfm_vbprintf("start offset: -0x%lx end_offset: +0x%lx\n", out_rr->rr_soff, out_rr->rr_eoff);
Packit Service a1973e
Packit Service a1973e
	for (j=0; j < n_pairs; j++, base_idx += 2) {
Packit Service a1973e
Packit Service a1973e
		d.val = dbr[base_idx+1].reg_value;
Packit Service a1973e
		r_end = dbr[base_idx].reg_value+((~(d.db.db_mask)) & ~(0xffUL << 56));
Packit Service a1973e
Packit Service a1973e
		__pfm_vbprintf("brp%u:  db%u: 0x%016lx db%u: plm=0x%x mask=0x%016lx end=0x%016lx\n",
Packit Service a1973e
			dbr[base_idx].reg_num>>1,
Packit Service a1973e
			dbr[base_idx].reg_num,
Packit Service a1973e
			dbr[base_idx].reg_value,
Packit Service a1973e
			dbr[base_idx+1].reg_num,
Packit Service a1973e
			d.db.db_plm,
Packit Service a1973e
			(unsigned long) d.db.db_mask,
Packit Service a1973e
			r_end);
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
compute_normal_rr(pfmlib_ita_input_rr_t *irr, int dfl_plm, int n, int *base_idx, pfmlib_ita_output_rr_t *orr)
Packit Service a1973e
{
Packit Service a1973e
	pfmlib_ita_input_rr_desc_t *in_rr;
Packit Service a1973e
	pfmlib_ita_output_rr_desc_t *out_rr;
Packit Service a1973e
	unsigned long r_end;
Packit Service a1973e
	pfmlib_reg_t *br;
Packit Service a1973e
	dbreg_t d;
Packit Service a1973e
	int i, j, br_index, reg_idx, prev_index;
Packit Service a1973e
Packit Service a1973e
	in_rr     = irr->rr_limits;
Packit Service a1973e
	out_rr    = orr->rr_infos;
Packit Service a1973e
	br        = orr->rr_br;
Packit Service a1973e
	reg_idx   = *base_idx;
Packit Service a1973e
	br_index  = 0;
Packit Service a1973e
Packit Service a1973e
	for (i=0; i < n; i++, in_rr++, out_rr++) {
Packit Service a1973e
		/*
Packit Service a1973e
		 * running out of registers
Packit Service a1973e
		 */
Packit Service a1973e
		if (br_index == 8) break;
Packit Service a1973e
Packit Service a1973e
		prev_index = br_index;
Packit Service a1973e
Packit Service a1973e
		do_normal_rr(	in_rr->rr_start,
Packit Service a1973e
				in_rr->rr_end,
Packit Service a1973e
				br,
Packit Service a1973e
				4 - (reg_idx>>1), /* how many pairs available */
Packit Service a1973e
				0,
Packit Service a1973e
				&br_index,
Packit Service a1973e
				&reg_idx, in_rr->rr_plm ? in_rr->rr_plm : dfl_plm);
Packit Service a1973e
Packit Service a1973e
		DPRINT("br_index=%d reg_idx=%d\n", br_index, reg_idx);
Packit Service a1973e
		/*
Packit Service a1973e
		 * compute offsets
Packit Service a1973e
		 */
Packit Service a1973e
		out_rr->rr_soff = out_rr->rr_eoff = 0;
Packit Service a1973e
Packit Service a1973e
		for(j=prev_index; j < br_index; j+=2) {
Packit Service a1973e
Packit Service a1973e
			d.val = br[j+1].reg_value;
Packit Service a1973e
			r_end = br[j].reg_value+((~(d.db.db_mask)+1) & ~(0xffUL << 56));
Packit Service a1973e
Packit Service a1973e
			if (br[j].reg_value <= in_rr->rr_start)
Packit Service a1973e
				out_rr->rr_soff = in_rr->rr_start - br[j].reg_value;
Packit Service a1973e
Packit Service a1973e
			if (r_end >= in_rr->rr_end)
Packit Service a1973e
				out_rr->rr_eoff = r_end - in_rr->rr_end;
Packit Service a1973e
		}
Packit Service a1973e
Packit Service a1973e
		if (PFMLIB_VERBOSE()) print_one_range(in_rr, out_rr, br, prev_index, (br_index-prev_index)>>1);
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	/* do not have enough registers to cover all the ranges */
Packit Service a1973e
	if (br_index == 8 && i < n) return PFMLIB_ERR_TOOMANY;
Packit Service a1973e
Packit Service a1973e
	orr->rr_nbr_used = br_index;
Packit Service a1973e
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
pfm_dispatch_irange(pfmlib_input_param_t *inp, pfmlib_ita_input_param_t *mod_in, pfmlib_output_param_t *outp, pfmlib_ita_output_param_t *mod_out)
Packit Service a1973e
{
Packit Service a1973e
	pfm_ita_pmc_reg_t reg;
Packit Service a1973e
	pfmlib_ita_input_param_t *param = mod_in;
Packit Service a1973e
	pfmlib_reg_t *pc = outp->pfp_pmcs;
Packit Service a1973e
	pfmlib_ita_input_rr_t *irr;
Packit Service a1973e
	pfmlib_ita_output_rr_t *orr;
Packit Service a1973e
	int pos = outp->pfp_pmc_count;
Packit Service a1973e
	int ret, base_idx = 0;
Packit Service a1973e
	int n_intervals;
Packit Service a1973e
Packit Service a1973e
	if (param == NULL || param->pfp_ita_irange.rr_used == 0) return PFMLIB_SUCCESS;
Packit Service a1973e
Packit Service a1973e
	if (mod_out == NULL) return PFMLIB_ERR_INVAL;
Packit Service a1973e
Packit Service a1973e
	irr = &param->pfp_ita_irange;
Packit Service a1973e
	orr = &mod_out->pfp_ita_irange;
Packit Service a1973e
Packit Service a1973e
	ret = check_intervals(irr, 0, &n_intervals);
Packit Service a1973e
	if (ret != PFMLIB_SUCCESS) return ret;
Packit Service a1973e
Packit Service a1973e
	if (n_intervals < 1) return PFMLIB_ERR_IRRINVAL;
Packit Service a1973e
	
Packit Service a1973e
	DPRINT("n_intervals=%d\n", n_intervals);
Packit Service a1973e
Packit Service a1973e
	ret = compute_normal_rr(irr, inp->pfp_dfl_plm, n_intervals, &base_idx, orr);
Packit Service a1973e
	if (ret != PFMLIB_SUCCESS) {
Packit Service a1973e
		return ret == PFMLIB_ERR_TOOMANY ? PFMLIB_ERR_IRRTOOMANY : ret;
Packit Service a1973e
	}
Packit Service a1973e
	reg.pmc_val = 0;
Packit Service a1973e
Packit Service a1973e
	reg.pmc13_ita_reg.irange_ta = 0x0;
Packit Service a1973e
Packit Service a1973e
	if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 13))
Packit Service a1973e
		return PFMLIB_ERR_NOASSIGN;
Packit Service a1973e
Packit Service a1973e
	pc[pos].reg_num     = 13;
Packit Service a1973e
	pc[pos].reg_value   = reg.pmc_val;
Packit Service a1973e
	pc[pos].reg_addr    = 13;
Packit Service a1973e
	pc[pos].reg_alt_addr= 13;
Packit Service a1973e
	pos++;
Packit Service a1973e
Packit Service a1973e
	__pfm_vbprintf("[PMC13(pmc13)=0x%lx ta=%d]\n", reg.pmc_val, reg.pmc13_ita_reg.irange_ta);
Packit Service a1973e
	
Packit Service a1973e
	outp->pfp_pmc_count = pos;
Packit Service a1973e
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
	
Packit Service a1973e
static int
Packit Service a1973e
pfm_dispatch_drange(pfmlib_input_param_t *inp, pfmlib_ita_input_param_t *mod_in, pfmlib_output_param_t *outp, pfmlib_ita_output_param_t *mod_out)
Packit Service a1973e
{
Packit Service a1973e
	pfmlib_ita_input_param_t *param = mod_in;
Packit Service a1973e
	pfmlib_event_t *e = inp->pfp_events;
Packit Service a1973e
	pfmlib_reg_t *pc = outp->pfp_pmcs;
Packit Service a1973e
	pfmlib_ita_input_rr_t *irr;
Packit Service a1973e
	pfmlib_ita_output_rr_t *orr;
Packit Service a1973e
	pfm_ita_pmc_reg_t reg;
Packit Service a1973e
	unsigned int i, count;
Packit Service a1973e
	int pos = outp->pfp_pmc_count;
Packit Service a1973e
	int ret, base_idx = 0;
Packit Service a1973e
	int n_intervals;
Packit Service a1973e
Packit Service a1973e
	if (param == NULL || param->pfp_ita_drange.rr_used == 0) return PFMLIB_SUCCESS;
Packit Service a1973e
Packit Service a1973e
	if (mod_out == NULL) return PFMLIB_ERR_INVAL;
Packit Service a1973e
Packit Service a1973e
	irr = &param->pfp_ita_drange;
Packit Service a1973e
	orr = &mod_out->pfp_ita_drange;
Packit Service a1973e
Packit Service a1973e
	ret = check_intervals(irr, 1 , &n_intervals);
Packit Service a1973e
	if (ret != PFMLIB_SUCCESS) return ret;
Packit Service a1973e
Packit Service a1973e
	if (n_intervals < 1) return PFMLIB_ERR_DRRINVAL;
Packit Service a1973e
	
Packit Service a1973e
	DPRINT("n_intervals=%d\n", n_intervals);
Packit Service a1973e
Packit Service a1973e
	ret = compute_normal_rr(irr, inp->pfp_dfl_plm, n_intervals, &base_idx, orr);
Packit Service a1973e
	if (ret != PFMLIB_SUCCESS) {
Packit Service a1973e
		return ret == PFMLIB_ERR_TOOMANY ? PFMLIB_ERR_DRRTOOMANY : ret;
Packit Service a1973e
	}
Packit Service a1973e
	count = inp->pfp_event_count;
Packit Service a1973e
	for (i=0; i < count; i++) {
Packit Service a1973e
		if (is_dear(e[i].event)) return PFMLIB_SUCCESS; /* will be done there */
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	reg.pmc_val = 0UL;
Packit Service a1973e
	/*
Packit Service a1973e
	 * here we have no other choice but to use the default priv level as there is no
Packit Service a1973e
	 * specific D-EAR event provided
Packit Service a1973e
	 */
Packit Service a1973e
	reg.pmc11_ita_reg.dear_plm = inp->pfp_dfl_plm;
Packit Service a1973e
Packit Service a1973e
	if (pfm_regmask_isset(&inp->pfp_unavail_pmcs, 11))
Packit Service a1973e
		return PFMLIB_ERR_NOASSIGN;
Packit Service a1973e
Packit Service a1973e
	pc[pos].reg_num     = 11;
Packit Service a1973e
	pc[pos].reg_value   = reg.pmc_val;
Packit Service a1973e
	pc[pos].reg_addr    = 11;
Packit Service a1973e
	pc[pos].reg_alt_addr= 11;
Packit Service a1973e
	pos++;
Packit Service a1973e
Packit Service a1973e
	__pfm_vbprintf("[PMC11(pmc11)=0x%lx tlb=%s plm=%d pm=%d ism=0x%x umask=0x%x pt=%d]\n",
Packit Service a1973e
			reg.pmc_val,
Packit Service a1973e
			reg.pmc11_ita_reg.dear_tlb ? "Yes" : "No",
Packit Service a1973e
			reg.pmc11_ita_reg.dear_plm,	
Packit Service a1973e
			reg.pmc11_ita_reg.dear_pm,
Packit Service a1973e
			reg.pmc11_ita_reg.dear_ism,
Packit Service a1973e
			reg.pmc11_ita_reg.dear_umask,
Packit Service a1973e
			reg.pmc11_ita_reg.dear_pt);
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
	outp->pfp_pmc_count = pos;
Packit Service a1973e
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
check_qualifier_constraints(pfmlib_input_param_t *inp, pfmlib_ita_input_param_t *mod_in)
Packit Service a1973e
{
Packit Service a1973e
	pfmlib_event_t *e = inp->pfp_events;
Packit Service a1973e
	unsigned int i, count;
Packit Service a1973e
Packit Service a1973e
	count = inp->pfp_event_count;
Packit Service a1973e
	for(i=0; i < count; i++) {
Packit Service a1973e
		/*
Packit Service a1973e
		 * skip check for counter which requested it. Use at your own risk.
Packit Service a1973e
		 * No all counters have necessarily been validated for use with
Packit Service a1973e
		 * qualifiers. Typically the event is counted as if no constraint
Packit Service a1973e
		 * existed.
Packit Service a1973e
		 */
Packit Service a1973e
		if (mod_in->pfp_ita_counters[i].flags & PFMLIB_ITA_FL_EVT_NO_QUALCHECK) continue;
Packit Service a1973e
Packit Service a1973e
		if (evt_use_irange(mod_in) && has_iarr(e[i].event) == 0) return PFMLIB_ERR_FEATCOMB;
Packit Service a1973e
		if (evt_use_drange(mod_in) && has_darr(e[i].event) == 0) return PFMLIB_ERR_FEATCOMB;
Packit Service a1973e
		if (evt_use_opcm(mod_in) && has_opcm(e[i].event) == 0) return PFMLIB_ERR_FEATCOMB;
Packit Service a1973e
	}
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
check_range_plm(pfmlib_input_param_t *inp, pfmlib_ita_input_param_t *mod_in)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int i, count;
Packit Service a1973e
Packit Service a1973e
	if (mod_in->pfp_ita_drange.rr_used == 0 && mod_in->pfp_ita_irange.rr_used == 0) return PFMLIB_SUCCESS;
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * range restriction applies to all events, therefore we must have a consistent
Packit Service a1973e
	 * set of plm and they must match the pfp_dfl_plm which is used to setup the debug
Packit Service a1973e
	 * registers
Packit Service a1973e
	 */
Packit Service a1973e
	count = inp->pfp_event_count;
Packit Service a1973e
	for(i=0; i < count; i++) {
Packit Service a1973e
		if (inp->pfp_events[i].plm  && inp->pfp_events[i].plm != inp->pfp_dfl_plm) return PFMLIB_ERR_FEATCOMB;
Packit Service a1973e
	}
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
pfm_ita_dispatch_events(pfmlib_input_param_t *inp, void *model_in, pfmlib_output_param_t *outp, void *model_out)
Packit Service a1973e
{
Packit Service a1973e
	int ret;
Packit Service a1973e
	pfmlib_ita_input_param_t *mod_in  = (pfmlib_ita_input_param_t *)model_in;
Packit Service a1973e
	pfmlib_ita_output_param_t *mod_out = (pfmlib_ita_output_param_t *)model_out;
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * nothing will come out of this combination
Packit Service a1973e
	 */
Packit Service a1973e
	if (mod_out && mod_in == NULL) return PFMLIB_ERR_INVAL;
Packit Service a1973e
Packit Service a1973e
	/* check opcode match, range restriction qualifiers */
Packit Service a1973e
	if (mod_in && check_qualifier_constraints(inp, mod_in) != PFMLIB_SUCCESS) return PFMLIB_ERR_FEATCOMB;
Packit Service a1973e
Packit Service a1973e
	/* check for problems with raneg restriction and per-event plm */
Packit Service a1973e
	if (mod_in && check_range_plm(inp, mod_in) != PFMLIB_SUCCESS) return PFMLIB_ERR_FEATCOMB;
Packit Service a1973e
Packit Service a1973e
	ret = pfm_ita_dispatch_counters(inp, mod_in, outp);
Packit Service a1973e
	if (ret != PFMLIB_SUCCESS) return ret;
Packit Service a1973e
Packit Service a1973e
	/* now check for I-EAR */
Packit Service a1973e
	ret = pfm_dispatch_iear(inp, mod_in, outp);
Packit Service a1973e
	if (ret != PFMLIB_SUCCESS) return ret;
Packit Service a1973e
Packit Service a1973e
	/* now check for D-EAR */
Packit Service a1973e
	ret = pfm_dispatch_dear(inp, mod_in, outp);
Packit Service a1973e
	if (ret != PFMLIB_SUCCESS) return ret;
Packit Service a1973e
Packit Service a1973e
	/* now check for Opcode matchers */
Packit Service a1973e
	ret = pfm_dispatch_opcm(inp, mod_in, outp);
Packit Service a1973e
	if (ret != PFMLIB_SUCCESS) return ret;
Packit Service a1973e
Packit Service a1973e
	ret = pfm_dispatch_btb(inp, mod_in, outp);
Packit Service a1973e
	if (ret != PFMLIB_SUCCESS) return ret;
Packit Service a1973e
Packit Service a1973e
	ret = pfm_dispatch_irange(inp, mod_in, outp, mod_out);;
Packit Service a1973e
	if (ret != PFMLIB_SUCCESS) return ret;
Packit Service a1973e
Packit Service a1973e
	ret = pfm_dispatch_drange(inp, mod_in, outp, mod_out);;
Packit Service a1973e
Packit Service a1973e
	return ret;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* XXX: return value is also error code */
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_get_event_maxincr(unsigned int i, unsigned int *maxincr)
Packit Service a1973e
{
Packit Service a1973e
	if (i >= PME_ITA_EVENT_COUNT || maxincr == NULL) return PFMLIB_ERR_INVAL;
Packit Service a1973e
	*maxincr = itanium_pe[i].pme_maxincr;
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_is_ear(unsigned int i)
Packit Service a1973e
{
Packit Service a1973e
	return i >= PME_ITA_EVENT_COUNT || ! is_ear(i) ? 0 : 1;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_is_dear(unsigned int i)
Packit Service a1973e
{
Packit Service a1973e
	return i >= PME_ITA_EVENT_COUNT || ! is_dear(i) ? 0 : 1;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_is_dear_tlb(unsigned int i)
Packit Service a1973e
{
Packit Service a1973e
	return i >= PME_ITA_EVENT_COUNT || ! (is_dear(i) && is_ear_tlb(i)) ? 0 : 1;
Packit Service a1973e
}
Packit Service a1973e
	
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_is_dear_cache(unsigned int i)
Packit Service a1973e
{
Packit Service a1973e
	return i >= PME_ITA_EVENT_COUNT || ! (is_dear(i) && !is_ear_tlb(i)) ? 0 : 1;
Packit Service a1973e
}
Packit Service a1973e
	
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_is_iear(unsigned int i)
Packit Service a1973e
{
Packit Service a1973e
	return i >= PME_ITA_EVENT_COUNT || ! is_iear(i) ? 0 : 1;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_is_iear_tlb(unsigned int i)
Packit Service a1973e
{
Packit Service a1973e
	return i >= PME_ITA_EVENT_COUNT || ! (is_iear(i) && is_ear_tlb(i)) ? 0 : 1;
Packit Service a1973e
}
Packit Service a1973e
	
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_is_iear_cache(unsigned int i)
Packit Service a1973e
{
Packit Service a1973e
	return i >= PME_ITA_EVENT_COUNT || ! (is_iear(i) && !is_ear_tlb(i)) ? 0 : 1;
Packit Service a1973e
}
Packit Service a1973e
	
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_is_btb(unsigned int i)
Packit Service a1973e
{
Packit Service a1973e
	return i >= PME_ITA_EVENT_COUNT || ! is_btb(i) ? 0 : 1;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_support_iarr(unsigned int i)
Packit Service a1973e
{
Packit Service a1973e
	return i >= PME_ITA_EVENT_COUNT || ! has_iarr(i) ? 0 : 1;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_support_darr(unsigned int i)
Packit Service a1973e
{
Packit Service a1973e
	return i >= PME_ITA_EVENT_COUNT || ! has_darr(i) ? 0 : 1;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_support_opcm(unsigned int i)
Packit Service a1973e
{
Packit Service a1973e
	return i >= PME_ITA_EVENT_COUNT || ! has_opcm(i) ? 0 : 1;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_get_ear_mode(unsigned int i, pfmlib_ita_ear_mode_t *m)
Packit Service a1973e
{
Packit Service a1973e
	if (!is_ear(i) || m == NULL) return PFMLIB_ERR_INVAL;
Packit Service a1973e
Packit Service a1973e
	*m = is_ear_tlb(i) ? PFMLIB_ITA_EAR_TLB_MODE : PFMLIB_ITA_EAR_CACHE_MODE;
Packit Service a1973e
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
pfm_ita_get_event_code(unsigned int i, unsigned int cnt, int *code)
Packit Service a1973e
{
Packit Service a1973e
	if (cnt != PFMLIB_CNT_FIRST && (cnt < 4 || cnt > 7))
Packit Service a1973e
		return PFMLIB_ERR_INVAL;
Packit Service a1973e
Packit Service a1973e
	*code = (int)itanium_pe[i].pme_code;
Packit Service a1973e
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * This function is accessible directly to the user
Packit Service a1973e
 */
Packit Service a1973e
int
Packit Service a1973e
pfm_ita_get_event_umask(unsigned int i, unsigned long *umask)
Packit Service a1973e
{
Packit Service a1973e
	if (i >= PME_ITA_EVENT_COUNT || umask == NULL) return PFMLIB_ERR_INVAL;
Packit Service a1973e
	*umask = evt_umask(i);
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
	
Packit Service a1973e
static char *
Packit Service a1973e
pfm_ita_get_event_name(unsigned int i)
Packit Service a1973e
{
Packit Service a1973e
	return itanium_pe[i].pme_name;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void
Packit Service a1973e
pfm_ita_get_event_counters(unsigned int j, pfmlib_regmask_t *counters)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int i;
Packit Service a1973e
	unsigned long m;
Packit Service a1973e
Packit Service a1973e
	memset(counters, 0, sizeof(*counters));
Packit Service a1973e
Packit Service a1973e
	m =itanium_pe[j].pme_counters;
Packit Service a1973e
	for(i=0; m ; i++, m>>=1) {
Packit Service a1973e
		if (m & 0x1)
Packit Service a1973e
			pfm_regmask_set(counters, i);
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void
Packit Service a1973e
pfm_ita_get_impl_pmcs(pfmlib_regmask_t *impl_pmcs)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int i = 0;
Packit Service a1973e
Packit Service a1973e
	/* all pmcs are contiguous */
Packit Service a1973e
	for(i=0; i < PMU_ITA_NUM_PMCS; i++)
Packit Service a1973e
		pfm_regmask_set(impl_pmcs, i);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void
Packit Service a1973e
pfm_ita_get_impl_pmds(pfmlib_regmask_t *impl_pmds)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int i = 0;
Packit Service a1973e
Packit Service a1973e
	/* all pmds are contiguous */
Packit Service a1973e
	for(i=0; i < PMU_ITA_NUM_PMDS; i++)
Packit Service a1973e
		pfm_regmask_set(impl_pmds, i);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void
Packit Service a1973e
pfm_ita_get_impl_counters(pfmlib_regmask_t *impl_counters)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int i = 0;
Packit Service a1973e
Packit Service a1973e
	/* counting pmds are contiguous */
Packit Service a1973e
	for(i=4; i < 8; i++)
Packit Service a1973e
		pfm_regmask_set(impl_counters, i);
Packit Service a1973e
}
Packit Service a1973e
	
Packit Service a1973e
static void
Packit Service a1973e
pfm_ita_get_hw_counter_width(unsigned int *width)
Packit Service a1973e
{
Packit Service a1973e
	*width = PMU_ITA_COUNTER_WIDTH;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
pfm_ita_get_cycle_event(pfmlib_event_t *e)
Packit Service a1973e
{
Packit Service a1973e
	e->event = PME_ITA_CPU_CYCLES;
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int
Packit Service a1973e
pfm_ita_get_inst_retired(pfmlib_event_t *e)
Packit Service a1973e
{
Packit Service a1973e
	e->event = PME_ITA_IA64_INST_RETIRED;
Packit Service a1973e
	return PFMLIB_SUCCESS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
pfm_pmu_support_t itanium_support={
Packit Service a1973e
	.pmu_name		= "itanium",
Packit Service a1973e
	.pmu_type		= PFMLIB_ITANIUM_PMU,
Packit Service a1973e
	.pme_count		= PME_ITA_EVENT_COUNT,
Packit Service a1973e
	.pmc_count		= PMU_ITA_NUM_PMCS,
Packit Service a1973e
	.pmd_count		= PMU_ITA_NUM_PMDS,
Packit Service a1973e
	.num_cnt		= PMU_ITA_NUM_COUNTERS,
Packit Service a1973e
	.get_event_code		= pfm_ita_get_event_code,
Packit Service a1973e
	.get_event_name		= pfm_ita_get_event_name,
Packit Service a1973e
	.get_event_counters	= pfm_ita_get_event_counters,
Packit Service a1973e
	.dispatch_events	= pfm_ita_dispatch_events,
Packit Service a1973e
	.pmu_detect		= pfm_ita_detect,
Packit Service a1973e
	.get_impl_pmcs		= pfm_ita_get_impl_pmcs,
Packit Service a1973e
	.get_impl_pmds		= pfm_ita_get_impl_pmds,
Packit Service a1973e
	.get_impl_counters	= pfm_ita_get_impl_counters,
Packit Service a1973e
	.get_hw_counter_width	= pfm_ita_get_hw_counter_width,
Packit Service a1973e
	.get_cycle_event	= pfm_ita_get_cycle_event,
Packit Service a1973e
	.get_inst_retired_event = pfm_ita_get_inst_retired
Packit Service a1973e
	/* no event description available for Itanium */
Packit Service a1973e
};