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