1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Common helper functions for kprobes and uprobes 4 * 5 * Copyright IBM Corp. 2014 6 */ 7 8 #include <linux/errno.h> 9 #include <asm/kprobes.h> 10 #include <asm/dis.h> 11 probe_is_prohibited_opcode(u16 * insn)12int probe_is_prohibited_opcode(u16 *insn) 13 { 14 if (!is_known_insn((unsigned char *)insn)) 15 return -EINVAL; 16 switch (insn[0] >> 8) { 17 case 0x0c: /* bassm */ 18 case 0x0b: /* bsm */ 19 case 0x83: /* diag */ 20 case 0x44: /* ex */ 21 case 0xac: /* stnsm */ 22 case 0xad: /* stosm */ 23 return -EINVAL; 24 case 0xc6: 25 switch (insn[0] & 0x0f) { 26 case 0x00: /* exrl */ 27 return -EINVAL; 28 } 29 } 30 switch (insn[0]) { 31 case 0x0101: /* pr */ 32 case 0xb25a: /* bsa */ 33 case 0xb240: /* bakr */ 34 case 0xb258: /* bsg */ 35 case 0xb218: /* pc */ 36 case 0xb228: /* pt */ 37 case 0xb98d: /* epsw */ 38 case 0xe560: /* tbegin */ 39 case 0xe561: /* tbeginc */ 40 case 0xb2f8: /* tend */ 41 return -EINVAL; 42 } 43 return 0; 44 } 45 probe_get_fixup_type(u16 * insn)46int probe_get_fixup_type(u16 *insn) 47 { 48 /* default fixup method */ 49 int fixup = FIXUP_PSW_NORMAL; 50 51 switch (insn[0] >> 8) { 52 case 0x05: /* balr */ 53 case 0x0d: /* basr */ 54 fixup = FIXUP_RETURN_REGISTER; 55 /* if r2 = 0, no branch will be taken */ 56 if ((insn[0] & 0x0f) == 0) 57 fixup |= FIXUP_BRANCH_NOT_TAKEN; 58 break; 59 case 0x06: /* bctr */ 60 case 0x07: /* bcr */ 61 fixup = FIXUP_BRANCH_NOT_TAKEN; 62 break; 63 case 0x45: /* bal */ 64 case 0x4d: /* bas */ 65 fixup = FIXUP_RETURN_REGISTER; 66 break; 67 case 0x47: /* bc */ 68 case 0x46: /* bct */ 69 case 0x86: /* bxh */ 70 case 0x87: /* bxle */ 71 fixup = FIXUP_BRANCH_NOT_TAKEN; 72 break; 73 case 0x82: /* lpsw */ 74 fixup = FIXUP_NOT_REQUIRED; 75 break; 76 case 0xb2: /* lpswe */ 77 if ((insn[0] & 0xff) == 0xb2) 78 fixup = FIXUP_NOT_REQUIRED; 79 break; 80 case 0xb9: /* bctgr */ 81 if ((insn[0] & 0xff) == 0x46) 82 fixup = FIXUP_BRANCH_NOT_TAKEN; 83 break; 84 case 0xa7: /* bras */ 85 if ((insn[0] & 0x0f) == 0x05) 86 fixup |= FIXUP_RETURN_REGISTER; 87 break; 88 case 0xc0: 89 if ((insn[0] & 0x0f) == 0x05) /* brasl */ 90 fixup |= FIXUP_RETURN_REGISTER; 91 break; 92 case 0xe3: 93 switch (insn[2] & 0xff) { 94 case 0x46: /* bctg */ 95 case 0x47: /* bic */ 96 fixup = FIXUP_BRANCH_NOT_TAKEN; 97 break; 98 } 99 break; 100 case 0xeb: 101 switch (insn[2] & 0xff) { 102 case 0x44: /* bxhg */ 103 case 0x45: /* bxleg */ 104 fixup = FIXUP_BRANCH_NOT_TAKEN; 105 break; 106 } 107 break; 108 case 0xec: 109 switch (insn[2] & 0xff) { 110 case 0xe4: /* cgrb */ 111 case 0xe5: /* clgrb */ 112 case 0xf6: /* crb */ 113 case 0xf7: /* clrb */ 114 case 0xfc: /* cgib */ 115 case 0xfd: /* clgib */ 116 case 0xfe: /* cib */ 117 case 0xff: /* clib */ 118 fixup = FIXUP_BRANCH_NOT_TAKEN; 119 break; 120 } 121 break; 122 } 123 return fixup; 124 } 125 probe_is_insn_relative_long(u16 * insn)126int probe_is_insn_relative_long(u16 *insn) 127 { 128 /* Check if we have a RIL-b or RIL-c format instruction which 129 * we need to modify in order to avoid instruction emulation. */ 130 switch (insn[0] >> 8) { 131 case 0xc0: 132 if ((insn[0] & 0x0f) == 0x00) /* larl */ 133 return true; 134 break; 135 case 0xc4: 136 switch (insn[0] & 0x0f) { 137 case 0x02: /* llhrl */ 138 case 0x04: /* lghrl */ 139 case 0x05: /* lhrl */ 140 case 0x06: /* llghrl */ 141 case 0x07: /* sthrl */ 142 case 0x08: /* lgrl */ 143 case 0x0b: /* stgrl */ 144 case 0x0c: /* lgfrl */ 145 case 0x0d: /* lrl */ 146 case 0x0e: /* llgfrl */ 147 case 0x0f: /* strl */ 148 return true; 149 } 150 break; 151 case 0xc6: 152 switch (insn[0] & 0x0f) { 153 case 0x02: /* pfdrl */ 154 case 0x04: /* cghrl */ 155 case 0x05: /* chrl */ 156 case 0x06: /* clghrl */ 157 case 0x07: /* clhrl */ 158 case 0x08: /* cgrl */ 159 case 0x0a: /* clgrl */ 160 case 0x0c: /* cgfrl */ 161 case 0x0d: /* crl */ 162 case 0x0e: /* clgfrl */ 163 case 0x0f: /* clrl */ 164 return true; 165 } 166 break; 167 } 168 return false; 169 } 170