[PATCH 3.16 15/87] powerpc/perf: Fix MMCRA corruption by bhrb_filter

From: Ben Hutchings
Date: Wed Oct 02 2019 - 15:13:12 EST


3.16.75-rc1 review patch. If anyone has any objections, please let me know.

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

From: Ravi Bangoria <ravi.bangoria@xxxxxxxxxxxxx>

commit 3202e35ec1c8fc19cea24253ff83edf702a60a02 upstream.

Consider a scenario where user creates two events:

1st event:
attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY;
fd = perf_event_open(attr, 0, 1, -1, 0);

This sets cpuhw->bhrb_filter to 0 and returns valid fd.

2nd event:
attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
attr.branch_sample_type = PERF_SAMPLE_BRANCH_CALL;
fd = perf_event_open(attr, 0, 1, -1, 0);

It overrides cpuhw->bhrb_filter to -1 and returns with error.

Now if power_pmu_enable() gets called by any path other than
power_pmu_add(), ppmu->config_bhrb(-1) will set MMCRA to -1.

Fixes: 3925f46bb590 ("powerpc/perf: Enable branch stack sampling framework")
Signed-off-by: Ravi Bangoria <ravi.bangoria@xxxxxxxxxxxxx>
Reviewed-by: Madhavan Srinivasan <maddy@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Michael Ellerman <mpe@xxxxxxxxxxxxxx>
[bwh: Backported to 3.16: drop changes in power9-pmu.c]
Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx>
---
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -1726,6 +1726,7 @@ static int power_pmu_event_init(struct p
int n;
int err;
struct cpu_hw_events *cpuhw;
+ u64 bhrb_filter;

if (!ppmu)
return -ENOENT;
@@ -1822,13 +1823,14 @@ static int power_pmu_event_init(struct p
err = power_check_constraints(cpuhw, events, cflags, n + 1);

if (has_branch_stack(event)) {
- cpuhw->bhrb_filter = ppmu->bhrb_filter_map(
+ bhrb_filter = ppmu->bhrb_filter_map(
event->attr.branch_sample_type);

- if (cpuhw->bhrb_filter == -1) {
+ if (bhrb_filter == -1) {
put_cpu_var(cpu_hw_events);
return -EOPNOTSUPP;
}
+ cpuhw->bhrb_filter = bhrb_filter;
}

put_cpu_var(cpu_hw_events);
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -175,6 +175,7 @@
#define POWER8_MMCRA_IFM1 0x0000000040000000UL
#define POWER8_MMCRA_IFM2 0x0000000080000000UL
#define POWER8_MMCRA_IFM3 0x00000000C0000000UL
+#define POWER8_MMCRA_BHRB_MASK 0x00000000C0000000UL

#define ONLY_PLM \
(PERF_SAMPLE_BRANCH_USER |\
@@ -666,6 +667,8 @@ static u64 power8_bhrb_filter_map(u64 br

static void power8_config_bhrb(u64 pmu_bhrb_filter)
{
+ pmu_bhrb_filter &= POWER8_MMCRA_BHRB_MASK;
+
/* Enable BHRB filter in PMU */
mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
}