powerpc/perf: Check that events only include valid bits on Power8
authorMichael Ellerman <michael@ellerman.id.au>
Fri, 28 Jun 2013 08:15:10 +0000 (18:15 +1000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Jul 2013 21:07:22 +0000 (14:07 -0700)
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

index f7d1c4fff30308c5febe047665ff95486a9f8412..84cdc6d892e3b17333b06d98c15f95655f749ac5 100644 (file)
 #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 event, unsigned long *maskp, unsigned long
 
        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;