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: 39d62336f5
("s390/pai: add support for cryptography counters")
Reported-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
This commit is contained in:
parent
541a496644
commit
21e8764487
|
@ -209,6 +209,12 @@ static int paicrypt_event_init(struct perf_event *event)
|
|||
if (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;
|
||||
event->destroy = paicrypt_event_destroy;
|
||||
|
||||
|
@ -243,9 +249,12 @@ static void paicrypt_start(struct perf_event *event, int flags)
|
|||
{
|
||||
u64 sum;
|
||||
|
||||
sum = paicrypt_getall(event); /* Get current value */
|
||||
local64_set(&event->hw.prev_count, sum);
|
||||
local64_set(&event->count, 0);
|
||||
if (!event->hw.last_tag) {
|
||||
event->hw.last_tag = 1;
|
||||
sum = paicrypt_getall(event); /* Get current value */
|
||||
local64_set(&event->count, 0);
|
||||
local64_set(&event->hw.prev_count, sum);
|
||||
}
|
||||
}
|
||||
|
||||
static int paicrypt_add(struct perf_event *event, int flags)
|
||||
|
|
Loading…
Reference in New Issue