18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Counter facility support definitions for the Linux perf
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2019
68c2ecf20Sopenharmony_ci * Author(s): Hendrik Brueckner <brueckner@linux.ibm.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#ifndef _ASM_S390_CPU_MCF_H
98c2ecf20Sopenharmony_ci#define _ASM_S390_CPU_MCF_H
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/perf_event.h>
128c2ecf20Sopenharmony_ci#include <asm/cpu_mf.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cienum cpumf_ctr_set {
158c2ecf20Sopenharmony_ci	CPUMF_CTR_SET_BASIC   = 0,    /* Basic Counter Set */
168c2ecf20Sopenharmony_ci	CPUMF_CTR_SET_USER    = 1,    /* Problem-State Counter Set */
178c2ecf20Sopenharmony_ci	CPUMF_CTR_SET_CRYPTO  = 2,    /* Crypto-Activity Counter Set */
188c2ecf20Sopenharmony_ci	CPUMF_CTR_SET_EXT     = 3,    /* Extended Counter Set */
198c2ecf20Sopenharmony_ci	CPUMF_CTR_SET_MT_DIAG = 4,    /* MT-diagnostic Counter Set */
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	/* Maximum number of counter sets */
228c2ecf20Sopenharmony_ci	CPUMF_CTR_SET_MAX,
238c2ecf20Sopenharmony_ci};
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define CPUMF_LCCTL_ENABLE_SHIFT    16
268c2ecf20Sopenharmony_ci#define CPUMF_LCCTL_ACTCTL_SHIFT     0
278c2ecf20Sopenharmony_cistatic const u64 cpumf_ctr_ctl[CPUMF_CTR_SET_MAX] = {
288c2ecf20Sopenharmony_ci	[CPUMF_CTR_SET_BASIC]	= 0x02,
298c2ecf20Sopenharmony_ci	[CPUMF_CTR_SET_USER]	= 0x04,
308c2ecf20Sopenharmony_ci	[CPUMF_CTR_SET_CRYPTO]	= 0x08,
318c2ecf20Sopenharmony_ci	[CPUMF_CTR_SET_EXT]	= 0x01,
328c2ecf20Sopenharmony_ci	[CPUMF_CTR_SET_MT_DIAG] = 0x20,
338c2ecf20Sopenharmony_ci};
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic inline void ctr_set_enable(u64 *state, int ctr_set)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	*state |= cpumf_ctr_ctl[ctr_set] << CPUMF_LCCTL_ENABLE_SHIFT;
388c2ecf20Sopenharmony_ci}
398c2ecf20Sopenharmony_cistatic inline void ctr_set_disable(u64 *state, int ctr_set)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	*state &= ~(cpumf_ctr_ctl[ctr_set] << CPUMF_LCCTL_ENABLE_SHIFT);
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_cistatic inline void ctr_set_start(u64 *state, int ctr_set)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	*state |= cpumf_ctr_ctl[ctr_set] << CPUMF_LCCTL_ACTCTL_SHIFT;
468c2ecf20Sopenharmony_ci}
478c2ecf20Sopenharmony_cistatic inline void ctr_set_stop(u64 *state, int ctr_set)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	*state &= ~(cpumf_ctr_ctl[ctr_set] << CPUMF_LCCTL_ACTCTL_SHIFT);
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic inline void ctr_set_multiple_enable(u64 *state, u64 ctrsets)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	*state |= ctrsets << CPUMF_LCCTL_ENABLE_SHIFT;
558c2ecf20Sopenharmony_ci}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistatic inline void ctr_set_multiple_disable(u64 *state, u64 ctrsets)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	*state &= ~(ctrsets << CPUMF_LCCTL_ENABLE_SHIFT);
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic inline void ctr_set_multiple_start(u64 *state, u64 ctrsets)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	*state |= ctrsets << CPUMF_LCCTL_ACTCTL_SHIFT;
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic inline void ctr_set_multiple_stop(u64 *state, u64 ctrsets)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	*state &= ~(ctrsets << CPUMF_LCCTL_ACTCTL_SHIFT);
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic inline int ctr_stcctm(enum cpumf_ctr_set set, u64 range, u64 *dest)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	switch (set) {
758c2ecf20Sopenharmony_ci	case CPUMF_CTR_SET_BASIC:
768c2ecf20Sopenharmony_ci		return stcctm(BASIC, range, dest);
778c2ecf20Sopenharmony_ci	case CPUMF_CTR_SET_USER:
788c2ecf20Sopenharmony_ci		return stcctm(PROBLEM_STATE, range, dest);
798c2ecf20Sopenharmony_ci	case CPUMF_CTR_SET_CRYPTO:
808c2ecf20Sopenharmony_ci		return stcctm(CRYPTO_ACTIVITY, range, dest);
818c2ecf20Sopenharmony_ci	case CPUMF_CTR_SET_EXT:
828c2ecf20Sopenharmony_ci		return stcctm(EXTENDED, range, dest);
838c2ecf20Sopenharmony_ci	case CPUMF_CTR_SET_MT_DIAG:
848c2ecf20Sopenharmony_ci		return stcctm(MT_DIAG_CLEARING, range, dest);
858c2ecf20Sopenharmony_ci	case CPUMF_CTR_SET_MAX:
868c2ecf20Sopenharmony_ci		return 3;
878c2ecf20Sopenharmony_ci	}
888c2ecf20Sopenharmony_ci	return 3;
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistruct cpu_cf_events {
928c2ecf20Sopenharmony_ci	struct cpumf_ctr_info	info;
938c2ecf20Sopenharmony_ci	atomic_t		ctr_set[CPUMF_CTR_SET_MAX];
948c2ecf20Sopenharmony_ci	atomic64_t		alert;
958c2ecf20Sopenharmony_ci	u64			state, tx_state;
968c2ecf20Sopenharmony_ci	unsigned int		flags;
978c2ecf20Sopenharmony_ci	unsigned int		txn_flags;
988c2ecf20Sopenharmony_ci};
998c2ecf20Sopenharmony_ciDECLARE_PER_CPU(struct cpu_cf_events, cpu_cf_events);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cibool kernel_cpumcf_avail(void);
1028c2ecf20Sopenharmony_ciint __kernel_cpumcf_begin(void);
1038c2ecf20Sopenharmony_ciunsigned long kernel_cpumcf_alert(int clear);
1048c2ecf20Sopenharmony_civoid __kernel_cpumcf_end(void);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_cistatic inline int kernel_cpumcf_begin(void)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	if (!cpum_cf_avail())
1098c2ecf20Sopenharmony_ci		return -ENODEV;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	preempt_disable();
1128c2ecf20Sopenharmony_ci	return __kernel_cpumcf_begin();
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_cistatic inline void kernel_cpumcf_end(void)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	__kernel_cpumcf_end();
1178c2ecf20Sopenharmony_ci	preempt_enable();
1188c2ecf20Sopenharmony_ci}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci/* Return true if store counter set multiple instruction is available */
1218c2ecf20Sopenharmony_cistatic inline int stccm_avail(void)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	return test_facility(142);
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci#endif /* _ASM_S390_CPU_MCF_H */
127