1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * s390 diagnose functions
4 *
5 * Copyright IBM Corp. 2007
6 * Author(s): Michael Holzheu <holzheu@de.ibm.com>
7 */
8
9 #ifndef _ASM_S390_DIAG_H
10 #define _ASM_S390_DIAG_H
11
12 #include <linux/if_ether.h>
13 #include <linux/percpu.h>
14 #include <asm/asm-extable.h>
15 #include <asm/sclp.h>
16 #include <asm/cio.h>
17
18 enum diag_stat_enum {
19 DIAG_STAT_X008,
20 DIAG_STAT_X00C,
21 DIAG_STAT_X010,
22 DIAG_STAT_X014,
23 DIAG_STAT_X044,
24 DIAG_STAT_X064,
25 DIAG_STAT_X08C,
26 DIAG_STAT_X09C,
27 DIAG_STAT_X0DC,
28 DIAG_STAT_X204,
29 DIAG_STAT_X210,
30 DIAG_STAT_X224,
31 DIAG_STAT_X250,
32 DIAG_STAT_X258,
33 DIAG_STAT_X26C,
34 DIAG_STAT_X288,
35 DIAG_STAT_X2C4,
36 DIAG_STAT_X2FC,
37 DIAG_STAT_X304,
38 DIAG_STAT_X308,
39 DIAG_STAT_X310,
40 DIAG_STAT_X318,
41 DIAG_STAT_X320,
42 DIAG_STAT_X324,
43 DIAG_STAT_X49C,
44 DIAG_STAT_X500,
45 NR_DIAG_STAT
46 };
47
48 void diag_stat_inc(enum diag_stat_enum nr);
49 void diag_stat_inc_norecursion(enum diag_stat_enum nr);
50
51 struct hypfs_diag0c_entry;
52
53 /*
54 * Diagnose 0c: Pseudo Timer
55 */
56 void diag0c(struct hypfs_diag0c_entry *data);
57
58 /*
59 * Diagnose 10: Release page range
60 */
diag10_range(unsigned long start_pfn,unsigned long num_pfn)61 static inline void diag10_range(unsigned long start_pfn, unsigned long num_pfn)
62 {
63 unsigned long start_addr, end_addr;
64
65 start_addr = pfn_to_phys(start_pfn);
66 end_addr = pfn_to_phys(start_pfn + num_pfn - 1);
67
68 diag_stat_inc(DIAG_STAT_X010);
69 asm_inline volatile(
70 "0: diag %0,%1,0x10\n"
71 "1:\n"
72 EX_TABLE_INSN(0b, 1b)
73 : : "a" (start_addr), "a" (end_addr));
74 }
75
76 /*
77 * Diagnose 14: Input spool file manipulation
78 */
79 extern int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode);
80
81 /*
82 * Diagnose 210: Get information about a virtual device
83 */
84 struct diag210 {
85 u16 vrdcdvno; /* device number (input) */
86 u16 vrdclen; /* data block length (input) */
87 u8 vrdcvcla; /* virtual device class (output) */
88 u8 vrdcvtyp; /* virtual device type (output) */
89 u8 vrdcvsta; /* virtual device status (output) */
90 u8 vrdcvfla; /* virtual device flags (output) */
91 u8 vrdcrccl; /* real device class (output) */
92 u8 vrdccrty; /* real device type (output) */
93 u8 vrdccrmd; /* real device model (output) */
94 u8 vrdccrft; /* real device feature (output) */
95 } __packed __aligned(4);
96
97 extern int diag210(struct diag210 *addr);
98
99 struct diag8c {
100 u8 flags;
101 u8 num_partitions;
102 u16 width;
103 u16 height;
104 u8 data[];
105 } __packed __aligned(4);
106
107 extern int diag8c(struct diag8c *out, struct ccw_dev_id *devno);
108
109 /* bit is set in flags, when physical cpu info is included in diag 204 data */
110 #define DIAG204_LPAR_PHYS_FLG 0x80
111 #define DIAG204_LPAR_NAME_LEN 8 /* lpar name len in diag 204 data */
112 #define DIAG204_CPU_NAME_LEN 16 /* type name len of cpus in diag224 name table */
113
114 /* diag 204 subcodes */
115 enum diag204_sc {
116 DIAG204_SUBC_STIB4 = 4,
117 DIAG204_SUBC_RSI = 5,
118 DIAG204_SUBC_STIB6 = 6,
119 DIAG204_SUBC_STIB7 = 7
120 };
121
122 #define DIAG204_SUBCODE_MASK 0xffff
123 #define DIAG204_BIF_BIT 0x80000000
124 #define DIAG204_BUSY_WAIT (HZ / 10)
125
126 /* The two available diag 204 data formats */
127 enum diag204_format {
128 DIAG204_INFO_SIMPLE = 0,
129 DIAG204_INFO_EXT = 0x00010000
130 };
131
132 enum diag204_cpu_flags {
133 DIAG204_CPU_ONLINE = 0x20,
134 DIAG204_CPU_CAPPED = 0x40,
135 };
136
137 struct diag204_info_blk_hdr {
138 __u8 npar;
139 __u8 flags;
140 __u16 tslice;
141 __u16 phys_cpus;
142 __u16 this_part;
143 __u64 curtod;
144 } __packed;
145
146 struct diag204_x_info_blk_hdr {
147 __u8 npar;
148 __u8 flags;
149 __u16 tslice;
150 __u16 phys_cpus;
151 __u16 this_part;
152 __u64 curtod1;
153 __u64 curtod2;
154 char reserved[40];
155 } __packed;
156
157 struct diag204_part_hdr {
158 __u8 pn;
159 __u8 cpus;
160 char reserved[6];
161 char part_name[DIAG204_LPAR_NAME_LEN];
162 } __packed;
163
164 struct diag204_x_part_hdr {
165 __u8 pn;
166 __u8 cpus;
167 __u8 rcpus;
168 __u8 pflag;
169 __u32 mlu;
170 char part_name[DIAG204_LPAR_NAME_LEN];
171 char lpc_name[8];
172 char os_name[8];
173 __u64 online_cs;
174 __u64 online_es;
175 __u8 upid;
176 __u8 reserved:3;
177 __u8 mtid:5;
178 char reserved1[2];
179 __u32 group_mlu;
180 char group_name[8];
181 char hardware_group_name[8];
182 char reserved2[24];
183 } __packed;
184
185 struct diag204_cpu_info {
186 __u16 cpu_addr;
187 char reserved1[2];
188 __u8 ctidx;
189 __u8 cflag;
190 __u16 weight;
191 __u64 acc_time;
192 __u64 lp_time;
193 } __packed;
194
195 struct diag204_x_cpu_info {
196 __u16 cpu_addr;
197 char reserved1[2];
198 __u8 ctidx;
199 __u8 cflag;
200 __u16 weight;
201 __u64 acc_time;
202 __u64 lp_time;
203 __u16 min_weight;
204 __u16 cur_weight;
205 __u16 max_weight;
206 char reseved2[2];
207 __u64 online_time;
208 __u64 wait_time;
209 __u32 pma_weight;
210 __u32 polar_weight;
211 __u32 cpu_type_cap;
212 __u32 group_cpu_type_cap;
213 char reserved3[32];
214 } __packed;
215
216 struct diag204_phys_hdr {
217 char reserved1[1];
218 __u8 cpus;
219 char reserved2[6];
220 char mgm_name[8];
221 } __packed;
222
223 struct diag204_x_phys_hdr {
224 char reserved1[1];
225 __u8 cpus;
226 char reserved2[6];
227 char mgm_name[8];
228 char reserved3[80];
229 } __packed;
230
231 struct diag204_phys_cpu {
232 __u16 cpu_addr;
233 char reserved1[2];
234 __u8 ctidx;
235 char reserved2[3];
236 __u64 mgm_time;
237 char reserved3[8];
238 } __packed;
239
240 struct diag204_x_phys_cpu {
241 __u16 cpu_addr;
242 char reserved1[2];
243 __u8 ctidx;
244 char reserved2[1];
245 __u16 weight;
246 __u64 mgm_time;
247 char reserved3[80];
248 } __packed;
249
250 struct diag204_x_part_block {
251 struct diag204_x_part_hdr hdr;
252 struct diag204_x_cpu_info cpus[];
253 } __packed;
254
255 struct diag204_x_phys_block {
256 struct diag204_x_phys_hdr hdr;
257 struct diag204_x_phys_cpu cpus[];
258 } __packed;
259
260 enum diag26c_sc {
261 DIAG26C_PORT_VNIC = 0x00000024,
262 DIAG26C_MAC_SERVICES = 0x00000030
263 };
264
265 enum diag26c_version {
266 DIAG26C_VERSION2 = 0x00000002, /* z/VM 5.4.0 */
267 DIAG26C_VERSION6_VM65918 = 0x00020006 /* z/VM 6.4.0 + VM65918 */
268 };
269
270 #define DIAG26C_VNIC_INFO 0x0002
271 struct diag26c_vnic_req {
272 u32 resp_buf_len;
273 u32 resp_version;
274 u16 req_format;
275 u16 vlan_id;
276 u64 sys_name;
277 u8 res[2];
278 u16 devno;
279 } __packed __aligned(8);
280
281 #define VNIC_INFO_PROT_L3 1
282 #define VNIC_INFO_PROT_L2 2
283 /* Note: this is the bare minimum, use it for uninitialized VNICs only. */
284 struct diag26c_vnic_resp {
285 u32 version;
286 u32 entry_cnt;
287 /* VNIC info: */
288 u32 next_entry;
289 u64 owner;
290 u16 devno;
291 u8 status;
292 u8 type;
293 u64 lan_owner;
294 u64 lan_name;
295 u64 port_name;
296 u8 port_type;
297 u8 ext_status:6;
298 u8 protocol:2;
299 u16 base_devno;
300 u32 port_num;
301 u32 ifindex;
302 u32 maxinfo;
303 u32 dev_count;
304 /* 3x device info: */
305 u8 dev_info1[28];
306 u8 dev_info2[28];
307 u8 dev_info3[28];
308 } __packed __aligned(8);
309
310 #define DIAG26C_GET_MAC 0x0000
311 struct diag26c_mac_req {
312 u32 resp_buf_len;
313 u32 resp_version;
314 u16 op_code;
315 u16 devno;
316 u8 res[4];
317 };
318
319 struct diag26c_mac_resp {
320 u32 version;
321 u8 mac[ETH_ALEN];
322 u8 res[2];
323 } __aligned(8);
324
325 #define CPNC_LINUX 0x4
326 union diag318_info {
327 unsigned long val;
328 struct {
329 unsigned long cpnc : 8;
330 unsigned long cpvc : 56;
331 };
332 };
333
diag204_has_bif(void)334 static inline bool diag204_has_bif(void)
335 {
336 return sclp.has_diag204_bif;
337 }
338
339 int diag204(unsigned long subcode, unsigned long size, void *addr);
340 int diag224(void *ptr);
341 int diag26c(void *req, void *resp, enum diag26c_sc subcode);
342
343 struct hypfs_diag0c_entry;
344
345 /*
346 * This structure must contain only pointers/references into
347 * the AMODE31 text section.
348 */
349 struct diag_ops {
350 int (*diag210)(struct diag210 *addr);
351 int (*diag26c)(unsigned long rx, unsigned long rx1, enum diag26c_sc subcode);
352 int (*diag14)(unsigned long rx, unsigned long ry1, unsigned long subcode);
353 int (*diag8c)(struct diag8c *addr, struct ccw_dev_id *devno, size_t len);
354 void (*diag0c)(unsigned long rx);
355 void (*diag308_reset)(void);
356 };
357
358 extern struct diag_ops diag_amode31_ops;
359 extern struct diag210 *__diag210_tmp_amode31;
360
361 int _diag210_amode31(struct diag210 *addr);
362 int _diag26c_amode31(unsigned long rx, unsigned long rx1, enum diag26c_sc subcode);
363 int _diag14_amode31(unsigned long rx, unsigned long ry1, unsigned long subcode);
364 void _diag0c_amode31(unsigned long rx);
365 void _diag308_reset_amode31(void);
366 int _diag8c_amode31(struct diag8c *addr, struct ccw_dev_id *devno, size_t len);
367
368 /* diag 49c subcodes */
369 enum diag49c_sc {
370 DIAG49C_SUBC_ACK = 0,
371 DIAG49C_SUBC_REG = 1
372 };
373
374 int diag49c(unsigned long subcode);
375
376 #endif /* _ASM_S390_DIAG_H */
377