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