File Index
Files and directories
Sign in
FILE

cpu_mf.h

File preview with syntax highlighting.

linux-6.19.14/arch/s390/include/asm/cpu_mf.h C
  1/* SPDX-License-Identifier: GPL-2.0 */
  2/*
  3 * CPU-measurement facilities
  4 *
  5 *  Copyright IBM Corp. 2012, 2018
  6 *  Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
  7 *	       Jan Glauber <jang@linux.vnet.ibm.com>
  8 */
  9#ifndef _ASM_S390_CPU_MF_H
 10#define _ASM_S390_CPU_MF_H
 11
 12#include <linux/errno.h>
 13#include <linux/kmsan-checks.h>
 14#include <asm/asm-extable.h>
 15#include <asm/facility.h>
 16#include <asm/asm.h>
 17
 18asm(".include \"asm/cpu_mf-insn.h\"\n");
 19
 20#define CPU_MF_INT_SF_IAE	(1 << 31)	/* invalid entry address */
 21#define CPU_MF_INT_SF_ISE	(1 << 30)	/* incorrect SDBT entry */
 22#define CPU_MF_INT_SF_PRA	(1 << 29)	/* program request alert */
 23#define CPU_MF_INT_SF_SACA	(1 << 23)	/* sampler auth. change alert */
 24#define CPU_MF_INT_SF_LSDA	(1 << 22)	/* loss of sample data alert */
 25#define CPU_MF_INT_CF_MTDA	(1 << 15)	/* loss of MT ctr. data alert */
 26#define CPU_MF_INT_CF_CACA	(1 <<  7)	/* counter auth. change alert */
 27#define CPU_MF_INT_CF_LCDA	(1 <<  6)	/* loss of counter data alert */
 28#define CPU_MF_INT_CF_MASK	(CPU_MF_INT_CF_MTDA|CPU_MF_INT_CF_CACA| \
 29				 CPU_MF_INT_CF_LCDA)
 30#define CPU_MF_INT_SF_MASK	(CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE|	\
 31				 CPU_MF_INT_SF_PRA|CPU_MF_INT_SF_SACA|	\
 32				 CPU_MF_INT_SF_LSDA)
 33
 34#define CPU_MF_SF_RIBM_NOTAV	0x1		/* Sampling unavailable */
 35
 36/* CPU measurement facility support */
 37static inline int cpum_cf_avail(void)
 38{
 39	return test_facility(40) && test_facility(67);
 40}
 41
 42static inline int cpum_sf_avail(void)
 43{
 44	return test_facility(40) && test_facility(68);
 45}
 46
 47struct cpumf_ctr_info {
 48	u16   cfvn;
 49	u16   auth_ctl;
 50	u16   enable_ctl;
 51	u16   act_ctl;
 52	u16   max_cpu;
 53	u16   csvn;
 54	u16   max_cg;
 55	u16   reserved1;
 56	u32   reserved2[12];
 57} __packed;
 58
 59/* QUERY SAMPLING INFORMATION block */
 60struct hws_qsi_info_block {	    /* Bit(s) */
 61	unsigned int b0_13:14;	    /* 0-13: zeros			 */
 62	unsigned int as:1;	    /* 14: basic-sampling authorization	 */
 63	unsigned int ad:1;	    /* 15: diag-sampling authorization	 */
 64	unsigned int b16_21:6;	    /* 16-21: zeros			 */
 65	unsigned int es:1;	    /* 22: basic-sampling enable control */
 66	unsigned int ed:1;	    /* 23: diag-sampling enable control	 */
 67	unsigned int b24_29:6;	    /* 24-29: zeros			 */
 68	unsigned int cs:1;	    /* 30: basic-sampling activation control */
 69	unsigned int cd:1;	    /* 31: diag-sampling activation control */
 70	unsigned int bsdes:16;	    /* 4-5: size of basic sampling entry */
 71	unsigned int dsdes:16;	    /* 6-7: size of diagnostic sampling entry */
 72	unsigned long min_sampl_rate; /* 8-15: minimum sampling interval */
 73	unsigned long max_sampl_rate; /* 16-23: maximum sampling interval*/
 74	unsigned long tear;	    /* 24-31: TEAR contents		 */
 75	unsigned long dear;	    /* 32-39: DEAR contents		 */
 76	unsigned int rsvrd0:24;	    /* 40-42: reserved			 */
 77	unsigned int ribm:8;	    /* 43: Reserved by IBM		 */
 78	unsigned int cpu_speed;     /* 44-47: CPU speed			 */
 79	unsigned long long rsvrd1;  /* 48-55: reserved			 */
 80	unsigned long long rsvrd2;  /* 56-63: reserved			 */
 81} __packed;
 82
 83/* SET SAMPLING CONTROLS request block */
 84struct hws_lsctl_request_block {
 85	unsigned int s:1;	    /* 0: maximum buffer indicator	 */
 86	unsigned int h:1;	    /* 1: part. level reserved for VM use*/
 87	unsigned long long b2_53:52;/* 2-53: zeros			 */
 88	unsigned int es:1;	    /* 54: basic-sampling enable control */
 89	unsigned int ed:1;	    /* 55: diag-sampling enable control	 */
 90	unsigned int b56_61:6;	    /* 56-61: - zeros			 */
 91	unsigned int cs:1;	    /* 62: basic-sampling activation control */
 92	unsigned int cd:1;	    /* 63: diag-sampling activation control  */
 93	unsigned long interval;     /* 8-15: sampling interval		 */
 94	unsigned long tear;	    /* 16-23: TEAR contents		 */
 95	unsigned long dear;	    /* 24-31: DEAR contents		 */
 96	/* 32-63:							 */
 97	unsigned long rsvrd1;	    /* reserved				 */
 98	unsigned long rsvrd2;	    /* reserved				 */
 99	unsigned long rsvrd3;	    /* reserved				 */
100	unsigned long rsvrd4;	    /* reserved				 */
101} __packed;
102
103struct hws_basic_entry {
104	unsigned int def:16;	    /* 0-15  Data Entry Format		 */
105	unsigned int R:4;	    /* 16-19 reserved			 */
106	unsigned int U:4;	    /* 20-23 Number of unique instruct.  */
107	unsigned int z:2;	    /* zeros				 */
108	unsigned int T:1;	    /* 26 PSW DAT mode			 */
109	unsigned int W:1;	    /* 27 PSW wait state		 */
110	unsigned int P:1;	    /* 28 PSW Problem state		 */
111	unsigned int AS:2;	    /* 29-30 PSW address-space control	 */
112	unsigned int I:1;	    /* 31 entry valid or invalid	 */
113	unsigned int CL:2;	    /* 32-33 Configuration Level	 */
114	unsigned int H:1;	    /* 34 Host Indicator		 */
115	unsigned int LS:1;	    /* 35 Limited Sampling		 */
116	unsigned int:12;
117	unsigned int prim_asn:16;   /* primary ASN			 */
118	unsigned long long ia;	    /* Instruction Address		 */
119	unsigned long long gpp;     /* Guest Program Parameter		 */
120	unsigned long long hpp;     /* Host Program Parameter		 */
121} __packed;
122
123struct hws_diag_entry {
124	unsigned int def:16;	    /* 0-15  Data Entry Format		 */
125	unsigned int R:15;	    /* 16-19 and 20-30 reserved		 */
126	unsigned int I:1;	    /* 31 entry valid or invalid	 */
127	u8	     data[];	    /* Machine-dependent sample data	 */
128} __packed;
129
130struct hws_combined_entry {
131	struct hws_basic_entry	basic;	/* Basic-sampling data entry */
132	struct hws_diag_entry	diag;	/* Diagnostic-sampling data entry */
133} __packed;
134
135union hws_trailer_header {
136	struct {
137		unsigned int f:1;	/* 0 - Block Full Indicator   */
138		unsigned int a:1;	/* 1 - Alert request control  */
139		unsigned int t:1;	/* 2 - Timestamp format	      */
140		unsigned int :29;	/* 3 - 31: Reserved	      */
141		unsigned int bsdes:16;	/* 32-47: size of basic SDE   */
142		unsigned int dsdes:16;	/* 48-63: size of diagnostic SDE */
143		unsigned long long overflow; /* 64 - Overflow Count   */
144	};
145	u128 val;
146};
147
148struct hws_trailer_entry {
149	union hws_trailer_header header; /* 0 - 15 Flags + Overflow Count     */
150	unsigned char timestamp[16];	 /* 16 - 31 timestamp		      */
151	unsigned long long reserved1;	 /* 32 -Reserved		      */
152	unsigned long long reserved2;	 /*				      */
153	union {				 /* 48 - reserved for programming use */
154		struct {
155			unsigned int clock_base:1; /* in progusage2 */
156			unsigned long long progusage1:63;
157			unsigned long long progusage2;
158		};
159		unsigned long long progusage[2];
160	};
161} __packed;
162
163/* Load program parameter */
164static inline void lpp(void *pp)
165{
166	asm volatile("lpp 0(%0)\n" :: "a" (pp) : "memory");
167}
168
169/* Query counter information */
170static inline int qctri(struct cpumf_ctr_info *info)
171{
172	int rc = -EINVAL;
173
174	asm_inline volatile (
175		"0:	qctri	%1\n"
176		"1:	lhi	%0,0\n"
177		"2:\n"
178		EX_TABLE(1b, 2b)
179		: "+d" (rc), "=Q" (*info));
180	return rc;
181}
182
183/* Load CPU-counter-set controls */
184static inline int lcctl(u64 ctl)
185{
186	int cc;
187
188	asm_inline volatile (
189		"	lcctl	%[ctl]\n"
190		CC_IPM(cc)
191		: CC_OUT(cc, cc)
192		: [ctl] "Q" (ctl)
193		: CC_CLOBBER);
194	return CC_TRANSFORM(cc);
195}
196
197/* Extract CPU counter */
198static inline int __ecctr(u64 ctr, u64 *content)
199{
200	u64 _content;
201	int cc;
202
203	asm_inline volatile (
204		"	ecctr	%[_content],%[ctr]\n"
205		CC_IPM(cc)
206		: CC_OUT(cc, cc), [_content] "=d" (_content)
207		: [ctr] "d" (ctr)
208		: CC_CLOBBER);
209	*content = _content;
210	return CC_TRANSFORM(cc);
211}
212
213/* Extract CPU counter */
214static inline int ecctr(u64 ctr, u64 *val)
215{
216	u64 content;
217	int cc;
218
219	cc = __ecctr(ctr, &content);
220	if (!cc)
221		*val = content;
222	return cc;
223}
224
225/* Store CPU counter multiple for a particular counter set */
226enum stcctm_ctr_set {
227	EXTENDED = 0,
228	BASIC = 1,
229	PROBLEM_STATE = 2,
230	CRYPTO_ACTIVITY = 3,
231	MT_DIAG = 5,
232	MT_DIAG_CLEARING = 9,	/* clears loss-of-MT-ctr-data alert */
233};
234
235static __always_inline int stcctm(enum stcctm_ctr_set set, u64 range, u64 *dest)
236{
237	int cc;
238
239	asm volatile (
240		"	STCCTM	%[range],%[set],%[dest]\n"
241		CC_IPM(cc)
242		: CC_OUT(cc, cc)
243		: [dest] "Q" (*dest), [range] "d" (range), [set] "i" (set)
244		: CC_CLOBBER_LIST("memory"));
245	/*
246	 * If cc == 2, less than RANGE counters are stored, but it's not easy
247	 * to tell how many. Always unpoison the whole range for simplicity.
248	 */
249	kmsan_unpoison_memory(dest, range * sizeof(u64));
250	return CC_TRANSFORM(cc);
251}
252
253/* Query sampling information */
254static inline int qsi(struct hws_qsi_info_block *info)
255{
256	int cc = 1;
257
258	asm volatile(
259		"0:	qsi	%1\n"
260		"1:	lhi	%0,0\n"
261		"2:\n"
262		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
263		: "+d" (cc), "+Q" (*info));
264	return cc ? -EINVAL : 0;
265}
266
267/* Load sampling controls */
268static inline int lsctl(struct hws_lsctl_request_block *req)
269{
270	int cc, exception;
271
272	exception = 1;
273	asm volatile(
274		"0:	lsctl	%[req]\n"
275		"1:	lhi	%[exc],0\n"
276		"2:\n"
277		CC_IPM(cc)
278		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
279		: CC_OUT(cc, cc), [exc] "+d" (exception)
280		: [req] "Q" (*req)
281		: CC_CLOBBER);
282	if (exception || CC_TRANSFORM(cc))
283		return -EINVAL;
284	return 0;
285}
286#endif /* _ASM_S390_CPU_MF_H */
~/ Read-only file preview.