perf: accumulate counter in overflow handler
Change-Id: If5f5a913e0fde889d1835ffb16c19ea0ad5e685a
This commit is contained in:
@ -491,6 +491,11 @@ static inline int armv8pmu_has_overflowed(uint32_t pmovsr)
|
|||||||
return pmovsr & ARMV8_PMU_OVERFLOWED_MASK;
|
return pmovsr & ARMV8_PMU_OVERFLOWED_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int armv8pmu_counter_has_overflowed(uint32_t pmnc, int idx)
|
||||||
|
{
|
||||||
|
return pmnc & BIT(idx);
|
||||||
|
}
|
||||||
|
|
||||||
/* @ref.impl linux-v4.15-rc3 arch/arm64/kernel/perf_event.c */
|
/* @ref.impl linux-v4.15-rc3 arch/arm64/kernel/perf_event.c */
|
||||||
static int __armv8_pmuv3_map_event(uint32_t type, uint64_t config,
|
static int __armv8_pmuv3_map_event(uint32_t type, uint64_t config,
|
||||||
const unsigned int (*extra_event_map)
|
const unsigned int (*extra_event_map)
|
||||||
@ -781,14 +786,11 @@ static uint32_t armv8pmu_read_num_pmnc_events(void)
|
|||||||
|
|
||||||
static void armv8pmu_handle_irq(void *priv)
|
static void armv8pmu_handle_irq(void *priv)
|
||||||
{
|
{
|
||||||
struct siginfo info;
|
|
||||||
uint32_t pmovsr;
|
uint32_t pmovsr;
|
||||||
struct thread *thread = cpu_local_var(current);
|
struct thread *thread = cpu_local_var(current);
|
||||||
struct process *proc = thread->proc;
|
struct process *proc = thread->proc;
|
||||||
long irqstate;
|
const struct per_cpu_arm_pmu *cpu_pmu = get_per_cpu_pmu();
|
||||||
struct mckfd *fdp;
|
int idx;
|
||||||
struct pt_regs *regs = (struct pt_regs *)priv;
|
|
||||||
struct mc_perf_event *event = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get and reset the IRQ flags
|
* Get and reset the IRQ flags
|
||||||
@ -801,29 +803,36 @@ static void armv8pmu_handle_irq(void *priv)
|
|||||||
if (!armv8pmu_has_overflowed(pmovsr))
|
if (!armv8pmu_has_overflowed(pmovsr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!proc->monitoring_event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Handle the counter(s) overflow(s)
|
* Handle the counter(s) overflow(s)
|
||||||
*/
|
*/
|
||||||
/* same as x86_64 mckernel */
|
for (idx = 0; idx < cpu_pmu->num_events; idx++) {
|
||||||
irqstate = ihk_mc_spinlock_lock(&proc->mckfd_lock);
|
struct mc_perf_event *event = NULL;
|
||||||
for (fdp = proc->mckfd; fdp; fdp = fdp->next) {
|
struct mc_perf_event *sub;
|
||||||
if (fdp->sig_no > 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ihk_mc_spinlock_unlock(&proc->mckfd_lock, irqstate);
|
|
||||||
|
|
||||||
if (fdp) {
|
if (!armv8pmu_counter_has_overflowed(pmovsr, idx)) {
|
||||||
memset(&info, '\0', sizeof(info));
|
continue;
|
||||||
info.si_signo = fdp->sig_no;
|
}
|
||||||
info._sifields._sigfault.si_addr = (void *)regs->pc;
|
|
||||||
info._sifields._sigpoll.si_fd = fdp->fd;
|
|
||||||
set_signal(fdp->sig_no, regs, &info);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
set_signal(SIGIO, regs, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event) {
|
if (proc->monitoring_event->counter_id == idx) {
|
||||||
|
event = proc->monitoring_event;
|
||||||
|
} else {
|
||||||
|
list_for_each_entry(sub,
|
||||||
|
&proc->monitoring_event->sibling_list,
|
||||||
|
group_entry) {
|
||||||
|
if (sub->counter_id == idx) {
|
||||||
|
event = sub;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!event) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ihk_mc_event_update(event);
|
ihk_mc_event_update(event);
|
||||||
ihk_mc_event_set_period(event);
|
ihk_mc_event_set_period(event);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user