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