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