From: Thomas Richter Date: Thu, 29 Feb 2024 14:13:48 +0000 (+0100) Subject: s390/pai_crypto: Enable concurrent system-wide counting/sampling event X-Git-Tag: v6.11-rc1~126^2~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fb412c6241dccc530416917efe8e9fea5fa1fda2;p=thirdparty%2Fkernel%2Flinux.git s390/pai_crypto: Enable concurrent system-wide counting/sampling event The PMU for PAI crypto counters enforces the following restriction: - No system wide counting while system wide sampling is active. This restriction is removed. One or more system wide counting events can now be active at the same time while at most one system wide sampling event is active. Acked-by: Sumanth Korikkar Signed-off-by: Thomas Richter Signed-off-by: Alexander Gordeev --- diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c index 4ad472d130a3c..d3a64f041819f 100644 --- a/arch/s390/kernel/perf_pai_crypto.c +++ b/arch/s390/kernel/perf_pai_crypto.c @@ -97,6 +97,8 @@ static void paicrypt_event_destroy(struct perf_event *event) event->attr.config, event->cpu, cpump->active_events, cpump->mode, refcount_read(&cpump->refcnt)); + if (event->attr.sample_period) + cpump->mode &= ~PAI_MODE_SAMPLING; free_page(PAI_SAVE_AREA(event)); if (refcount_dec_and_test(&cpump->refcnt)) { debug_sprintf_event(cfm_dbg, 4, "%s page %#lx save %p\n", @@ -160,9 +162,7 @@ static u64 paicrypt_getall(struct perf_event *event) * sampling for crypto events * * Only one instance of event pai_crypto/CRYPTO_ALL/ for sampling is - * allowed and when this event is running, no counting event is allowed. - * Several counting events are allowed in parallel, but no sampling event - * is allowed while one (or more) counting events are running. + * allowed. Several counting events are allowed in parallel. * * This function is called in process context and it is save to block. * When the event initialization functions fails, no other call back will @@ -196,12 +196,12 @@ static struct paicrypt_map *paicrypt_busy(struct perf_event *event) } if (a->sample_period) { /* Sampling requested */ - if (cpump->mode != PAI_MODE_NONE) - rc = -EBUSY; /* ... sampling/counting active */ - } else { /* Counting requested */ - if (cpump->mode == PAI_MODE_SAMPLING) + if (cpump->mode & PAI_MODE_SAMPLING) rc = -EBUSY; /* ... and sampling active */ + else + cpump->mode |= PAI_MODE_SAMPLING; } + /* * This error case triggers when there is a conflict: * Either sampling requested and counting already active, or visa @@ -235,7 +235,6 @@ static struct paicrypt_map *paicrypt_busy(struct perf_event *event) /* Set mode and reference count */ rc = 0; refcount_set(&cpump->refcnt, 1); - cpump->mode = a->sample_period ? PAI_MODE_SAMPLING : PAI_MODE_COUNTING; mp->mapptr = cpump; debug_sprintf_event(cfm_dbg, 5, "%s sample_period %#llx users %d" " mode %d refcnt %u page %#lx save %p rc %d\n", @@ -249,7 +248,6 @@ free_paicrypt_map: mp->mapptr = NULL; free_root: paicrypt_root_free(); - unlock: mutex_unlock(&pai_reserve_mutex); return rc ? ERR_PTR(rc) : cpump; @@ -332,6 +330,7 @@ static void paicrypt_start(struct perf_event *event, int flags) local64_set(&event->hw.prev_count, sum); } else { /* Sampling */ cpump->event = event; + memcpy((void *)PAI_SAVE_AREA(event), cpump->page, PAGE_SIZE); perf_sched_cb_inc(event->pmu); } } @@ -480,7 +479,7 @@ static int paicrypt_have_sample(void) static void paicrypt_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in) { /* We started with a clean page on event installation. So read out - * results on schedule_out and if page was dirty, clear values. + * results on schedule_out and if page was dirty, save old values. */ if (!sched_in) paicrypt_have_sample();