Commit 3202e35e authored by Ravi Bangoria's avatar Ravi Bangoria Committed by Michael Ellerman

powerpc/perf: Fix MMCRA corruption by bhrb_filter

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: 3925f46b ("powerpc/perf: Enable branch stack sampling framework")
Cc: stable@vger.kernel.org # v3.10+
Signed-off-by: default avatarRavi Bangoria <ravi.bangoria@linux.ibm.com>
Reviewed-by: default avatarMadhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent b59bd352
...@@ -1850,6 +1850,7 @@ static int power_pmu_event_init(struct perf_event *event) ...@@ -1850,6 +1850,7 @@ static int power_pmu_event_init(struct perf_event *event)
int n; int n;
int err; int err;
struct cpu_hw_events *cpuhw; struct cpu_hw_events *cpuhw;
u64 bhrb_filter;
if (!ppmu) if (!ppmu)
return -ENOENT; return -ENOENT;
...@@ -1955,13 +1956,14 @@ static int power_pmu_event_init(struct perf_event *event) ...@@ -1955,13 +1956,14 @@ static int power_pmu_event_init(struct perf_event *event)
err = power_check_constraints(cpuhw, events, cflags, n + 1); err = power_check_constraints(cpuhw, events, cflags, n + 1);
if (has_branch_stack(event)) { if (has_branch_stack(event)) {
cpuhw->bhrb_filter = ppmu->bhrb_filter_map( bhrb_filter = ppmu->bhrb_filter_map(
event->attr.branch_sample_type); event->attr.branch_sample_type);
if (cpuhw->bhrb_filter == -1) { if (bhrb_filter == -1) {
put_cpu_var(cpu_hw_events); put_cpu_var(cpu_hw_events);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
cpuhw->bhrb_filter = bhrb_filter;
} }
put_cpu_var(cpu_hw_events); put_cpu_var(cpu_hw_events);
......
...@@ -29,6 +29,7 @@ enum { ...@@ -29,6 +29,7 @@ enum {
#define POWER8_MMCRA_IFM1 0x0000000040000000UL #define POWER8_MMCRA_IFM1 0x0000000040000000UL
#define POWER8_MMCRA_IFM2 0x0000000080000000UL #define POWER8_MMCRA_IFM2 0x0000000080000000UL
#define POWER8_MMCRA_IFM3 0x00000000C0000000UL #define POWER8_MMCRA_IFM3 0x00000000C0000000UL
#define POWER8_MMCRA_BHRB_MASK 0x00000000C0000000UL
/* /*
* Raw event encoding for PowerISA v2.07 (Power8): * Raw event encoding for PowerISA v2.07 (Power8):
...@@ -243,6 +244,8 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type) ...@@ -243,6 +244,8 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type)
static void power8_config_bhrb(u64 pmu_bhrb_filter) static void power8_config_bhrb(u64 pmu_bhrb_filter)
{ {
pmu_bhrb_filter &= POWER8_MMCRA_BHRB_MASK;
/* Enable BHRB filter in PMU */ /* Enable BHRB filter in PMU */
mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter)); mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
} }
......
...@@ -92,6 +92,7 @@ enum { ...@@ -92,6 +92,7 @@ enum {
#define POWER9_MMCRA_IFM1 0x0000000040000000UL #define POWER9_MMCRA_IFM1 0x0000000040000000UL
#define POWER9_MMCRA_IFM2 0x0000000080000000UL #define POWER9_MMCRA_IFM2 0x0000000080000000UL
#define POWER9_MMCRA_IFM3 0x00000000C0000000UL #define POWER9_MMCRA_IFM3 0x00000000C0000000UL
#define POWER9_MMCRA_BHRB_MASK 0x00000000C0000000UL
/* Nasty Power9 specific hack */ /* Nasty Power9 specific hack */
#define PVR_POWER9_CUMULUS 0x00002000 #define PVR_POWER9_CUMULUS 0x00002000
...@@ -300,6 +301,8 @@ static u64 power9_bhrb_filter_map(u64 branch_sample_type) ...@@ -300,6 +301,8 @@ static u64 power9_bhrb_filter_map(u64 branch_sample_type)
static void power9_config_bhrb(u64 pmu_bhrb_filter) static void power9_config_bhrb(u64 pmu_bhrb_filter)
{ {
pmu_bhrb_filter &= POWER9_MMCRA_BHRB_MASK;
/* Enable BHRB filter in PMU */ /* Enable BHRB filter in PMU */
mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter)); mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment