static inline void vperfctr_handle_overflow(struct task_struct *tsk,
				     struct vperfctr *perfctr)
{
	unsigned int pmc_mask;
	siginfo_t si;
	sigset_t old_blocked;

	pmc_mask = perfctr_cpu_identify_overflow(&perfctr->cpu_state);
	if (!pmc_mask) {
		printk(KERN_ERR "%s: BUG! pid %d has unidentifiable overflow source\n", __FUNCTION__, tsk->pid);
		return;
	}
	/* suspend a-mode and i-mode PMCs, leaving only TSC on */
	/* XXX: some people also want to suspend the TSC */

	// we are storing 'cpu_state.cstatus' in 'iresume_cstatus' because
	// in vperfctr_resume, we only want to read the status of those
	// In the following TSC is resumed and continues to collect the
	// stats

	// if 'perfctr->iresume_cstatus' is not updated below, vperfctr_iresume() fails
	// as it thinks it was spuriously called inspite of absence of i-mode counters.
	// vperfctr_iresume() -> ... -> do_vperfctr_iresume() is a different thread of
	// execution from vperfctr_resume() -> ... -> vperfctr_iresume() -> __write_control() ->
	// ...
	perfctr->iresume_cstatus = perfctr->cpu_state.cstatus;

	if (perfctr_cstatus_has_tsc(perfctr->iresume_cstatus)) {
		perfctr->cpu_state.cstatus = perfctr_mk_cstatus(1, 0, 0);
		vperfctr_resume(perfctr);
	} 
	else {
		perfctr->cpu_state.cstatus = 0;
	}

	// the following siginfo_t structure helps the kernel in invoking
	// the correct signal handler. Is that right ?
	// what's the deal with si_errno? what does it say ? si_code ?

	si.si_signo = perfctr->si_signo;
	si.si_errno = 0;
	si.si_code = SI_PMC_OVF;
	si.si_pmc_ovf_mask = pmc_mask;

	/* deliver signal without waking up the receiver */
	spin_lock_irq(&tsk->sighand->siglock);
	old_blocked = tsk->blocked;
	sigaddset(&tsk->blocked, si.si_signo);
	spin_unlock_irq(&tsk->sighand->siglock);

	if (!send_sig_info(si.si_signo, &si, tsk)) {
		send_sig(si.si_signo, tsk, 1);
	}

	spin_lock_irq(&tsk->sighand->siglock);
	tsk->blocked = old_blocked;
	recalc_sigpending();
	spin_unlock_irq(&tsk->sighand->siglock);
}
Esempio n. 2
0
static void vperfctr_handle_overflow(struct task_struct *tsk,
				     struct vperfctr *perfctr)
{
	unsigned int pmc_mask;
	siginfo_t si;
	sigset_t old_blocked;

	pmc_mask = perfctr_cpu_identify_overflow(&perfctr->cpu_state);
	if (!pmc_mask) {
#ifdef CONFIG_PPC64
		/* On some hardware (ppc64, in particular) it's
		 * impossible to control interrupts finely enough to
		 * eliminate overflows on counters we don't care
		 * about.  So in this case just restart the counters
		 * and keep going. */
		vperfctr_resume(perfctr);
#else
		printk(KERN_ERR "%s: BUG! pid %d has unidentifiable overflow source\n",
		       __FUNCTION__, tsk->id);
#endif
		return;
	}
	perfctr->ireload_needed = 1;
	/* suspend a-mode and i-mode PMCs, leaving only TSC on */
	/* XXX: some people also want to suspend the TSC */
	perfctr->resume_cstatus = perfctr->cpu_state.user.cstatus;
	if (perfctr_cstatus_has_tsc(perfctr->resume_cstatus)) {
		perfctr->cpu_state.user.cstatus = perfctr_mk_cstatus(1, 0, 0);
		vperfctr_resume(perfctr);
	} else
		perfctr->cpu_state.user.cstatus = 0;
	si.si_signo = perfctr->si_signo;
	si.si_errno = 0;
	si.si_code = SI_PMC_OVF;
	si.si_pmc_ovf_mask = pmc_mask;

	/* deliver signal without waking up the receiver */
	spin_lock_irq(&tsk->sighand->siglock);
	old_blocked = tsk->blocked;
	sigaddset(&tsk->blocked, si.si_signo);
	spin_unlock_irq(&tsk->sighand->siglock);

	if (!send_sig_info(si.si_signo, &si, tsk))
		send_sig(si.si_signo, tsk, 1);

	spin_lock_irq(&tsk->sighand->siglock);
	tsk->blocked = old_blocked;
	recalc_sigpending();
	spin_unlock_irq(&tsk->sighand->siglock);
}
Esempio n. 3
0
static void vperfctr_handle_overflow(struct task_struct *tsk,
				     struct vperfctr *perfctr)
{
	unsigned int pmc_mask;
	siginfo_t si;
	sigset_t old_blocked;

	pmc_mask = perfctr_cpu_identify_overflow(&perfctr->cpu_state);
	if (!pmc_mask) {
		printk(KERN_ERR "%s: BUG! pid %d has unidentifiable overflow source\n",
		       __FUNCTION__, tsk->pid);
		return;
	}
	/* suspend a-mode and i-mode PMCs, leaving only TSC on */
	/* XXX: some people also want to suspend the TSC */
	perfctr->iresume_cstatus = perfctr->cpu_state.cstatus;
	if (perfctr_cstatus_has_tsc(perfctr->iresume_cstatus)) {
		perfctr->cpu_state.cstatus = perfctr_mk_cstatus(1, 0, 0);
		vperfctr_resume(perfctr);
	} else
		perfctr->cpu_state.cstatus = 0;
	si.si_signo = perfctr->si_signo;
	si.si_errno = 0;
	si.si_code = SI_PMC_OVF;
	si.si_pmc_ovf_mask = pmc_mask;

	/* deliver signal without waking up the receiver */
	spin_lock_irq(&task_siglock(tsk));
	old_blocked = tsk->blocked;
	sigaddset(&tsk->blocked, si.si_signo);
	spin_unlock_irq(&task_siglock(tsk));

	if (!send_sig_info(si.si_signo, &si, tsk))
		send_sig(si.si_signo, tsk, 1);

	spin_lock_irq(&task_siglock(tsk));
	tsk->blocked = old_blocked;
	recalc_sigpending();
	spin_unlock_irq(&task_siglock(tsk));
}
Esempio n. 4
0
int perfctr_cpu_update_control(struct perfctr_cpu_state *state, int is_global)
{
    int err;

    // since we updated the control, we invalidate the cpu id in the state
    // so that we can force reload of control registers
    clear_isuspend_cpu(state);
    state->cstatus = 0;

    /* disallow i-mode counters if we cannot catch the interrupts */
    if (!(perfctr_info.cpu_features & PERFCTR_FEATURE_PCINT)
        && state->control.nrictrs) {
        
        return -EPERM;
    }

    err = check_ireset(state);
    if (err < 0) {
        return err;
    }
    err = check_control(state); /* may initialise state->cstatus */
    if (err < 0) {
        return err;
    }

    // Ok, while the map values and the start values for i-mode counters
    // are updated in the above function check_control() and the following
    // function setup_imode_start_values(), the 'cstatus' values is set here

    // how do u ensure that all i-mode registers are specified beyond a-mode
    // registers
    state->cstatus |= perfctr_mk_cstatus(state->control.tsc_on,
                         state->control.nractrs,
                         state->control.nrictrs);
    setup_imode_start_values(state);
    return 0;
}