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