Skip to content

Commit 39d6233

Browse files
Thomas Richterhcahca
authored andcommitted
s390/pai: add support for cryptography counters
PMU device driver perf_pai_crypto supports Processor Activity Instrumentation (PAI), available with IBM z16: - maps a full page to lowcore address 0x1500. - uses CR0 bit 13 to turn PAI crypto counting on and off. - creates a sample with raw data on each context switch out when at context switch some mapped counters have a value of nonzero. This device driver only supports CPU wide context, no task context is allowed. Support for counting: - one or more counters can be specified using perf stat -e pai_crypto/xxx/ where xxx stands for the counter event name. Multiple invocation of this command is possible. The counter names are listed in /sys/devices/pai_crypto/events directory. - one special counters can be specified using perf stat -e pai_crypto/CRYPTO_ALL/ which returns the sum of all incremented crypto counters. - one event pai_crypto/CRYPTO_ALL/ is reserved for sampling. No multiple invocations are possible. The event collects data at context switch out and saves them in the ring buffer. Add qpaci assembly instruction to query supported memory mapped crypto counters. It returns the number of counters (no holes allowed in that range). The PAI crypto counter events are system wide and can not be executed in parallel. Therefore some restrictions documented in function paicrypt_busy apply. In particular event CRYPTO_ALL for sampling must run exclusive. Only counting events can run in parallel. PAI crypto counter events can not be created when a CPU hot plug add is processed. This means a CPU hot plug add does not get the necessary PAI event to record PAI cryptography counter increments on the newly added CPU. CPU hot plug remove removes the event and terminates the counting of PAI counters immediately. Co-developed-by: Sven Schnelle <[email protected]> Signed-off-by: Sven Schnelle <[email protected]> Reviewed-by: Juergen Christ <[email protected]> Signed-off-by: Thomas Richter <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Heiko Carstens <[email protected]>
1 parent 6d97af4 commit 39d6233

File tree

9 files changed

+784
-7
lines changed

9 files changed

+784
-7
lines changed

arch/s390/include/asm/ctl_reg.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ union ctlreg0 {
9393
unsigned long tcx : 1; /* Transactional-Execution control */
9494
unsigned long pifo : 1; /* Transactional-Execution Program-
9595
Interruption-Filtering Override */
96-
unsigned long : 22;
96+
unsigned long : 3;
97+
unsigned long ccc : 1; /* Cryptography counter control */
98+
unsigned long : 18;
9799
unsigned long : 3;
98100
unsigned long lap : 1; /* Low-address-protection control */
99101
unsigned long : 4;

arch/s390/include/asm/entry-common.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,21 @@
99
#include <linux/uaccess.h>
1010
#include <asm/timex.h>
1111
#include <asm/fpu/api.h>
12+
#include <asm/pai.h>
1213

1314
#define ARCH_EXIT_TO_USER_MODE_WORK (_TIF_GUARDED_STORAGE | _TIF_PER_TRAP)
1415

1516
void do_per_trap(struct pt_regs *regs);
1617

17-
#ifdef CONFIG_DEBUG_ENTRY
1818
static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs)
1919
{
20-
debug_user_asce(0);
20+
if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
21+
debug_user_asce(0);
22+
23+
pai_kernel_enter(regs);
2124
}
2225

2326
#define arch_enter_from_user_mode arch_enter_from_user_mode
24-
#endif /* CONFIG_DEBUG_ENTRY */
2527

2628
static __always_inline void arch_exit_to_user_mode_work(struct pt_regs *regs,
2729
unsigned long ti_work)
@@ -44,6 +46,8 @@ static __always_inline void arch_exit_to_user_mode(void)
4446

4547
if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
4648
debug_user_asce(1);
49+
50+
pai_kernel_exit(current_pt_regs());
4751
}
4852

4953
#define arch_exit_to_user_mode arch_exit_to_user_mode

