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