diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2013-08-01 04:16:27 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-08-22 06:20:12 -0400 |
commit | 6b169ac9b4342ff3a1499bdeb7596aa4f1bc401b (patch) | |
tree | 3697bebddba3158aefd5481e7009ecd5ae5a1291 /arch/s390 | |
parent | bee5c2863ef807fa50bbdf8b2bae887c54a97083 (diff) |
s390/kprobes: add support for compare and branch instructions
The compare and branch instructions (not relative) all need special
handling when kprobed:
- if a branch was taken, the instruction pointer should be left alone
- if a branch was not taken, the instruction pointer must be adjusted
The compare and branch instructions family was introduced with the general
instruction extension facility (z10).
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/kernel/kprobes.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 3388b2b2a07d..adbbe7f1cb0d 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -105,14 +105,31 @@ static int __kprobes get_fixup_type(kprobe_opcode_t *insn) | |||
105 | fixup |= FIXUP_RETURN_REGISTER; | 105 | fixup |= FIXUP_RETURN_REGISTER; |
106 | break; | 106 | break; |
107 | case 0xeb: | 107 | case 0xeb: |
108 | if ((insn[2] & 0xff) == 0x44 || /* bxhg */ | 108 | switch (insn[2] & 0xff) { |
109 | (insn[2] & 0xff) == 0x45) /* bxleg */ | 109 | case 0x44: /* bxhg */ |
110 | case 0x45: /* bxleg */ | ||
110 | fixup = FIXUP_BRANCH_NOT_TAKEN; | 111 | fixup = FIXUP_BRANCH_NOT_TAKEN; |
112 | break; | ||
113 | } | ||
111 | break; | 114 | break; |
112 | case 0xe3: /* bctg */ | 115 | case 0xe3: /* bctg */ |
113 | if ((insn[2] & 0xff) == 0x46) | 116 | if ((insn[2] & 0xff) == 0x46) |
114 | fixup = FIXUP_BRANCH_NOT_TAKEN; | 117 | fixup = FIXUP_BRANCH_NOT_TAKEN; |
115 | break; | 118 | break; |
119 | case 0xec: | ||
120 | switch (insn[2] & 0xff) { | ||
121 | case 0xe5: /* clgrb */ | ||
122 | case 0xe6: /* cgrb */ | ||
123 | case 0xf6: /* crb */ | ||
124 | case 0xf7: /* clrb */ | ||
125 | case 0xfc: /* cgib */ | ||
126 | case 0xfd: /* cglib */ | ||
127 | case 0xfe: /* cib */ | ||
128 | case 0xff: /* clib */ | ||
129 | fixup = FIXUP_BRANCH_NOT_TAKEN; | ||
130 | break; | ||
131 | } | ||
132 | break; | ||
116 | } | 133 | } |
117 | return fixup; | 134 | return fixup; |
118 | } | 135 | } |