Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: s390: Add sthyi emulation

Store Hypervisor Information is an emulated z/VM instruction that
provides a guest with basic information about the layers it is running
on. This includes information about the cpu configuration of both the
machine and the lpar, as well as their names, machine model and
machine type. This information enables an application to determine the
maximum capacity of CPs and IFLs available to software.

The instruction is available whenever the facility bit 74 is set,
otherwise executing it results in an operation exception.

It is important to check the validity flags in the sections before
using data from any structure member. It is not guaranteed that all
members will be valid on all machines / machine configurations.

Signed-off-by: Janosch Frank <frankja@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>

authored by

Janosch Frank and committed by
Christian Borntraeger
95ca2cb5 a2d57b35

+507 -1
+10
arch/s390/include/asm/diag.h
··· 215 215 char reserved3[80]; 216 216 } __packed; 217 217 218 + struct diag204_x_part_block { 219 + struct diag204_x_part_hdr hdr; 220 + struct diag204_x_cpu_info cpus[]; 221 + } __packed; 222 + 223 + struct diag204_x_phys_block { 224 + struct diag204_x_phys_hdr hdr; 225 + struct diag204_x_phys_cpu cpus[]; 226 + } __packed; 227 + 218 228 int diag204(unsigned long subcode, unsigned long size, void *addr); 219 229 int diag224(void *ptr); 220 230 #endif /* _ASM_S390_DIAG_H */
+2
arch/s390/include/asm/kvm_host.h
··· 154 154 #define LCTL_CR14 0x0002 155 155 __u16 lctl; /* 0x0044 */ 156 156 __s16 icpua; /* 0x0046 */ 157 + #define ICTL_OPEREXC 0x80000000 157 158 #define ICTL_PINT 0x20000000 158 159 #define ICTL_LPSW 0x00400000 159 160 #define ICTL_STCTL 0x00040000 ··· 280 279 u32 instruction_stfl; 281 280 u32 instruction_tprot; 282 281 u32 instruction_essa; 282 + u32 instruction_sthyi; 283 283 u32 instruction_sigp_sense; 284 284 u32 instruction_sigp_sense_running; 285 285 u32 instruction_sigp_external_call;
+1
arch/s390/include/uapi/asm/sie.h
··· 140 140 exit_code_ipa0(0xB2, 0x4c, "TAR"), \ 141 141 exit_code_ipa0(0xB2, 0x50, "CSP"), \ 142 142 exit_code_ipa0(0xB2, 0x54, "MVPG"), \ 143 + exit_code_ipa0(0xB2, 0x56, "STHYI"), \ 143 144 exit_code_ipa0(0xB2, 0x58, "BSG"), \ 144 145 exit_code_ipa0(0xB2, 0x5a, "BSA"), \ 145 146 exit_code_ipa0(0xB2, 0x5f, "CHSC"), \
+1 -1
arch/s390/kvm/Makefile
··· 12 12 ccflags-y := -Ivirt/kvm -Iarch/s390/kvm 13 13 14 14 kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o 15 - kvm-objs += diag.o gaccess.o guestdbg.o 15 + kvm-objs += diag.o gaccess.o guestdbg.o sthyi.o 16 16 17 17 obj-$(CONFIG_KVM) += kvm.o
+4
arch/s390/kvm/intercept.c
··· 355 355 trace_kvm_s390_handle_operexc(vcpu, vcpu->arch.sie_block->ipa, 356 356 vcpu->arch.sie_block->ipb); 357 357 358 + if (vcpu->arch.sie_block->ipa == 0xb256 && 359 + test_kvm_facility(vcpu->kvm, 74)) 360 + return handle_sthyi(vcpu); 361 + 358 362 return kvm_s390_inject_program_int(vcpu, PGM_OPERATION); 359 363 } 360 364
+6
arch/s390/kvm/kvm-s390.c
··· 94 94 { "instruction_stsi", VCPU_STAT(instruction_stsi) }, 95 95 { "instruction_stfl", VCPU_STAT(instruction_stfl) }, 96 96 { "instruction_tprot", VCPU_STAT(instruction_tprot) }, 97 + { "instruction_sthyi", VCPU_STAT(instruction_sthyi) }, 97 98 { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) }, 98 99 { "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) }, 99 100 { "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) }, ··· 1190 1189 memcpy(kvm->arch.model.fac_list, kvm->arch.model.fac_mask, 1191 1190 S390_ARCH_FAC_LIST_SIZE_BYTE); 1192 1191 1192 + set_kvm_facility(kvm->arch.model.fac_mask, 74); 1193 + set_kvm_facility(kvm->arch.model.fac_list, 74); 1194 + 1193 1195 kvm->arch.model.cpuid = kvm_s390_get_initial_cpuid(); 1194 1196 kvm->arch.model.ibc = sclp.ibc & 0x0fff; 1195 1197 ··· 1683 1679 } 1684 1680 vcpu->arch.sie_block->riccbd = (unsigned long) &vcpu->run->s.regs.riccb; 1685 1681 vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE; 1682 + if (test_kvm_facility(vcpu->kvm, 74)) 1683 + vcpu->arch.sie_block->ictl |= ICTL_OPEREXC; 1686 1684 1687 1685 if (vcpu->kvm->arch.use_cmma) { 1688 1686 rc = kvm_s390_vcpu_setup_cmma(vcpu);
+3
arch/s390/kvm/kvm-s390.h
··· 250 250 int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); 251 251 int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu); 252 252 253 + /* implemented in sthyi.c */ 254 + int handle_sthyi(struct kvm_vcpu *vcpu); 255 + 253 256 /* implemented in kvm-s390.c */ 254 257 void kvm_s390_set_tod_clock(struct kvm *kvm, u64 tod); 255 258 long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable);
+460
arch/s390/kvm/sthyi.c
··· 1 + /* 2 + * store hypervisor information instruction emulation functions. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License (version 2 only) 6 + * as published by the Free Software Foundation. 7 + * 8 + * Copyright IBM Corp. 2016 9 + * Author(s): Janosch Frank <frankja@linux.vnet.ibm.com> 10 + */ 11 + #include <linux/kvm_host.h> 12 + #include <linux/errno.h> 13 + #include <linux/pagemap.h> 14 + #include <linux/vmalloc.h> 15 + 16 + #include <asm/kvm_host.h> 17 + #include <asm/asm-offsets.h> 18 + #include <asm/sclp.h> 19 + #include <asm/diag.h> 20 + #include <asm/sysinfo.h> 21 + #include <asm/ebcdic.h> 22 + 23 + #include "kvm-s390.h" 24 + #include "gaccess.h" 25 + #include "trace.h" 26 + 27 + #define DED_WEIGHT 0xffff 28 + /* 29 + * CP and IFL as EBCDIC strings, SP/0x40 determines the end of string 30 + * as they are justified with spaces. 31 + */ 32 + #define CP 0xc3d7404040404040UL 33 + #define IFL 0xc9c6d34040404040UL 34 + 35 + enum hdr_flags { 36 + HDR_NOT_LPAR = 0x10, 37 + HDR_STACK_INCM = 0x20, 38 + HDR_STSI_UNAV = 0x40, 39 + HDR_PERF_UNAV = 0x80, 40 + }; 41 + 42 + enum mac_validity { 43 + MAC_NAME_VLD = 0x20, 44 + MAC_ID_VLD = 0x40, 45 + MAC_CNT_VLD = 0x80, 46 + }; 47 + 48 + enum par_flag { 49 + PAR_MT_EN = 0x80, 50 + }; 51 + 52 + enum par_validity { 53 + PAR_GRP_VLD = 0x08, 54 + PAR_ID_VLD = 0x10, 55 + PAR_ABS_VLD = 0x20, 56 + PAR_WGHT_VLD = 0x40, 57 + PAR_PCNT_VLD = 0x80, 58 + }; 59 + 60 + struct hdr_sctn { 61 + u8 infhflg1; 62 + u8 infhflg2; /* reserved */ 63 + u8 infhval1; /* reserved */ 64 + u8 infhval2; /* reserved */ 65 + u8 reserved[3]; 66 + u8 infhygct; 67 + u16 infhtotl; 68 + u16 infhdln; 69 + u16 infmoff; 70 + u16 infmlen; 71 + u16 infpoff; 72 + u16 infplen; 73 + u16 infhoff1; 74 + u16 infhlen1; 75 + u16 infgoff1; 76 + u16 infglen1; 77 + u16 infhoff2; 78 + u16 infhlen2; 79 + u16 infgoff2; 80 + u16 infglen2; 81 + u16 infhoff3; 82 + u16 infhlen3; 83 + u16 infgoff3; 84 + u16 infglen3; 85 + u8 reserved2[4]; 86 + } __packed; 87 + 88 + struct mac_sctn { 89 + u8 infmflg1; /* reserved */ 90 + u8 infmflg2; /* reserved */ 91 + u8 infmval1; 92 + u8 infmval2; /* reserved */ 93 + u16 infmscps; 94 + u16 infmdcps; 95 + u16 infmsifl; 96 + u16 infmdifl; 97 + char infmname[8]; 98 + char infmtype[4]; 99 + char infmmanu[16]; 100 + char infmseq[16]; 101 + char infmpman[4]; 102 + u8 reserved[4]; 103 + } __packed; 104 + 105 + struct par_sctn { 106 + u8 infpflg1; 107 + u8 infpflg2; /* reserved */ 108 + u8 infpval1; 109 + u8 infpval2; /* reserved */ 110 + u16 infppnum; 111 + u16 infpscps; 112 + u16 infpdcps; 113 + u16 infpsifl; 114 + u16 infpdifl; 115 + u16 reserved; 116 + char infppnam[8]; 117 + u32 infpwbcp; 118 + u32 infpabcp; 119 + u32 infpwbif; 120 + u32 infpabif; 121 + char infplgnm[8]; 122 + u32 infplgcp; 123 + u32 infplgif; 124 + } __packed; 125 + 126 + struct sthyi_sctns { 127 + struct hdr_sctn hdr; 128 + struct mac_sctn mac; 129 + struct par_sctn par; 130 + } __packed; 131 + 132 + struct cpu_inf { 133 + u64 lpar_cap; 134 + u64 lpar_grp_cap; 135 + u64 lpar_weight; 136 + u64 all_weight; 137 + int cpu_num_ded; 138 + int cpu_num_shd; 139 + }; 140 + 141 + struct lpar_cpu_inf { 142 + struct cpu_inf cp; 143 + struct cpu_inf ifl; 144 + }; 145 + 146 + static inline u64 cpu_id(u8 ctidx, void *diag224_buf) 147 + { 148 + return *((u64 *)(diag224_buf + (ctidx + 1) * DIAG204_CPU_NAME_LEN)); 149 + } 150 + 151 + /* 152 + * Scales the cpu capping from the lpar range to the one expected in 153 + * sthyi data. 154 + * 155 + * diag204 reports a cap in hundredths of processor units. 156 + * z/VM's range for one core is 0 - 0x10000. 157 + */ 158 + static u32 scale_cap(u32 in) 159 + { 160 + return (0x10000 * in) / 100; 161 + } 162 + 163 + static void fill_hdr(struct sthyi_sctns *sctns) 164 + { 165 + sctns->hdr.infhdln = sizeof(sctns->hdr); 166 + sctns->hdr.infmoff = sizeof(sctns->hdr); 167 + sctns->hdr.infmlen = sizeof(sctns->mac); 168 + sctns->hdr.infplen = sizeof(sctns->par); 169 + sctns->hdr.infpoff = sctns->hdr.infhdln + sctns->hdr.infmlen; 170 + sctns->hdr.infhtotl = sctns->hdr.infpoff + sctns->hdr.infplen; 171 + } 172 + 173 + static void fill_stsi_mac(struct sthyi_sctns *sctns, 174 + struct sysinfo_1_1_1 *sysinfo) 175 + { 176 + if (stsi(sysinfo, 1, 1, 1)) 177 + return; 178 + 179 + sclp_ocf_cpc_name_copy(sctns->mac.infmname); 180 + 181 + memcpy(sctns->mac.infmtype, sysinfo->type, sizeof(sctns->mac.infmtype)); 182 + memcpy(sctns->mac.infmmanu, sysinfo->manufacturer, sizeof(sctns->mac.infmmanu)); 183 + memcpy(sctns->mac.infmpman, sysinfo->plant, sizeof(sctns->mac.infmpman)); 184 + memcpy(sctns->mac.infmseq, sysinfo->sequence, sizeof(sctns->mac.infmseq)); 185 + 186 + sctns->mac.infmval1 |= MAC_ID_VLD | MAC_NAME_VLD; 187 + } 188 + 189 + static void fill_stsi_par(struct sthyi_sctns *sctns, 190 + struct sysinfo_2_2_2 *sysinfo) 191 + { 192 + if (stsi(sysinfo, 2, 2, 2)) 193 + return; 194 + 195 + sctns->par.infppnum = sysinfo->lpar_number; 196 + memcpy(sctns->par.infppnam, sysinfo->name, sizeof(sctns->par.infppnam)); 197 + 198 + sctns->par.infpval1 |= PAR_ID_VLD; 199 + } 200 + 201 + static void fill_stsi(struct sthyi_sctns *sctns) 202 + { 203 + void *sysinfo; 204 + 205 + /* Errors are handled through the validity bits in the response. */ 206 + sysinfo = (void *)__get_free_page(GFP_KERNEL); 207 + if (!sysinfo) 208 + return; 209 + 210 + fill_stsi_mac(sctns, sysinfo); 211 + fill_stsi_par(sctns, sysinfo); 212 + 213 + free_pages((unsigned long)sysinfo, 0); 214 + } 215 + 216 + static void fill_diag_mac(struct sthyi_sctns *sctns, 217 + struct diag204_x_phys_block *block, 218 + void *diag224_buf) 219 + { 220 + int i; 221 + 222 + for (i = 0; i < block->hdr.cpus; i++) { 223 + switch (cpu_id(block->cpus[i].ctidx, diag224_buf)) { 224 + case CP: 225 + if (block->cpus[i].weight == DED_WEIGHT) 226 + sctns->mac.infmdcps++; 227 + else 228 + sctns->mac.infmscps++; 229 + break; 230 + case IFL: 231 + if (block->cpus[i].weight == DED_WEIGHT) 232 + sctns->mac.infmdifl++; 233 + else 234 + sctns->mac.infmsifl++; 235 + break; 236 + } 237 + } 238 + sctns->mac.infmval1 |= MAC_CNT_VLD; 239 + } 240 + 241 + /* Returns a pointer to the the next partition block. */ 242 + static struct diag204_x_part_block *lpar_cpu_inf(struct lpar_cpu_inf *part_inf, 243 + bool this_lpar, 244 + void *diag224_buf, 245 + struct diag204_x_part_block *block) 246 + { 247 + int i, capped = 0, weight_cp = 0, weight_ifl = 0; 248 + struct cpu_inf *cpu_inf; 249 + 250 + for (i = 0; i < block->hdr.rcpus; i++) { 251 + if (!(block->cpus[i].cflag & DIAG204_CPU_ONLINE)) 252 + continue; 253 + 254 + switch (cpu_id(block->cpus[i].ctidx, diag224_buf)) { 255 + case CP: 256 + cpu_inf = &part_inf->cp; 257 + if (block->cpus[i].cur_weight < DED_WEIGHT) 258 + weight_cp |= block->cpus[i].cur_weight; 259 + break; 260 + case IFL: 261 + cpu_inf = &part_inf->ifl; 262 + if (block->cpus[i].cur_weight < DED_WEIGHT) 263 + weight_ifl |= block->cpus[i].cur_weight; 264 + break; 265 + default: 266 + continue; 267 + } 268 + 269 + if (!this_lpar) 270 + continue; 271 + 272 + capped |= block->cpus[i].cflag & DIAG204_CPU_CAPPED; 273 + cpu_inf->lpar_cap |= block->cpus[i].cpu_type_cap; 274 + cpu_inf->lpar_grp_cap |= block->cpus[i].group_cpu_type_cap; 275 + 276 + if (block->cpus[i].weight == DED_WEIGHT) 277 + cpu_inf->cpu_num_ded += 1; 278 + else 279 + cpu_inf->cpu_num_shd += 1; 280 + } 281 + 282 + if (this_lpar && capped) { 283 + part_inf->cp.lpar_weight = weight_cp; 284 + part_inf->ifl.lpar_weight = weight_ifl; 285 + } 286 + part_inf->cp.all_weight += weight_cp; 287 + part_inf->ifl.all_weight += weight_ifl; 288 + return (struct diag204_x_part_block *)&block->cpus[i]; 289 + } 290 + 291 + static void fill_diag(struct sthyi_sctns *sctns) 292 + { 293 + int i, r, pages; 294 + bool this_lpar; 295 + void *diag204_buf; 296 + void *diag224_buf = NULL; 297 + struct diag204_x_info_blk_hdr *ti_hdr; 298 + struct diag204_x_part_block *part_block; 299 + struct diag204_x_phys_block *phys_block; 300 + struct lpar_cpu_inf lpar_inf = {}; 301 + 302 + /* Errors are handled through the validity bits in the response. */ 303 + pages = diag204((unsigned long)DIAG204_SUBC_RSI | 304 + (unsigned long)DIAG204_INFO_EXT, 0, NULL); 305 + if (pages <= 0) 306 + return; 307 + 308 + diag204_buf = vmalloc(PAGE_SIZE * pages); 309 + if (!diag204_buf) 310 + return; 311 + 312 + r = diag204((unsigned long)DIAG204_SUBC_STIB7 | 313 + (unsigned long)DIAG204_INFO_EXT, pages, diag204_buf); 314 + if (r < 0) 315 + goto out; 316 + 317 + diag224_buf = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA); 318 + if (!diag224_buf || diag224(diag224_buf)) 319 + goto out; 320 + 321 + ti_hdr = diag204_buf; 322 + part_block = diag204_buf + sizeof(*ti_hdr); 323 + 324 + for (i = 0; i < ti_hdr->npar; i++) { 325 + /* 326 + * For the calling lpar we also need to get the cpu 327 + * caps and weights. The time information block header 328 + * specifies the offset to the partition block of the 329 + * caller lpar, so we know when we process its data. 330 + */ 331 + this_lpar = (void *)part_block - diag204_buf == ti_hdr->this_part; 332 + part_block = lpar_cpu_inf(&lpar_inf, this_lpar, diag224_buf, 333 + part_block); 334 + } 335 + 336 + phys_block = (struct diag204_x_phys_block *)part_block; 337 + part_block = diag204_buf + ti_hdr->this_part; 338 + if (part_block->hdr.mtid) 339 + sctns->par.infpflg1 = PAR_MT_EN; 340 + 341 + sctns->par.infpval1 |= PAR_GRP_VLD; 342 + sctns->par.infplgcp = scale_cap(lpar_inf.cp.lpar_grp_cap); 343 + sctns->par.infplgif = scale_cap(lpar_inf.ifl.lpar_grp_cap); 344 + memcpy(sctns->par.infplgnm, part_block->hdr.hardware_group_name, 345 + sizeof(sctns->par.infplgnm)); 346 + 347 + sctns->par.infpscps = lpar_inf.cp.cpu_num_shd; 348 + sctns->par.infpdcps = lpar_inf.cp.cpu_num_ded; 349 + sctns->par.infpsifl = lpar_inf.ifl.cpu_num_shd; 350 + sctns->par.infpdifl = lpar_inf.ifl.cpu_num_ded; 351 + sctns->par.infpval1 |= PAR_PCNT_VLD; 352 + 353 + sctns->par.infpabcp = scale_cap(lpar_inf.cp.lpar_cap); 354 + sctns->par.infpabif = scale_cap(lpar_inf.ifl.lpar_cap); 355 + sctns->par.infpval1 |= PAR_ABS_VLD; 356 + 357 + /* 358 + * Everything below needs global performance data to be 359 + * meaningful. 360 + */ 361 + if (!(ti_hdr->flags & DIAG204_LPAR_PHYS_FLG)) { 362 + sctns->hdr.infhflg1 |= HDR_PERF_UNAV; 363 + goto out; 364 + } 365 + 366 + fill_diag_mac(sctns, phys_block, diag224_buf); 367 + 368 + if (lpar_inf.cp.lpar_weight) { 369 + sctns->par.infpwbcp = sctns->mac.infmscps * 0x10000 * 370 + lpar_inf.cp.lpar_weight / lpar_inf.cp.all_weight; 371 + } 372 + 373 + if (lpar_inf.ifl.lpar_weight) { 374 + sctns->par.infpwbif = sctns->mac.infmsifl * 0x10000 * 375 + lpar_inf.ifl.lpar_weight / lpar_inf.ifl.all_weight; 376 + } 377 + sctns->par.infpval1 |= PAR_WGHT_VLD; 378 + 379 + out: 380 + kfree(diag224_buf); 381 + vfree(diag204_buf); 382 + } 383 + 384 + static int sthyi(u64 vaddr) 385 + { 386 + register u64 code asm("0") = 0; 387 + register u64 addr asm("2") = vaddr; 388 + int cc; 389 + 390 + asm volatile( 391 + ".insn rre,0xB2560000,%[code],%[addr]\n" 392 + "ipm %[cc]\n" 393 + "srl %[cc],28\n" 394 + : [cc] "=d" (cc) 395 + : [code] "d" (code), [addr] "a" (addr) 396 + : "memory", "cc"); 397 + return cc; 398 + } 399 + 400 + int handle_sthyi(struct kvm_vcpu *vcpu) 401 + { 402 + int reg1, reg2, r = 0; 403 + u64 code, addr, cc = 0; 404 + struct sthyi_sctns *sctns = NULL; 405 + 406 + kvm_s390_get_regs_rre(vcpu, &reg1, &reg2); 407 + code = vcpu->run->s.regs.gprs[reg1]; 408 + addr = vcpu->run->s.regs.gprs[reg2]; 409 + 410 + vcpu->stat.instruction_sthyi++; 411 + VCPU_EVENT(vcpu, 3, "STHYI: fc: %llu addr: 0x%016llx", code, addr); 412 + trace_kvm_s390_handle_sthyi(vcpu, code, addr); 413 + 414 + if (reg1 == reg2 || reg1 & 1 || reg2 & 1 || addr & ~PAGE_MASK) 415 + return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 416 + 417 + if (code & 0xffff) { 418 + cc = 3; 419 + goto out; 420 + } 421 + 422 + /* 423 + * If the page has not yet been faulted in, we want to do that 424 + * now and not after all the expensive calculations. 425 + */ 426 + r = write_guest(vcpu, addr, reg2, &cc, 1); 427 + if (r) 428 + return kvm_s390_inject_prog_cond(vcpu, r); 429 + 430 + sctns = (void *)get_zeroed_page(GFP_KERNEL); 431 + if (!sctns) 432 + return -ENOMEM; 433 + 434 + /* 435 + * If we are a guest, we don't want to emulate an emulated 436 + * instruction. We ask the hypervisor to provide the data. 437 + */ 438 + if (test_facility(74)) { 439 + cc = sthyi((u64)sctns); 440 + goto out; 441 + } 442 + 443 + fill_hdr(sctns); 444 + fill_stsi(sctns); 445 + fill_diag(sctns); 446 + 447 + out: 448 + if (!cc) { 449 + r = write_guest(vcpu, addr, reg2, sctns, PAGE_SIZE); 450 + if (r) { 451 + free_page((unsigned long)sctns); 452 + return kvm_s390_inject_prog_cond(vcpu, r); 453 + } 454 + } 455 + 456 + free_page((unsigned long)sctns); 457 + vcpu->run->s.regs.gprs[reg2 + 1] = cc ? 4 : 0; 458 + kvm_s390_set_psw_cc(vcpu, cc); 459 + return r; 460 + }
+20
arch/s390/kvm/trace.h
··· 433 433 icpt_insn_codes)) 434 434 ); 435 435 436 + TRACE_EVENT(kvm_s390_handle_sthyi, 437 + TP_PROTO(VCPU_PROTO_COMMON, u64 code, u64 addr), 438 + TP_ARGS(VCPU_ARGS_COMMON, code, addr), 439 + 440 + TP_STRUCT__entry( 441 + VCPU_FIELD_COMMON 442 + __field(u64, code) 443 + __field(u64, addr) 444 + ), 445 + 446 + TP_fast_assign( 447 + VCPU_ASSIGN_COMMON 448 + __entry->code = code; 449 + __entry->addr = addr; 450 + ), 451 + 452 + VCPU_TP_PRINTK("STHYI fc: %llu addr: %016llx", 453 + __entry->code, __entry->addr) 454 + ); 455 + 436 456 #endif /* _TRACE_KVM_H */ 437 457 438 458 /* This part must be outside protection */