powerpc/perf: Infrastructure to support addition of blacklisted events
authorMadhavan Srinivasan <maddy@linux.vnet.ibm.com>
Sun, 4 Mar 2018 11:56:26 +0000 (17:26 +0530)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 27 Mar 2018 08:25:10 +0000 (19:25 +1100)
Introduce code to support addition of blacklisted events for a
processor version. Blacklisted events are events that are known to not
count correctly on that CPU revision, and so should be prevented from
being counted so as to avoid user confusion.

A 'pointer' and 'int' variable to hold the number of events are added
to 'struct power_pmu', along with a generic function to loop through
the list to validate the given event. Generic function
'is_event_blacklisted' is called in power_pmu_event_init() to detect
and reject early.

Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/perf_event_server.h
arch/powerpc/perf/core-book3s.c

index 723bf48e7494b5e59af463fbc411ac301b364aac..67a8a9585d50f878aba7b664569b3e65b0df07ee 100644 (file)
@@ -53,6 +53,8 @@ struct power_pmu {
                               [PERF_COUNT_HW_CACHE_OP_MAX]
                               [PERF_COUNT_HW_CACHE_RESULT_MAX];
 
+       int             n_blacklist_ev;
+       int             *blacklist_ev;
        /* BHRB entries in the PMU */
        int             bhrb_nr;
 };
index a00b364fb9d7c0abddd5d0cce1924fb9803e8530..e032aeff3d6b1ec81e0734681bad17f3de1b85e1 100644 (file)
@@ -1839,6 +1839,18 @@ static int hw_perf_cache_event(u64 config, u64 *eventp)
        return 0;
 }
 
+static bool is_event_blacklisted(u64 ev)
+{
+       int i;
+
+       for (i=0; i < ppmu->n_blacklist_ev; i++) {
+               if (ppmu->blacklist_ev[i] == ev)
+                       return true;
+       }
+
+       return false;
+}
+
 static int power_pmu_event_init(struct perf_event *event)
 {
        u64 ev;
@@ -1864,15 +1876,24 @@ static int power_pmu_event_init(struct perf_event *event)
                ev = event->attr.config;
                if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
                        return -EOPNOTSUPP;
+
+               if (ppmu->blacklist_ev && is_event_blacklisted(ev))
+                       return -EINVAL;
                ev = ppmu->generic_events[ev];
                break;
        case PERF_TYPE_HW_CACHE:
                err = hw_perf_cache_event(event->attr.config, &ev);
                if (err)
                        return err;
+
+               if (ppmu->blacklist_ev && is_event_blacklisted(ev))
+                       return -EINVAL;
                break;
        case PERF_TYPE_RAW:
                ev = event->attr.config;
+
+               if (ppmu->blacklist_ev && is_event_blacklisted(ev))
+                       return -EINVAL;
                break;
        default:
                return -ENOENT;