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