0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/errno.h>
0009 #include <asm/kprobes.h>
0010 #include <asm/dis.h>
0011
0012 int probe_is_prohibited_opcode(u16 *insn)
0013 {
0014 if (!is_known_insn((unsigned char *)insn))
0015 return -EINVAL;
0016 switch (insn[0] >> 8) {
0017 case 0x0c:
0018 case 0x0b:
0019 case 0x83:
0020 case 0x44:
0021 case 0xac:
0022 case 0xad:
0023 return -EINVAL;
0024 case 0xc6:
0025 switch (insn[0] & 0x0f) {
0026 case 0x00:
0027 return -EINVAL;
0028 }
0029 }
0030 switch (insn[0]) {
0031 case 0x0101:
0032 case 0xb25a:
0033 case 0xb240:
0034 case 0xb258:
0035 case 0xb218:
0036 case 0xb228:
0037 case 0xb98d:
0038 case 0xe560:
0039 case 0xe561:
0040 case 0xb2f8:
0041 return -EINVAL;
0042 }
0043 return 0;
0044 }
0045
0046 int probe_get_fixup_type(u16 *insn)
0047 {
0048
0049 int fixup = FIXUP_PSW_NORMAL;
0050
0051 switch (insn[0] >> 8) {
0052 case 0x05:
0053 case 0x0d:
0054 fixup = FIXUP_RETURN_REGISTER;
0055
0056 if ((insn[0] & 0x0f) == 0)
0057 fixup |= FIXUP_BRANCH_NOT_TAKEN;
0058 break;
0059 case 0x06:
0060 case 0x07:
0061 fixup = FIXUP_BRANCH_NOT_TAKEN;
0062 break;
0063 case 0x45:
0064 case 0x4d:
0065 fixup = FIXUP_RETURN_REGISTER;
0066 break;
0067 case 0x47:
0068 case 0x46:
0069 case 0x86:
0070 case 0x87:
0071 fixup = FIXUP_BRANCH_NOT_TAKEN;
0072 break;
0073 case 0x82:
0074 fixup = FIXUP_NOT_REQUIRED;
0075 break;
0076 case 0xb2:
0077 if ((insn[0] & 0xff) == 0xb2)
0078 fixup = FIXUP_NOT_REQUIRED;
0079 break;
0080 case 0xa7:
0081 if ((insn[0] & 0x0f) == 0x05)
0082 fixup |= FIXUP_RETURN_REGISTER;
0083 break;
0084 case 0xc0:
0085 if ((insn[0] & 0x0f) == 0x05)
0086 fixup |= FIXUP_RETURN_REGISTER;
0087 break;
0088 case 0xeb:
0089 switch (insn[2] & 0xff) {
0090 case 0x44:
0091 case 0x45:
0092 fixup = FIXUP_BRANCH_NOT_TAKEN;
0093 break;
0094 }
0095 break;
0096 case 0xe3:
0097 if ((insn[2] & 0xff) == 0x46)
0098 fixup = FIXUP_BRANCH_NOT_TAKEN;
0099 break;
0100 case 0xec:
0101 switch (insn[2] & 0xff) {
0102 case 0xe5:
0103 case 0xe6:
0104 case 0xf6:
0105 case 0xf7:
0106 case 0xfc:
0107 case 0xfd:
0108 case 0xfe:
0109 case 0xff:
0110 fixup = FIXUP_BRANCH_NOT_TAKEN;
0111 break;
0112 }
0113 break;
0114 }
0115 return fixup;
0116 }
0117
0118 int probe_is_insn_relative_long(u16 *insn)
0119 {
0120
0121
0122 switch (insn[0] >> 8) {
0123 case 0xc0:
0124 if ((insn[0] & 0x0f) == 0x00)
0125 return true;
0126 break;
0127 case 0xc4:
0128 switch (insn[0] & 0x0f) {
0129 case 0x02:
0130 case 0x04:
0131 case 0x05:
0132 case 0x06:
0133 case 0x07:
0134 case 0x08:
0135 case 0x0b:
0136 case 0x0c:
0137 case 0x0d:
0138 case 0x0e:
0139 case 0x0f:
0140 return true;
0141 }
0142 break;
0143 case 0xc6:
0144 switch (insn[0] & 0x0f) {
0145 case 0x02:
0146 case 0x04:
0147 case 0x05:
0148 case 0x06:
0149 case 0x07:
0150 case 0x08:
0151 case 0x0a:
0152 case 0x0c:
0153 case 0x0d:
0154 case 0x0e:
0155 case 0x0f:
0156 return true;
0157 }
0158 break;
0159 }
0160 return false;
0161 }