static int
xenoprof_handler(struct task_struct *task, void *buf, pfm_ovfl_arg_t *arg,
                 struct pt_regs *regs, unsigned long stamp)
{
    unsigned long ip = profile_pc(regs);
    int event = arg->pmd_eventid;
    struct vcpu *v = current;
    int mode = xenoprofile_get_mode(v, regs);

    // see pfm_do_interrupt_handler() in xen/arch/ia64/linux-xen/perfmon.c.
    // It always passes task as NULL. This is work around
    BUG_ON(task != NULL);

    arg->ovfl_ctrl.bits.reset_ovfl_pmds = 1;
    if (!allow_virq || !allow_ints)
        return 0;

    // Note that log event actually expect cpu_user_regs, cast back 
    // appropriately when doing the backtrace implementation in ia64
    xenoprof_log_event(v, regs, ip, mode, event);
    // send VIRQ_XENOPROF
    if (is_active(v->domain) && !xenoprof_is_xen_mode(v, regs) &&
        !is_idle_vcpu(v))
        send_guest_vcpu_virq(v, VIRQ_XENOPROF);

    return 0;
}
Exemple #2
0
static int ppro_check_ctrs(unsigned int const cpu,
                           struct op_msrs const * const msrs,
                           struct cpu_user_regs const * const regs)
{
	u64 val;
	int i;
	int ovf = 0;
	unsigned long eip = regs->eip;
	int mode = xenoprofile_get_mode(current, regs);
	struct arch_msr_pair *msrs_content = vcpu_vpmu(current)->context;

	for (i = 0 ; i < num_counters; ++i) {
		if (!reset_value[i])
			continue;
		rdmsrl(msrs->counters[i].addr, val);
		if (CTR_OVERFLOWED(val)) {
			xenoprof_log_event(current, regs, eip, mode, i);
			wrmsrl(msrs->counters[i].addr, -reset_value[i]);
			if ( is_passive(current->domain) && (mode != 2) &&
				vpmu_is_set(vcpu_vpmu(current),
                                            VPMU_PASSIVE_DOMAIN_ALLOCATED) )
			{
				if ( IS_ACTIVE(msrs_content[i].control) )
				{
					msrs_content[i].counter = val;
					if ( IS_ENABLE(msrs_content[i].control) )
						ovf = 2;
				}
			}
			if ( !ovf )
				ovf = 1;
		}
	}

	/* Only P6 based Pentium M need to re-unmask the apic vector but it
	 * doesn't hurt other P6 variant */
	apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);

	return ovf;
}