Beispiel #1
0
static int
prepare_btb(pfmon_event_set_t *set)
{
	pfmlib_ita_input_param_t *param = set->mod_inp;
	unsigned int i;
	int found_btb = -1;

	for(i=0; i < set->event_count; i++) {
		if (pfm_ita_is_btb(set->inp.pfp_events[i].event)) {
			found_btb = i;
			goto found;
		}
	}
	/*
	 * check for no BTB event, but just BTB options.
	 */
	if (param->pfp_ita_btb.btb_used == 0) return 0;
found:
	/*
	 * in case of no BTB event found, we are in free running mode (no BTB sampling)
	 * therefore we include the BTB PMD in all samples
	 */
	if (found_btb != -1 && (set->short_rates[i].flags & PFMON_RATE_VAL_SET)) {
		set->smpl_pmds[i][0]  	  |=  BTB_REGS_MASK;
		set->common_reset_pmds[0] |=  M_PMD(16);
	} else {
		set->common_smpl_pmds[0]  |=  BTB_REGS_MASK;
		set->common_reset_pmds[0] |=  BTB_REGS_MASK;
	}
	return 0;
}
Beispiel #2
0
static int
prepare_ears(pfmon_event_set_t *set)
{
	unsigned int i;
	int ev, is_iear;

	/*
	 * search for an EAR event
	 */
	for(i=0; i < set->event_count; i++) {

		ev = set->inp.pfp_events[i].event;

		/* look for EAR event */
		if (pfm_ita_is_ear(ev) == 0) continue;

		is_iear = pfm_ita_is_iear(ev);

		/*
		 * when used as sampling period, then just setup the bitmask
		 * of PMDs to record in each sample
		 */
		if (set->short_rates[i].flags & PFMON_RATE_VAL_SET) {
			set->smpl_pmds[i][0]  |=  is_iear ? IEAR_REGS_MASK : DEAR_REGS_MASK;
			continue;
		}

		/*
		 * for D-EAR, we must clear PMD3.stat and PMD17.vl to make
		 * sure we do not interpret the register in the wrong manner.
		 *
		 * for I-EAR, we must clear PMD0.stat to avoid interpreting stale
		 * entries
		 *
		 * This is ONLY necessary when the events are not used as sampling
		 * periods.
		 */
		set->common_reset_pmds[0] |= is_iear ? M_PMD(0) : M_PMD(17) | M_PMD(3);
	}
	return 0;
}
int
main(void)
{
	int ret;
	int type = 0;
	pid_t pid = getpid();
	pfmlib_ita2_param_t ita_param;
	pfarg_reg_t pd[NUM_PMDS];
	pfarg_context_t ctx[1];
	pfmlib_options_t pfmlib_options;
	struct sigaction act;

	/*
	 * Initialize pfm library (required before we can use it)
	 */
	if (pfm_initialize() != PFMLIB_SUCCESS) {
		fatal_error("Can't initialize library\n");
	}

	/*
	 * Let's make sure we run this on the right CPU
	 */
	pfm_get_pmu_type(&type);
	if (type != PFMLIB_ITANIUM2_PMU) {
		char *model; 
		pfm_get_pmu_name(&model);
		fatal_error("this program does not work with %s PMU\n", model);
	}

	/*
	 * Install the overflow handler (SIGPROF)
	 */
	memset(&act, 0, sizeof(act));
	act.sa_handler = (sig_t)overflow_handler;
	sigaction (SIGPROF, &act, 0);


	/*
	 * pass options to library (optional)
	 */
	memset(&pfmlib_options, 0, sizeof(pfmlib_options));
	pfmlib_options.pfm_debug = 0; /* set to 1 for debug */
	pfmlib_options.pfm_verbose = 0; /* set to 1 for debug */
	pfm_set_options(&pfmlib_options);



	memset(pd, 0, sizeof(pd));
	memset(ctx, 0, sizeof(ctx));

	/*
	 * prepare parameters to library. we don't use any Itanium
	 * specific features here. so the pfp_model is NULL.
	 */
	memset(&evt,0, sizeof(evt));
	memset(&ita_param,0, sizeof(ita_param));


	/*
	 * because we use a model specific feature, we must initialize the
	 * model specific pfmlib parameter structure and link it to the
	 * common structure.
	 * The magic number is a simple mechanism used by the library to check
	 * that the model specific data structure is decent. You must set it manually
	 * otherwise the model specific feature won't work.
	 */
	ita_param.pfp_magic = PFMLIB_ITA2_PARAM_MAGIC;
	evt.pfp_model       = &ita_param;

	/*
	 * Before calling pfm_find_dispatch(), we must specify what kind
	 * of branches we want to capture. We are interesteed in all the mispredicted branches, 
	 * therefore we program we set the various fields of the BTB config to:
	 */
	ita_param.pfp_ita2_btb.btb_used = 1;

	ita_param.pfp_ita2_btb.btb_ds  = 0;
	ita_param.pfp_ita2_btb.btb_tm  = 0x3;
	ita_param.pfp_ita2_btb.btb_ptm = 0x3;
	ita_param.pfp_ita2_btb.btb_ppm = 0x3;
	ita_param.pfp_ita2_btb.btb_brt = 0x0;
	ita_param.pfp_ita2_btb.btb_plm = PFM_PLM3;

	/*
	 * To count the number of occurence of this instruction, we must
	 * program a counting monitor with the IA64_TAGGED_INST_RETIRED_PMC8
	 * event.
	 */
	if (pfm_find_event_byname("BRANCH_EVENT", &evt.pfp_events[0].event) != PFMLIB_SUCCESS) {
		fatal_error("cannot find event BRANCH_EVENT\n");
	}

	/*
	 * set the (global) privilege mode:
	 * 	PFM_PLM3 : user level only
	 */
	evt.pfp_dfl_plm   = PFM_PLM3; 
	/*
	 * how many counters we use
	 */
	evt.pfp_event_count = 1;

	/*
	 * let the library figure out the values for the PMCS
	 */
	if ((ret=pfm_dispatch_events(&evt)) != PFMLIB_SUCCESS) {
		fatal_error("cannot configure events: %s\n", pfm_strerror(ret));
	}
	/*
	 * for this example, we will get notified ONLY when the sampling
	 * buffer is full. The monitoring is not to be inherited
	 * in derived tasks
	 */
	ctx[0].ctx_flags        = PFM_FL_INHERIT_NONE;
	ctx[0].ctx_notify_pid   = getpid();
	ctx[0].ctx_smpl_entries = SMPL_BUF_NENTRIES;
	ctx[0].ctx_smpl_regs[0] = smpl_regs = BTB_REGS_MASK;


	/*
	 * now create the context for self monitoring/per-task
	 */
	if (perfmonctl(pid, PFM_CREATE_CONTEXT, ctx, 1) == -1 ) {
		if (errno == ENOSYS) {
			fatal_error("Your kernel does not have performance monitoring support!\n");
		}
		fatal_error("Can't create PFM context %s\n", strerror(errno));
	}

	printf("Sampling buffer mapped at %p\n", ctx[0].ctx_smpl_vaddr);

	smpl_vaddr = ctx[0].ctx_smpl_vaddr;

	/* 
	 * Must be done before any PMD/PMD calls (unfreeze PMU). Initialize
	 * PMC/PMD to safe values. psr.up is cleared.
	 */
	if (perfmonctl(pid, PFM_ENABLE, NULL, 0) == -1) {
		fatal_error("perfmonctl error PFM_ENABLE errno %d\n",errno);
	}

	/*
	 * indicate we want notification when buffer is full
	 */
	evt.pfp_pc[0].reg_flags |= PFM_REGFL_OVFL_NOTIFY;

	/*
	 * Now prepare the argument to initialize the PMD and the sampling period
	 */
	pd[0].reg_num         = evt.pfp_pc[0].reg_num;
	pd[0].reg_value       = (~0UL) - SMPL_PERIOD +1;
	pd[0].reg_long_reset  = (~0UL) - SMPL_PERIOD +1;
	pd[0].reg_short_reset = (~0UL) - SMPL_PERIOD +1;

	/*
	 * When our counter overflows, we want to BTB index to be reset, so that we keep
	 * in sync. This is required to make it possible to interpret pmd16 on overflow
	 * to avoid repeating the same branch several times.
	 */
	evt.pfp_pc[0].reg_reset_pmds[0] = M_PMD(16);

	/*
	 * reset pmd16, short and long reset value are set to zero as well
	 */
	pd[1].reg_num         = 16;
	pd[1].reg_value       = 0UL;

	/*
	 * Now program the registers
	 *
	 * We don't use the save variable to indicate the number of elements passed to
	 * the kernel because, as we said earlier, pc may contain more elements than
	 * the number of events we specified, i.e., contains more thann coutning monitors.
	 */
	if (perfmonctl(pid, PFM_WRITE_PMCS, evt.pfp_pc, evt.pfp_pc_count) == -1) {
		fatal_error("perfmonctl error PFM_WRITE_PMCS errno %d\n",errno);
	}
	if (perfmonctl(pid, PFM_WRITE_PMDS, pd, 2) == -1) {
		fatal_error("perfmonctl error PFM_WRITE_PMDS errno %d\n",errno);
	}

	/*
	 * Let's roll now.
	 */

	do_test(100000);

	/*
	 * We must call the processing routine to cover the last entries recorded
	 * in the sampling buffer, i.e. which may not be full
	 */
	process_smpl_buffer();

	/* 
	 * let's stop this now
	 */
	if (perfmonctl(pid, PFM_DESTROY_CONTEXT, NULL, 0) == -1) {
		fatal_error("perfmonctl error PFM_DESTROY errno %d\n",errno);
	}
	return 0;
}