Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/s390/include/asm/cpu_mf.h
26493 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
/*
3
* CPU-measurement facilities
4
*
5
* Copyright IBM Corp. 2012, 2018
6
* Author(s): Hendrik Brueckner <[email protected]>
7
* Jan Glauber <[email protected]>
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
18
asm(".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 */
37
static inline int cpum_cf_avail(void)
38
{
39
return test_facility(40) && test_facility(67);
40
}
41
42
static inline int cpum_sf_avail(void)
43
{
44
return test_facility(40) && test_facility(68);
45
}
46
47
struct 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 */
60
struct 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 */
84
struct 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
103
struct 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
123
struct 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
130
struct 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
135
union 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
148
struct 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 */
164
static inline void lpp(void *pp)
165
{
166
asm volatile("lpp 0(%0)\n" :: "a" (pp) : "memory");
167
}
168
169
/* Query counter information */
170
static 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 */
184
static 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 */
198
static 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 */
214
static 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 */
226
enum 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
235
static __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 */
254
static 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 */
268
static 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 */
287
288