arch/s390/include/asm/lowcore.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ struct lowcore {
200200
__u64 last_break_save_area; /* 0x1338 */
201201
__u32 access_regs_save_area[16]; /* 0x1340 */
202202
__u64 cregs_save_area[16]; /* 0x1380 */
203-
__u8 pad_0x1400[0x1800-0x1400]; /* 0x1400 */
203+
__u8 pad_0x1400[0x1500-0x1400]; /* 0x1400 */
204+
/* Cryptography-counter designation */
205+
__u64 ccd; /* 0x1500 */
206+
__u8 pad_0x1508[0x1800-0x1508]; /* 0x1508 */
204207

205208
/* Transaction abort diagnostic block */
206209
struct pgm_tdb pgm_tdb; /* 0x1800 */

arch/s390/include/asm/nmi.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ void nmi_alloc_mcesa_early(u64 *mcesad);
101101
int nmi_alloc_mcesa(u64 *mcesad);
102102
void nmi_free_mcesa(u64 *mcesad);
103103

104-
void s390_handle_mcck(void);
104+
void s390_handle_mcck(struct pt_regs *regs);
105105
void __s390_handle_mcck(void);
106106
int s390_do_machine_check(struct pt_regs *regs);
107107

arch/s390/include/asm/pai.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Processor Activity Instrumentation support for cryptography counters
4+
*
5+
* Copyright IBM Corp. 2022
6+
* Author(s): Thomas Richter <[email protected]>
7+
*/
8+
#ifndef _ASM_S390_PAI_H
9+
#define _ASM_S390_PAI_H
10+
11+
#include <linux/jump_label.h>
12+
#include <asm/lowcore.h>
13+
#include <asm/ptrace.h>
14+
15+
struct qpaci_info_block {
16+
u64 header;
17+
struct {
18+
u64 : 8;
19+
u64 num_cc : 8; /* # of supported crypto counters */
20+
u64 : 48;
21+
};
22+
};
23+
24+
static inline int qpaci(struct qpaci_info_block *info)
25+
{
26+
/* Size of info (in double words minus one) */
27+
size_t size = sizeof(*info) / sizeof(u64) - 1;
28+
int cc;
29+
30+
asm volatile(
31+
" lgr 0,%[size]\n"
32+
" .insn s,0xb28f0000,%[info]\n"
33+
" lgr %[size],0\n"
34+
" ipm %[cc]\n"
35+
" srl %[cc],28\n"
36+
: [cc] "=d" (cc), [info] "=Q" (*info), [size] "+&d" (size)
37+
:
38+
: "0", "cc", "memory");
39+
return cc ? (size + 1) * sizeof(u64) : 0;
40+
}
41+
42+
#define PAI_CRYPTO_BASE 0x1000 /* First event number */
43+
#define PAI_CRYPTO_MAXCTR 256 /* Max # of event counters */
44+
#define PAI_CRYPTO_KERNEL_OFFSET 2048
45+
46+
DECLARE_STATIC_KEY_FALSE(pai_key);
47+
48+
static __always_inline void pai_kernel_enter(struct pt_regs *regs)
49+
{
50+
if (!IS_ENABLED(CONFIG_PERF_EVENTS))
51+
return;
52+
if (!static_branch_unlikely(&pai_key))
53+
return;
54+
if (!S390_lowcore.ccd)
55+
return;
56+
if (!user_mode(regs))
57+
return;
58+
WRITE_ONCE(S390_lowcore.ccd, S390_lowcore.ccd | PAI_CRYPTO_KERNEL_OFFSET);
59+
}
60+
61+
static __always_inline void pai_kernel_exit(struct pt_regs *regs)
62+
{
63+
if (!IS_ENABLED(CONFIG_PERF_EVENTS))
64+
return;
65+
if (!static_branch_unlikely(&pai_key))
66+
return;
67+
if (!S390_lowcore.ccd)
68+
return;
69+
if (!user_mode(regs))
70+
return;
71+
WRITE_ONCE(S390_lowcore.ccd, S390_lowcore.ccd & ~PAI_CRYPTO_KERNEL_OFFSET);
72+
}
73+
74+
#endif

arch/s390/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ obj-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT) += ima_arch.o
7272
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf_common.o
7373
obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf.o perf_cpum_sf.o
7474
obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o
75+
obj-$(CONFIG_PERF_EVENTS) += perf_pai_crypto.o
7576

7677
obj-$(CONFIG_TRACEPOINTS) += trace.o
7778
obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_PGSTE)) += uv.o

arch/s390/kernel/entry.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ ENTRY(mcck_int_handler)
599599
mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
600600
xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1)
601601
la %r11,STACK_FRAME_OVERHEAD(%r1)
602+
lgr %r2,%r11
602603
lgr %r15,%r1
603604
brasl %r14,s390_handle_mcck
604605
.Lmcck_return:

arch/s390/kernel/nmi.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include <asm/switch_to.h>
3030
#include <asm/ctl_reg.h>
3131
#include <asm/asm-offsets.h>
32+
#include <asm/pai.h>
33+
3234
#include <linux/kvm_host.h>
3335

3436
struct mcck_struct {
@@ -169,10 +171,12 @@ void __s390_handle_mcck(void)
169171
}
170172
}
171173

172-
void noinstr s390_handle_mcck(void)
174+
void noinstr s390_handle_mcck(struct pt_regs *regs)
173175
{
174176
trace_hardirqs_off();
177+
pai_kernel_enter(regs);
175178
__s390_handle_mcck();
179+
pai_kernel_exit(regs);
176180
trace_hardirqs_on();
177181
}
178182
/*

0 commit comments

Comments
 (0)