aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 {