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