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