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; }
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; }