| From d8bec4c9cd58f6d3679e09b7293851fb92ad7557 Mon Sep 17 00:00:00 2001 |
| From: Michael Ellerman <michael@ellerman.id.au> |
| Date: Fri, 28 Jun 2013 18:15:10 +1000 |
| Subject: powerpc/perf: Check that events only include valid bits on Power8 |
| |
| From: Michael Ellerman <michael@ellerman.id.au> |
| |
| commit d8bec4c9cd58f6d3679e09b7293851fb92ad7557 upstream. |
| |
| A mistake we have made in the past is that we pull out the fields we |
| need from the event code, but don't check that there are no unknown bits |
| set. This means that we can't ever assign meaning to those unknown bits |
| in future. |
| |
| Although we have once again failed to do this at release, it is still |
| early days for Power8 so I think we can still slip this in and get away |
| with it. |
| |
| Signed-off-by: Michael Ellerman <michael@ellerman.id.au> |
| Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/powerpc/perf/power8-pmu.c | 13 +++++++++++++ |
| 1 file changed, 13 insertions(+) |
| |
| --- a/arch/powerpc/perf/power8-pmu.c |
| +++ b/arch/powerpc/perf/power8-pmu.c |
| @@ -109,6 +109,16 @@ |
| #define EVENT_IS_MARKED (EVENT_MARKED_MASK << EVENT_MARKED_SHIFT) |
| #define EVENT_PSEL_MASK 0xff /* PMCxSEL value */ |
| |
| +#define EVENT_VALID_MASK \ |
| + ((EVENT_THRESH_MASK << EVENT_THRESH_SHIFT) | \ |
| + (EVENT_SAMPLE_MASK << EVENT_SAMPLE_SHIFT) | \ |
| + (EVENT_CACHE_SEL_MASK << EVENT_CACHE_SEL_SHIFT) | \ |
| + (EVENT_PMC_MASK << EVENT_PMC_SHIFT) | \ |
| + (EVENT_UNIT_MASK << EVENT_UNIT_SHIFT) | \ |
| + (EVENT_COMBINE_MASK << EVENT_COMBINE_SHIFT) | \ |
| + (EVENT_MARKED_MASK << EVENT_MARKED_SHIFT) | \ |
| + EVENT_PSEL_MASK) |
| + |
| /* MMCRA IFM bits - POWER8 */ |
| #define POWER8_MMCRA_IFM1 0x0000000040000000UL |
| #define POWER8_MMCRA_IFM2 0x0000000080000000UL |
| @@ -212,6 +222,9 @@ static int power8_get_constraint(u64 eve |
| |
| mask = value = 0; |
| |
| + if (event & ~EVENT_VALID_MASK) |
| + return -1; |
| + |
| pmc = (event >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; |
| unit = (event >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK; |
| cache = (event >> EVENT_CACHE_SEL_SHIFT) & EVENT_CACHE_SEL_MASK; |