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