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