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