aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnil S Keshavamurthy <anil.s.keshavamurthy@intel.com>2005-06-23 03:09:33 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-23 12:45:23 -0400
commit1674eafcbd3e3c68556cf19fbf4a2c30f7add729 (patch)
treed57a4698902a4bc2c2e6a08d24c42ec2a5c67706
parenta5403183d84d419651672f1aee5ff2273d185efa (diff)
[PATCH] Kprobes IA64: cmp ctype unc support
The current Kprobes when patching the original instruction with the break instruction tries to retain the original qualifying predicate(qp), however for cmp.crel.ctype where ctype == unc, which is a special instruction always needs to be executed irrespective of qp. Hence, if the instruction we are patching is of this type, then we should not copy the original qp to the break instruction, this is because we always want the break fault to happen so that we can emulate the instruction. This patch is based on the feedback given by David Mosberger Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/ia64/kernel/kprobes.c43
-rw-r--r--include/asm-ia64/kprobes.h17
2 files changed, 58 insertions, 2 deletions
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 5d5344681555..51bc08bd0466 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -120,6 +120,41 @@ static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode
120} 120}
121 121
122/* 122/*
123 * In this function we check to see if the instruction
124 * (qp) cmpx.crel.ctype p1,p2=r2,r3
125 * on which we are inserting kprobe is cmp instruction
126 * with ctype as unc.
127 */
128static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode,
129unsigned long kprobe_inst)
130{
131 cmp_inst_t cmp_inst;
132 uint ctype_unc = 0;
133
134 if (!((bundle_encoding[template][slot] == I) ||
135 (bundle_encoding[template][slot] == M)))
136 goto out;
137
138 if (!((major_opcode == 0xC) || (major_opcode == 0xD) ||
139 (major_opcode == 0xE)))
140 goto out;
141
142 cmp_inst.l = kprobe_inst;
143 if ((cmp_inst.f.x2 == 0) || (cmp_inst.f.x2 == 1)) {
144 /* Integere compare - Register Register (A6 type)*/
145 if ((cmp_inst.f.tb == 0) && (cmp_inst.f.ta == 0)
146 &&(cmp_inst.f.c == 1))
147 ctype_unc = 1;
148 } else if ((cmp_inst.f.x2 == 2)||(cmp_inst.f.x2 == 3)) {
149 /* Integere compare - Immediate Register (A8 type)*/
150 if ((cmp_inst.f.ta == 0) &&(cmp_inst.f.c == 1))
151 ctype_unc = 1;
152 }
153out:
154 return ctype_unc;
155}
156
157/*
123 * In this function we override the bundle with 158 * In this function we override the bundle with
124 * the break instruction at the given slot. 159 * the break instruction at the given slot.
125 */ 160 */
@@ -131,9 +166,13 @@ static void prepare_break_inst(uint template, uint slot, uint major_opcode,
131 166
132 /* 167 /*
133 * Copy the original kprobe_inst qualifying predicate(qp) 168 * Copy the original kprobe_inst qualifying predicate(qp)
134 * to the break instruction 169 * to the break instruction iff !is_cmp_ctype_unc_inst
170 * because for cmp instruction with ctype equal to unc,
171 * which is a special instruction always needs to be
172 * executed regradless of qp
135 */ 173 */
136 break_inst |= (0x3f & kprobe_inst); 174 if (!is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst))
175 break_inst |= (0x3f & kprobe_inst);
137 176
138 switch (slot) { 177 switch (slot) {
139 case 0: 178 case 0:
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index cec4d9958307..7b700035e36d 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -30,6 +30,23 @@
30 30
31#define BREAK_INST (long)(__IA64_BREAK_KPROBE << 6) 31#define BREAK_INST (long)(__IA64_BREAK_KPROBE << 6)
32 32
33typedef union cmp_inst {
34 struct {
35 unsigned long long qp : 6;
36 unsigned long long p1 : 6;
37 unsigned long long c : 1;
38 unsigned long long r2 : 7;
39 unsigned long long r3 : 7;
40 unsigned long long p2 : 6;
41 unsigned long long ta : 1;
42 unsigned long long x2 : 2;
43 unsigned long long tb : 1;
44 unsigned long long opcode : 4;
45 unsigned long long reserved : 23;
46 }f;
47 unsigned long long l;
48} cmp_inst_t;
49
33struct kprobe; 50struct kprobe;
34 51
35typedef struct _bundle { 52typedef struct _bundle {