提交 585104c0 编写于 作者: H He Chuyue 提交者: guzitao

sw64: perf: fix PMI with no event

Sunway inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5XTIW

--------------------------------

For perf disable PMU, this then presents the following error
condition in processes schedule:

Process A		Process B

Disable irq
<PMC overflow>
Disable PMU
			Enable irq
			<PMI comes>
			   ->sw64_perf_event_irq_handler()

When irq is disabled, PMC may still overflow then a PMI triggers.
After another process is scheduled and irq is enabled, this PMI
will raise immediately.

To avoid this, clear interrupt flag in hmcode when it disable PMU.
However, in kernel, events that do not exist will return directly.
Signed-off-by: NHe Chuyue <hechuyue@wxiat.com>
Reviewed-by: NHe Sheng <hesheng@wxiat.com>
Signed-off-by: NGu Zitao <guzitao@wxiat.com>
上级 931ff1e4
...@@ -385,7 +385,6 @@ static int sw64_pmu_add(struct perf_event *event, int flags) ...@@ -385,7 +385,6 @@ static int sw64_pmu_add(struct perf_event *event, int flags)
int err = 0; int err = 0;
unsigned long irq_flags; unsigned long irq_flags;
perf_pmu_disable(event->pmu);
local_irq_save(irq_flags); local_irq_save(irq_flags);
if (cpuc->pmcs[hwc->idx] == PMC_IN_USE) { if (cpuc->pmcs[hwc->idx] == PMC_IN_USE) {
...@@ -408,7 +407,6 @@ static int sw64_pmu_add(struct perf_event *event, int flags) ...@@ -408,7 +407,6 @@ static int sw64_pmu_add(struct perf_event *event, int flags)
out: out:
local_irq_restore(irq_flags); local_irq_restore(irq_flags);
perf_pmu_enable(event->pmu);
return err; return err;
} }
...@@ -422,24 +420,17 @@ static void sw64_pmu_del(struct perf_event *event, int flags) ...@@ -422,24 +420,17 @@ static void sw64_pmu_del(struct perf_event *event, int flags)
struct hw_perf_event *hwc = &event->hw; struct hw_perf_event *hwc = &event->hw;
unsigned long irq_flags; unsigned long irq_flags;
perf_pmu_disable(event->pmu);
local_irq_save(irq_flags); local_irq_save(irq_flags);
if (cpuc->event[hwc->idx] != event) sw64_pmu_stop(event, PERF_EF_UPDATE);
goto out;
cpuc->event[hwc->idx] = NULL; cpuc->event[hwc->idx] = NULL;
cpuc->pmcs[hwc->idx] = PMC_NOT_USE; cpuc->pmcs[hwc->idx] = PMC_NOT_USE;
cpuc->n_events--; cpuc->n_events--;
sw64_pmu_stop(event, PERF_EF_UPDATE);
/* Absorb the final count and turn off the event. */ /* Absorb the final count and turn off the event. */
perf_event_update_userpage(event); perf_event_update_userpage(event);
out:
local_irq_restore(irq_flags); local_irq_restore(irq_flags);
perf_pmu_enable(event->pmu);
} }
/* /*
...@@ -478,6 +469,9 @@ static void sw64_pmu_stop(struct perf_event *event, int flags) ...@@ -478,6 +469,9 @@ static void sw64_pmu_stop(struct perf_event *event, int flags)
struct hw_perf_event *hwc = &event->hw; struct hw_perf_event *hwc = &event->hw;
if (!(hwc->state & PERF_HES_STOPPED)) { if (!(hwc->state & PERF_HES_STOPPED)) {
wrperfmon(PERFMON_CMD_DISABLE, hwc->idx == 0 ?
PERFMON_DISABLE_ARGS_PC0 :
PERFMON_DISABLE_ARGS_PC1);
hwc->state |= PERF_HES_STOPPED; hwc->state |= PERF_HES_STOPPED;
barrier(); barrier();
} }
...@@ -486,12 +480,6 @@ static void sw64_pmu_stop(struct perf_event *event, int flags) ...@@ -486,12 +480,6 @@ static void sw64_pmu_stop(struct perf_event *event, int flags)
sw64_perf_event_update(event, hwc, hwc->idx, 0); sw64_perf_event_update(event, hwc, hwc->idx, 0);
hwc->state |= PERF_HES_UPTODATE; hwc->state |= PERF_HES_UPTODATE;
} }
if (hwc->idx == 0)
wrperfmon(PERFMON_CMD_DISABLE, PERFMON_DISABLE_ARGS_PC0);
else
wrperfmon(PERFMON_CMD_DISABLE, PERFMON_DISABLE_ARGS_PC1);
} }
/* /*
...@@ -659,10 +647,7 @@ static void sw64_perf_event_irq_handler(unsigned long perfmon_num, ...@@ -659,10 +647,7 @@ static void sw64_perf_event_irq_handler(unsigned long perfmon_num,
event = cpuc->event[idx]; event = cpuc->event[idx];
if (unlikely(!event)) { if (unlikely(!event)) {
/* This should never occur! */
irq_err_count++; irq_err_count++;
pr_warn("PMI: No event at index %d!\n", idx);
wrperfmon(PERFMON_CMD_ENABLE, idx == 0 ? PERFMON_DISABLE_ARGS_PC0 : PERFMON_DISABLE_ARGS_PC1);
return; return;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册