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