Commit 21e87644 authored by Thomas Richter's avatar Thomas Richter Committed by Alexander Gordeev

s390/pai: Fix multiple concurrent event installation

Two different events such as pai_crypto/KM_AES_128/ and
pai_crypto/KM_AES_192/ can be installed multiple times on the same CPU
and the events are executed concurrently:

  # perf stat -e pai_crypto/KM_AES_128/  -C0 -a -- sleep 5 &
  # sleep 2
  # perf stat -e pai_crypto/KM_AES_192/ -C0 -a -- true

This results in the first event being installed two times with two seconds
delay. The kernel does install the second event after the first
event has been deleted and re-added, as can be seen in the traces:

 13:48:47.600350  paicrypt_start event 0x1007 (event KM_AES_128)
 13:48:49.599359  paicrypt_stop event 0x1007  (event KM_AES_128)
 13:48:49.599198  paicrypt_start event 0x1007
 13:48:49.599199  paicrypt_start event 0x1008
 13:48:49.599921  paicrypt_event_destroy event 0x1008
 13:48:52.601507  paicrypt_event_destroy event 0x1007

This is caused by functions event_sched_in() and event_sched_out() which
call the PMU's add() and start() functions on schedule_in and the PMU's
stop() and del() functions on schedule_out. This is correct for events
attached to processes.  The pai_crypto events are system-wide events
and not attached to processes.

Since the kernel common code can not be changed easily, fix this issue
and do not reset the event count value to zero each time the event is
added and started. Instead use a flag and zero the event count value
only when called immediately after the event has been initialized.
Therefore only the first invocation of the the event's add() function
initializes the event count value to zero. The following invocations
of the event's add() function leave the current event count value
untouched.

Fixes: 39d62336 ("s390/pai: add support for cryptography counters")
Reported-by: default avatarSumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: default avatarThomas Richter <tmricht@linux.ibm.com>
Acked-by: default avatarSumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
parent 541a4966
...@@ -209,6 +209,12 @@ static int paicrypt_event_init(struct perf_event *event) ...@@ -209,6 +209,12 @@ static int paicrypt_event_init(struct perf_event *event)
if (rc) if (rc)
return rc; return rc;
/* Event initialization sets last_tag to 0. When later on the events
* are deleted and re-added, do not reset the event count value to zero.
* Events are added, deleted and re-added when 2 or more events
* are active at the same time.
*/
event->hw.last_tag = 0;
cpump->event = event; cpump->event = event;
event->destroy = paicrypt_event_destroy; event->destroy = paicrypt_event_destroy;
...@@ -243,9 +249,12 @@ static void paicrypt_start(struct perf_event *event, int flags) ...@@ -243,9 +249,12 @@ static void paicrypt_start(struct perf_event *event, int flags)
{ {
u64 sum; u64 sum;
if (!event->hw.last_tag) {
event->hw.last_tag = 1;
sum = paicrypt_getall(event); /* Get current value */ sum = paicrypt_getall(event); /* Get current value */
local64_set(&event->hw.prev_count, sum);
local64_set(&event->count, 0); local64_set(&event->count, 0);
local64_set(&event->hw.prev_count, sum);
}
} }
static int paicrypt_add(struct perf_event *event, int flags) static int paicrypt_add(struct perf_event *event, int flags)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment