1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Functionality for SIE interception handling. 4 * 5 * Copyright IBM Corp. 2024 6 */ 7 8 #include <sie-icpt.h> 9 sblk_ip_as_diag(struct kvm_s390_sie_block * sblk)10struct diag_itext sblk_ip_as_diag(struct kvm_s390_sie_block *sblk) 11 { 12 union { 13 struct { 14 uint64_t ipa : 16; 15 uint64_t ipb : 32; 16 uint64_t : 16; 17 }; 18 struct diag_itext diag; 19 } instr = { .ipa = sblk->ipa, .ipb = sblk->ipb }; 20 21 return instr.diag; 22 } 23 sie_is_diag_icpt(struct vm * vm,unsigned int diag)24bool sie_is_diag_icpt(struct vm *vm, unsigned int diag) 25 { 26 struct diag_itext instr = sblk_ip_as_diag(vm->sblk); 27 uint8_t icptcode; 28 uint64_t code; 29 30 switch (diag) { 31 case 0x44: 32 case 0x9c: 33 case 0x288: 34 case 0x308: 35 icptcode = ICPT_PV_NOTIFY; 36 break; 37 case 0x500: 38 icptcode = ICPT_PV_INSTR; 39 break; 40 default: 41 /* If a new diag is introduced add it to the cases above! */ 42 assert_msg(false, "unknown diag 0x%x", diag); 43 } 44 45 if (sie_is_pv(vm)) { 46 if (instr.r_1 != 0 || instr.r_2 != 2 || instr.r_base != 5) 47 return false; 48 if (instr.displace) 49 return false; 50 } else { 51 icptcode = ICPT_INST; 52 } 53 if (vm->sblk->icptcode != icptcode) 54 return false; 55 if (instr.opcode != 0x83 || instr.zero) 56 return false; 57 code = instr.r_base ? vm->save_area.guest.grs[instr.r_base] : 0; 58 code = (code + instr.displace) & 0xffff; 59 return code == diag; 60 } 61