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 17 enum 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 44 void diag_stat_inc(enum diag_stat_enum nr); 45 void diag_stat_inc_norecursion(enum diag_stat_enum nr); 46 47 struct hypfs_diag0c_entry; 48 49 /* 50 * Diagnose 0c: Pseudo Timer 51 */ 52 void diag0c(struct hypfs_diag0c_entry *data); 53 54 /* 55 * Diagnose 10: Release page range 56 */ 57 static 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 */ 76 extern int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode); 77 78 /* 79 * Diagnose 210: Get information about a virtual device 80 */ 81 struct 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 94 extern int diag210(struct diag210 *addr); 95 96 struct diag8c { 97 u8 flags; 98 u8 num_partitions; 99 u16 width; 100 u16 height; 101 u8 data[]; 102 } __packed __aligned(4); 103 104 extern 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 */ 112 enum 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 */ 122 enum diag204_format { 123 DIAG204_INFO_SIMPLE = 0, 124 DIAG204_INFO_EXT = 0x00010000 125 }; 126 127 enum diag204_cpu_flags { 128 DIAG204_CPU_ONLINE = 0x20, 129 DIAG204_CPU_CAPPED = 0x40, 130 }; 131 132 struct 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 141 struct 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 152 struct diag204_part_hdr { 153 __u8 pn; 154 __u8 cpus; 155 char reserved[6]; 156 char part_name[DIAG204_LPAR_NAME_LEN]; 157 } __packed; 158 159 struct 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 180 struct 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 190 struct 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 211 struct diag204_phys_hdr { 212 char reserved1[1]; 213 __u8 cpus; 214 char reserved2[6]; 215 char mgm_name[8]; 216 } __packed; 217 218 struct 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 226 struct 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 235 struct 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 245 struct diag204_x_part_block { 246 struct diag204_x_part_hdr hdr; 247 struct diag204_x_cpu_info cpus[]; 248 } __packed; 249 250 struct diag204_x_phys_block { 251 struct diag204_x_phys_hdr hdr; 252 struct diag204_x_phys_cpu cpus[]; 253 } __packed; 254 255 enum diag26c_sc { 256 DIAG26C_PORT_VNIC = 0x00000024, 257 DIAG26C_MAC_SERVICES = 0x00000030 258 }; 259 260 enum 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 266 struct 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. */ 279 struct 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 306 struct 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 314 struct diag26c_mac_resp { 315 u32 version; 316 u8 mac[ETH_ALEN]; 317 u8 res[2]; 318 } __aligned(8); 319 320 #define CPNC_LINUX 0x4 321 union diag318_info { 322 unsigned long val; 323 struct { 324 unsigned long cpnc : 8; 325 unsigned long cpvc : 56; 326 }; 327 }; 328 329 int diag204(unsigned long subcode, unsigned long size, void *addr); 330 int diag224(void *ptr); 331 int diag26c(void *req, void *resp, enum diag26c_sc subcode); 332 333 struct hypfs_diag0c_entry; 334 335 /* 336 * This structure must contain only pointers/references into 337 * the AMODE31 text section. 338 */ 339 struct 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 348 extern struct diag_ops diag_amode31_ops; 349 extern struct diag210 *__diag210_tmp_amode31; 350 351 int _diag210_amode31(struct diag210 *addr); 352 int _diag26c_amode31(unsigned long rx, unsigned long rx1, enum diag26c_sc subcode); 353 int _diag14_amode31(unsigned long rx, unsigned long ry1, unsigned long subcode); 354 void _diag0c_amode31(unsigned long rx); 355 void _diag308_reset_amode31(void); 356 int _diag8c_amode31(struct diag8c *addr, struct ccw_dev_id *devno, size_t len); 357 358 #endif /* _ASM_S390_DIAG_H */ 359