]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
s390/pai_crypto: Introduce generic event init using pai_pmu[]
authorThomas Richter <tmricht@linux.ibm.com>
Wed, 5 Nov 2025 14:38:47 +0000 (15:38 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Fri, 14 Nov 2025 10:30:05 +0000 (11:30 +0100)
To support one common PAI PMU device driver which handles
both PMUs pai_crypto and pai_ext, use a common naming scheme
for structures and variables suitable for both device drivers.

Rework PAI crypto event initialization. Add a common
function for event initialization. It uses the PAI characteristics
stored in the pai_pmu table instead of hardcoded values.
Enlarge pai_event_valid() to check all event validation aspects.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/include/asm/pai.h
arch/s390/kernel/perf_pai_crypto.c

index ebeabd0aaa516aa5a79309984b360636409bc3f8..534d0320e2aa095023219412e6306f16ceef2ca6 100644 (file)
@@ -77,6 +77,7 @@ static __always_inline void pai_kernel_exit(struct pt_regs *regs)
 
 #define PAI_SAVE_AREA(x)       ((x)->hw.event_base)
 #define PAI_CPU_MASK(x)                ((x)->hw.addr_filters)
+#define PAI_PMU_IDX(x)         ((x)->hw.last_tag)
 #define PAI_SWLIST(x)          (&(x)->hw.tp_list)
 
 #endif
index 36a99cdc3d37e1eea860b5c1bd1fac5901c4966f..163053cb61a64d1a271d6769f4293f4ccf699b9b 100644 (file)
@@ -204,11 +204,11 @@ static u64 paicrypt_getall(struct perf_event *event)
  *
  * Allocate the memory for the event.
  */
-static int paicrypt_alloc_cpu(struct perf_event *event, int cpu)
+static int pai_alloc_cpu(struct perf_event *event, int cpu)
 {
+       int rc, idx = PAI_PMU_IDX(event);
        struct pai_map *cpump = NULL;
        struct pai_mapptr *mp;
-       int rc;
 
        mutex_lock(&pai_reserve_mutex);
        /* Allocate root node */
@@ -229,7 +229,7 @@ static int paicrypt_alloc_cpu(struct perf_event *event, int cpu)
                 */
                mp->mapptr = cpump;
                cpump->area = (unsigned long *)get_zeroed_page(GFP_KERNEL);
-               cpump->save = kvmalloc_array(paicrypt_cnt + 1,
+               cpump->save = kvmalloc_array(pai_pmu[idx].num_avail + 1,
                                             sizeof(struct pai_userdata),
                                             GFP_KERNEL);
                if (!cpump->area || !cpump->save) {
@@ -253,10 +253,11 @@ undo:
        }
 unlock:
        mutex_unlock(&pai_reserve_mutex);
+       /* If rc is non-zero, no increment of counter/sampler was done. */
        return rc;
 }
 
-static int paicrypt_alloc(struct perf_event *event)
+static int pai_alloc(struct perf_event *event)
 {
        struct cpumask *maskptr;
        int cpu, rc = -ENOMEM;
@@ -266,7 +267,7 @@ static int paicrypt_alloc(struct perf_event *event)
                goto out;
 
        for_each_online_cpu(cpu) {
-               rc = paicrypt_alloc_cpu(event, cpu);
+               rc = pai_alloc_cpu(event, cpu);
                if (rc) {
                        for_each_cpu(cpu, maskptr)
                                paicrypt_event_destroy_cpu(event, cpu);
@@ -288,22 +289,38 @@ out:
        return rc;
 }
 
-/* Might be called on different CPU than the one the event is intended for. */
-static int paicrypt_event_init(struct perf_event *event)
+/* Validate event number and return error if event is not supported.
+ * On successful return, PAI_PMU_IDX(event) is set to the index of
+ * the supporting paing_support[] array element.
+ */
+static int pai_event_valid(struct perf_event *event, int idx)
 {
        struct perf_event_attr *a = &event->attr;
-       int rc = 0;
+       struct pai_pmu *pp = &pai_pmu[idx];
 
        /* PAI crypto PMU registered as PERF_TYPE_RAW, check event type */
        if (a->type != PERF_TYPE_RAW && event->pmu->type != a->type)
                return -ENOENT;
+       /* Allow only CRYPTO_ALL/NNPA_ALL for sampling */
+       if (a->sample_period && a->config != pp->base)
+               return -EINVAL;
        /* PAI crypto event must be in valid range, try others if not */
-       if (a->config < PAI_CRYPTO_BASE ||
-           a->config > PAI_CRYPTO_BASE + paicrypt_cnt)
+       if (a->config < pp->base || a->config > pp->base + pp->num_avail)
                return -ENOENT;
-       /* Allow only CRYPTO_ALL for sampling */
-       if (a->sample_period && a->config != PAI_CRYPTO_BASE)
-               return -EINVAL;
+       PAI_PMU_IDX(event) = idx;
+       return 0;
+}
+
+/* Might be called on different CPU than the one the event is intended for. */
+static int pai_event_init(struct perf_event *event, int idx)
+{
+       struct perf_event_attr *a = &event->attr;
+       int rc;
+
+       /* PAI event must be valid and in supported range */
+       rc = pai_event_valid(event, idx);
+       if (rc)
+               goto out;
        /* Get a page to store last counter values for sampling */
        if (a->sample_period) {
                PAI_SAVE_AREA(event) = get_zeroed_page(GFP_KERNEL);
@@ -314,14 +331,13 @@ static int paicrypt_event_init(struct perf_event *event)
        }
 
        if (event->cpu >= 0)
-               rc = paicrypt_alloc_cpu(event, event->cpu);
+               rc = pai_alloc_cpu(event, event->cpu);
        else
-               rc = paicrypt_alloc(event);
+               rc = pai_alloc(event);
        if (rc) {
                free_page(PAI_SAVE_AREA(event));
                goto out;
        }
-       event->destroy = paicrypt_event_destroy;
 
        if (a->sample_period) {
                a->sample_period = 1;
@@ -333,12 +349,21 @@ static int paicrypt_event_init(struct perf_event *event)
                /* Turn off inheritance */
                a->inherit = 0;
        }
-
-       static_branch_inc(&pai_key);
 out:
        return rc;
 }
 
+static int paicrypt_event_init(struct perf_event *event)
+{
+       int rc = pai_event_init(event, PAI_PMU_CRYPTO);
+
+       if (!rc) {
+               event->destroy = paicrypt_event_destroy;
+               static_branch_inc(&pai_key);
+       }
+       return rc;
+}
+
 static void paicrypt_read(struct perf_event *event)
 {
        u64 prev, new, delta;