s390/pai: fix sampling event removal for PMU device driver
authorThomas Richter <tmricht@linux.ibm.com>
Thu, 29 Feb 2024 14:00:28 +0000 (15:00 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Wed, 3 Apr 2024 13:00:20 +0000 (15:00 +0200)
In case of a sampling event, the PAI PMU device drivers need a
reference to this event.  Currently to PMU device driver reference
is removed when a sampling event is destroyed. This may lead to
situations where the reference of the PMU device driver is removed
while being used by a different sampling event.
Reset the event reference pointer of the PMU device driver when
a sampling event is deleted and before the next one might be added.

Fixes: 39d62336f5c1 ("s390/pai: add support for cryptography counters")
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/kernel/perf_pai_crypto.c
arch/s390/kernel/perf_pai_ext.c

index 823d652e3917f8653fe71bb5c67a72c2653cf6c3..4ad472d130a3c075cda96949a605e080ef8d3e1a 100644 (file)
@@ -90,7 +90,6 @@ static void paicrypt_event_destroy(struct perf_event *event)
                                                 event->cpu);
        struct paicrypt_map *cpump = mp->mapptr;
 
-       cpump->event = NULL;
        static_branch_dec(&pai_key);
        mutex_lock(&pai_reserve_mutex);
        debug_sprintf_event(cfm_dbg, 5, "%s event %#llx cpu %d users %d"
@@ -356,10 +355,15 @@ static int paicrypt_add(struct perf_event *event, int flags)
 
 static void paicrypt_stop(struct perf_event *event, int flags)
 {
-       if (!event->attr.sample_period) /* Counting */
+       struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr);
+       struct paicrypt_map *cpump = mp->mapptr;
+
+       if (!event->attr.sample_period) {       /* Counting */
                paicrypt_read(event);
-       else                            /* Sampling */
+       } else {                                /* Sampling */
                perf_sched_cb_dec(event->pmu);
+               cpump->event = NULL;
+       }
        event->hw.state = PERF_HES_STOPPED;
 }
 
index 616a25606cd63dcda97a0b781c88b55dc86f0032..a6da7e0cc7a66dac02e9524feb802b0bfee8e0e8 100644 (file)
@@ -122,7 +122,6 @@ static void paiext_event_destroy(struct perf_event *event)
 
        free_page(PAI_SAVE_AREA(event));
        mutex_lock(&paiext_reserve_mutex);
-       cpump->event = NULL;
        if (refcount_dec_and_test(&cpump->refcnt))      /* Last reference gone */
                paiext_free(mp);
        paiext_root_free();
@@ -362,10 +361,15 @@ static int paiext_add(struct perf_event *event, int flags)
 
 static void paiext_stop(struct perf_event *event, int flags)
 {
-       if (!event->attr.sample_period) /* Counting */
+       struct paiext_mapptr *mp = this_cpu_ptr(paiext_root.mapptr);
+       struct paiext_map *cpump = mp->mapptr;
+
+       if (!event->attr.sample_period) {       /* Counting */
                paiext_read(event);
-       else                            /* Sampling */
+       } else {                                /* Sampling */
                perf_sched_cb_dec(event->pmu);
+               cpump->event = NULL;
+       }
        event->hw.state = PERF_HES_STOPPED;
 }