perf/x86/uncore: Fix event group support
[ Upstream commit75be6f703a] The events in the same group don't start or stop simultaneously. Here is the ftrace when enabling event group for uncore_iio_0: # perf stat -e "{uncore_iio_0/event=0x1/,uncore_iio_0/event=0xe/}" <idle>-0 [000] d.h. 8959.064832: read_msr: a41, value b2b0b030 //Read counter reg of IIO unit0 counter0 <idle>-0 [000] d.h. 8959.064835: write_msr: a48, value 400001 //Write Ctrl reg of IIO unit0 counter0 to enable counter0. <------ Although counter0 is enabled, Unit Ctrl is still freezed. Nothing will count. We are still good here. <idle>-0 [000] d.h. 8959.064836: read_msr: a40, value 30100 //Read Unit Ctrl reg of IIO unit0 <idle>-0 [000] d.h. 8959.064838: write_msr: a40, value 30000 //Write Unit Ctrl reg of IIO unit0 to enable all counters in the unit by clear Freeze bit <------Unit0 is un-freezed. Counter0 has been enabled. Now it starts counting. But counter1 has not been enabled yet. The issue starts here. <idle>-0 [000] d.h. 8959.064846: read_msr: a42, value 0 //Read counter reg of IIO unit0 counter1 <idle>-0 [000] d.h. 8959.064847: write_msr: a49, value 40000e //Write Ctrl reg of IIO unit0 counter1 to enable counter1. <------ Now, counter1 just starts to count. Counter0 has been running for a while. Current code un-freezes the Unit Ctrl right after the first counter is enabled. The subsequent group events always loses some counter values. Implement pmu_enable and pmu_disable support for uncore, which can help to batch hardware accesses. No one uses uncore_enable_box and uncore_disable_box. Remove them. Signed-off-by: Kan Liang <kan.liang@linux.intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Stephane Eranian <eranian@google.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Vince Weaver <vincent.weaver@maine.edu> Cc: linux-drivers-review@eclists.intel.com Cc: linux-perf@eclists.intel.com Fixes:087bfbb032("perf/x86: Add generic Intel uncore PMU support") Link: https://lkml.kernel.org/r/1572014593-31591-1-git-send-email-kan.liang@linux.intel.com Signed-off-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
f14751658a
commit
ef38f4d123
2 changed files with 38 additions and 18 deletions
|
|
@ -485,10 +485,8 @@ void uncore_pmu_event_start(struct perf_event *event, int flags)
|
|||
local64_set(&event->hw.prev_count, uncore_read_counter(box, event));
|
||||
uncore_enable_event(box, event);
|
||||
|
||||
if (box->n_active == 1) {
|
||||
uncore_enable_box(box);
|
||||
if (box->n_active == 1)
|
||||
uncore_pmu_start_hrtimer(box);
|
||||
}
|
||||
}
|
||||
|
||||
void uncore_pmu_event_stop(struct perf_event *event, int flags)
|
||||
|
|
@ -512,10 +510,8 @@ void uncore_pmu_event_stop(struct perf_event *event, int flags)
|
|||
WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
|
||||
hwc->state |= PERF_HES_STOPPED;
|
||||
|
||||
if (box->n_active == 0) {
|
||||
uncore_disable_box(box);
|
||||
if (box->n_active == 0)
|
||||
uncore_pmu_cancel_hrtimer(box);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
|
||||
|
|
@ -769,6 +765,40 @@ static int uncore_pmu_event_init(struct perf_event *event)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void uncore_pmu_enable(struct pmu *pmu)
|
||||
{
|
||||
struct intel_uncore_pmu *uncore_pmu;
|
||||
struct intel_uncore_box *box;
|
||||
|
||||
uncore_pmu = container_of(pmu, struct intel_uncore_pmu, pmu);
|
||||
if (!uncore_pmu)
|
||||
return;
|
||||
|
||||
box = uncore_pmu_to_box(uncore_pmu, smp_processor_id());
|
||||
if (!box)
|
||||
return;
|
||||
|
||||
if (uncore_pmu->type->ops->enable_box)
|
||||
uncore_pmu->type->ops->enable_box(box);
|
||||
}
|
||||
|
||||
static void uncore_pmu_disable(struct pmu *pmu)
|
||||
{
|
||||
struct intel_uncore_pmu *uncore_pmu;
|
||||
struct intel_uncore_box *box;
|
||||
|
||||
uncore_pmu = container_of(pmu, struct intel_uncore_pmu, pmu);
|
||||
if (!uncore_pmu)
|
||||
return;
|
||||
|
||||
box = uncore_pmu_to_box(uncore_pmu, smp_processor_id());
|
||||
if (!box)
|
||||
return;
|
||||
|
||||
if (uncore_pmu->type->ops->disable_box)
|
||||
uncore_pmu->type->ops->disable_box(box);
|
||||
}
|
||||
|
||||
static ssize_t uncore_get_attr_cpumask(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
|
@ -794,6 +824,8 @@ static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
|
|||
pmu->pmu = (struct pmu) {
|
||||
.attr_groups = pmu->type->attr_groups,
|
||||
.task_ctx_nr = perf_invalid_context,
|
||||
.pmu_enable = uncore_pmu_enable,
|
||||
.pmu_disable = uncore_pmu_disable,
|
||||
.event_init = uncore_pmu_event_init,
|
||||
.add = uncore_pmu_event_add,
|
||||
.del = uncore_pmu_event_del,
|
||||
|
|
|
|||
|
|
@ -412,18 +412,6 @@ static inline int uncore_freerunning_hw_config(struct intel_uncore_box *box,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline void uncore_disable_box(struct intel_uncore_box *box)
|
||||
{
|
||||
if (box->pmu->type->ops->disable_box)
|
||||
box->pmu->type->ops->disable_box(box);
|
||||
}
|
||||
|
||||
static inline void uncore_enable_box(struct intel_uncore_box *box)
|
||||
{
|
||||
if (box->pmu->type->ops->enable_box)
|
||||
box->pmu->type->ops->enable_box(box);
|
||||
}
|
||||
|
||||
static inline void uncore_disable_event(struct intel_uncore_box *box,
|
||||
struct perf_event *event)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue