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

s390/uprobes: common library for kprobes and uprobes

This patch moves common functions from kprobes.c to probes.c.
Thus its possible for uprobes to use them without enabling kprobes.

Signed-off-by: Jan Willeke <willeke@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Jan Willeke and committed by
Martin Schwidefsky
975fab17 bbae71bf

+168 -151
+4
arch/s390/include/asm/kprobes.h
··· 84 84 int kprobe_exceptions_notify(struct notifier_block *self, 85 85 unsigned long val, void *data); 86 86 87 + int probe_is_prohibited_opcode(u16 *insn); 88 + int probe_get_fixup_type(u16 *insn); 89 + int probe_is_insn_relative_long(u16 *insn); 90 + 87 91 #define flush_insn_slot(p) do { } while (0) 88 92 89 93 #endif /* _ASM_S390_KPROBES_H */
+3 -151
arch/s390/kernel/kprobes.c
··· 58 58 .insn_size = MAX_INSN_SIZE, 59 59 }; 60 60 61 - static int __kprobes is_prohibited_opcode(kprobe_opcode_t *insn) 62 - { 63 - if (!is_known_insn((unsigned char *)insn)) 64 - return -EINVAL; 65 - switch (insn[0] >> 8) { 66 - case 0x0c: /* bassm */ 67 - case 0x0b: /* bsm */ 68 - case 0x83: /* diag */ 69 - case 0x44: /* ex */ 70 - case 0xac: /* stnsm */ 71 - case 0xad: /* stosm */ 72 - return -EINVAL; 73 - case 0xc6: 74 - switch (insn[0] & 0x0f) { 75 - case 0x00: /* exrl */ 76 - return -EINVAL; 77 - } 78 - } 79 - switch (insn[0]) { 80 - case 0x0101: /* pr */ 81 - case 0xb25a: /* bsa */ 82 - case 0xb240: /* bakr */ 83 - case 0xb258: /* bsg */ 84 - case 0xb218: /* pc */ 85 - case 0xb228: /* pt */ 86 - case 0xb98d: /* epsw */ 87 - return -EINVAL; 88 - } 89 - return 0; 90 - } 91 - 92 - static int __kprobes get_fixup_type(kprobe_opcode_t *insn) 93 - { 94 - /* default fixup method */ 95 - int fixup = FIXUP_PSW_NORMAL; 96 - 97 - switch (insn[0] >> 8) { 98 - case 0x05: /* balr */ 99 - case 0x0d: /* basr */ 100 - fixup = FIXUP_RETURN_REGISTER; 101 - /* if r2 = 0, no branch will be taken */ 102 - if ((insn[0] & 0x0f) == 0) 103 - fixup |= FIXUP_BRANCH_NOT_TAKEN; 104 - break; 105 - case 0x06: /* bctr */ 106 - case 0x07: /* bcr */ 107 - fixup = FIXUP_BRANCH_NOT_TAKEN; 108 - break; 109 - case 0x45: /* bal */ 110 - case 0x4d: /* bas */ 111 - fixup = FIXUP_RETURN_REGISTER; 112 - break; 113 - case 0x47: /* bc */ 114 - case 0x46: /* bct */ 115 - case 0x86: /* bxh */ 116 - case 0x87: /* bxle */ 117 - fixup = FIXUP_BRANCH_NOT_TAKEN; 118 - break; 119 - case 0x82: /* lpsw */ 120 - fixup = FIXUP_NOT_REQUIRED; 121 - break; 122 - case 0xb2: /* lpswe */ 123 - if ((insn[0] & 0xff) == 0xb2) 124 - fixup = FIXUP_NOT_REQUIRED; 125 - break; 126 - case 0xa7: /* bras */ 127 - if ((insn[0] & 0x0f) == 0x05) 128 - fixup |= FIXUP_RETURN_REGISTER; 129 - break; 130 - case 0xc0: 131 - if ((insn[0] & 0x0f) == 0x05) /* brasl */ 132 - fixup |= FIXUP_RETURN_REGISTER; 133 - break; 134 - case 0xeb: 135 - switch (insn[2] & 0xff) { 136 - case 0x44: /* bxhg */ 137 - case 0x45: /* bxleg */ 138 - fixup = FIXUP_BRANCH_NOT_TAKEN; 139 - break; 140 - } 141 - break; 142 - case 0xe3: /* bctg */ 143 - if ((insn[2] & 0xff) == 0x46) 144 - fixup = FIXUP_BRANCH_NOT_TAKEN; 145 - break; 146 - case 0xec: 147 - switch (insn[2] & 0xff) { 148 - case 0xe5: /* clgrb */ 149 - case 0xe6: /* cgrb */ 150 - case 0xf6: /* crb */ 151 - case 0xf7: /* clrb */ 152 - case 0xfc: /* cgib */ 153 - case 0xfd: /* cglib */ 154 - case 0xfe: /* cib */ 155 - case 0xff: /* clib */ 156 - fixup = FIXUP_BRANCH_NOT_TAKEN; 157 - break; 158 - } 159 - break; 160 - } 161 - return fixup; 162 - } 163 - 164 - static int __kprobes is_insn_relative_long(kprobe_opcode_t *insn) 165 - { 166 - /* Check if we have a RIL-b or RIL-c format instruction which 167 - * we need to modify in order to avoid instruction emulation. */ 168 - switch (insn[0] >> 8) { 169 - case 0xc0: 170 - if ((insn[0] & 0x0f) == 0x00) /* larl */ 171 - return true; 172 - break; 173 - case 0xc4: 174 - switch (insn[0] & 0x0f) { 175 - case 0x02: /* llhrl */ 176 - case 0x04: /* lghrl */ 177 - case 0x05: /* lhrl */ 178 - case 0x06: /* llghrl */ 179 - case 0x07: /* sthrl */ 180 - case 0x08: /* lgrl */ 181 - case 0x0b: /* stgrl */ 182 - case 0x0c: /* lgfrl */ 183 - case 0x0d: /* lrl */ 184 - case 0x0e: /* llgfrl */ 185 - case 0x0f: /* strl */ 186 - return true; 187 - } 188 - break; 189 - case 0xc6: 190 - switch (insn[0] & 0x0f) { 191 - case 0x02: /* pfdrl */ 192 - case 0x04: /* cghrl */ 193 - case 0x05: /* chrl */ 194 - case 0x06: /* clghrl */ 195 - case 0x07: /* clhrl */ 196 - case 0x08: /* cgrl */ 197 - case 0x0a: /* clgrl */ 198 - case 0x0c: /* cgfrl */ 199 - case 0x0d: /* crl */ 200 - case 0x0e: /* clgfrl */ 201 - case 0x0f: /* clrl */ 202 - return true; 203 - } 204 - break; 205 - } 206 - return false; 207 - } 208 - 209 61 static void __kprobes copy_instruction(struct kprobe *p) 210 62 { 211 63 s64 disp, new_disp; 212 64 u64 addr, new_addr; 213 65 214 66 memcpy(p->ainsn.insn, p->addr, insn_length(p->opcode >> 8)); 215 - if (!is_insn_relative_long(p->ainsn.insn)) 67 + if (!probe_is_insn_relative_long(p->ainsn.insn)) 216 68 return; 217 69 /* 218 70 * For pc-relative instructions in RIL-b or RIL-c format patch the ··· 128 276 if ((unsigned long) p->addr & 0x01) 129 277 return -EINVAL; 130 278 /* Make sure the probe isn't going on a difficult instruction */ 131 - if (is_prohibited_opcode(p->addr)) 279 + if (probe_is_prohibited_opcode(p->addr)) 132 280 return -EINVAL; 133 281 if (s390_get_insn_slot(p)) 134 282 return -ENOMEM; ··· 457 605 { 458 606 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 459 607 unsigned long ip = regs->psw.addr & PSW_ADDR_INSN; 460 - int fixup = get_fixup_type(p->ainsn.insn); 608 + int fixup = probe_get_fixup_type(p->ainsn.insn); 461 609 462 610 if (fixup & FIXUP_PSW_NORMAL) 463 611 ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn;
+2
arch/s390/lib/Makefile
··· 6 6 obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o mem32.o 7 7 obj-$(CONFIG_64BIT) += mem64.o 8 8 lib-$(CONFIG_SMP) += spinlock.o 9 + lib-$(CONFIG_KPROBES) += probes.o 10 + lib-$(CONFIG_UPROBES) += probes.o
+159
arch/s390/lib/probes.c
··· 1 + /* 2 + * Common helper functions for kprobes and uprobes 3 + * 4 + * Copyright IBM Corp. 2014 5 + */ 6 + 7 + #include <linux/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 + }