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