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