diff options
-rw-r--r-- | arch/ia64/kernel/kprobes.c | 43 | ||||
-rw-r--r-- | include/asm-ia64/kprobes.h | 17 |
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 | */ | ||
128 | static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode, | ||
129 | unsigned 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 | } | ||
153 | out: | ||
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 | ||
33 | typedef 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 | |||
33 | struct kprobe; | 50 | struct kprobe; |
34 | 51 | ||
35 | typedef struct _bundle { | 52 | typedef struct _bundle { |