aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel
diff options
context:
space:
mode:
authorbibo,mao <bibo.mao@intel.com>2006-12-12 15:04:42 -0500
committerTony Luck <tony.luck@intel.com>2006-12-12 15:04:42 -0500
commitdf3e0d1c69c097f54588d720d39efdcdf31e3c24 (patch)
tree30740405fa706c1f20981f8c8f91fcd261305308 /arch/ia64/kernel
parent08ed38b68099f2a492196414b08a7f5dd8dc3537 (diff)
[IA64] kprobe clears qp bits for special instructions
On IA64 there exists some special instructions which always need to be executed regradless of qp bits, such as com.crel.unc, tbit.trel.unc etc. This patch clears qp bits when inserting kprobe trap code and disables probepoint on slot 1 for these special instructions. Signed-off-by: bibo,mao <bibo.mao@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r--arch/ia64/kernel/kprobes.c175
1 files changed, 122 insertions, 53 deletions
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 8406d24d516b..6cb56dd4056d 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -130,48 +130,6 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot,
130 130
131/* 131/*
132 * In this function we check to see if the instruction 132 * In this function we check to see if the instruction
133 * on which we are inserting kprobe is supported.
134 * Returns 0 if supported
135 * Returns -EINVAL if unsupported
136 */
137static int __kprobes unsupported_inst(uint template, uint slot,
138 uint major_opcode,
139 unsigned long kprobe_inst,
140 unsigned long addr)
141{
142 if (bundle_encoding[template][slot] == I) {
143 switch (major_opcode) {
144 case 0x0: //I_UNIT_MISC_OPCODE:
145 /*
146 * Check for Integer speculation instruction
147 * - Bit 33-35 to be equal to 0x1
148 */
149 if (((kprobe_inst >> 33) & 0x7) == 1) {
150 printk(KERN_WARNING
151 "Kprobes on speculation inst at <0x%lx> not supported\n",
152 addr);
153 return -EINVAL;
154 }
155
156 /*
157 * IP relative mov instruction
158 * - Bit 27-35 to be equal to 0x30
159 */
160 if (((kprobe_inst >> 27) & 0x1FF) == 0x30) {
161 printk(KERN_WARNING
162 "Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n",
163 addr);
164 return -EINVAL;
165
166 }
167 }
168 }
169 return 0;
170}
171
172
173/*
174 * In this function we check to see if the instruction
175 * (qp) cmpx.crel.ctype p1,p2=r2,r3 133 * (qp) cmpx.crel.ctype p1,p2=r2,r3
176 * on which we are inserting kprobe is cmp instruction 134 * on which we are inserting kprobe is cmp instruction
177 * with ctype as unc. 135 * with ctype as unc.
@@ -207,26 +165,136 @@ out:
207} 165}
208 166
209/* 167/*
168 * In this function we check to see if the instruction
169 * on which we are inserting kprobe is supported.
170 * Returns qp value if supported
171 * Returns -EINVAL if unsupported
172 */
173static int __kprobes unsupported_inst(uint template, uint slot,
174 uint major_opcode,
175 unsigned long kprobe_inst,
176 unsigned long addr)
177{
178 int qp;
179
180 qp = kprobe_inst & 0x3f;
181 if (is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) {
182 if (slot == 1 && qp) {
183 printk(KERN_WARNING "Kprobes on cmp unc"
184 "instruction on slot 1 at <0x%lx>"
185 "is not supported\n", addr);
186 return -EINVAL;
187
188 }
189 qp = 0;
190 }
191 else if (bundle_encoding[template][slot] == I) {
192 if (major_opcode == 0) {
193 /*
194 * Check for Integer speculation instruction
195 * - Bit 33-35 to be equal to 0x1
196 */
197 if (((kprobe_inst >> 33) & 0x7) == 1) {
198 printk(KERN_WARNING
199 "Kprobes on speculation inst at <0x%lx> not supported\n",
200 addr);
201 return -EINVAL;
202 }
203 /*
204 * IP relative mov instruction
205 * - Bit 27-35 to be equal to 0x30
206 */
207 if (((kprobe_inst >> 27) & 0x1FF) == 0x30) {
208 printk(KERN_WARNING
209 "Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n",
210 addr);
211 return -EINVAL;
212
213 }
214 }
215 else if ((major_opcode == 5) && !(kprobe_inst & (0xFUl << 33)) &&
216 (kprobe_inst & (0x1UL << 12))) {
217 /* test bit instructions, tbit,tnat,tf
218 * bit 33-36 to be equal to 0
219 * bit 12 to be equal to 1
220 */
221 if (slot == 1 && qp) {
222 printk(KERN_WARNING "Kprobes on test bit"
223 "instruction on slot at <0x%lx>"
224 "is not supported\n", addr);
225 return -EINVAL;
226 }
227 qp = 0;
228 }
229 }
230 else if (bundle_encoding[template][slot] == B) {
231 if (major_opcode == 7) {
232 /* IP-Relative Predict major code is 7 */
233 printk(KERN_WARNING "Kprobes on IP-Relative"
234 "Predict is not supported\n");
235 return -EINVAL;
236 }
237 else if (major_opcode == 2) {
238 /* Indirect Predict, major code is 2
239 * bit 27-32 to be equal to 10 or 11
240 */
241 int x6=(kprobe_inst >> 27) & 0x3F;
242 if ((x6 == 0x10) || (x6 == 0x11)) {
243 printk(KERN_WARNING "Kprobes on"
244 "Indirect Predict is not supported\n");
245 return -EINVAL;
246 }
247 }
248 }
249 /* kernel does not use float instruction, here for safety kprobe
250 * will judge whether it is fcmp/flass/float approximation instruction
251 */
252 else if (unlikely(bundle_encoding[template][slot] == F)) {
253 if ((major_opcode == 4 || major_opcode == 5) &&
254 (kprobe_inst & (0x1 << 12))) {
255 /* fcmp/fclass unc instruction */
256 if (slot == 1 && qp) {
257 printk(KERN_WARNING "Kprobes on fcmp/fclass "
258 "instruction on slot at <0x%lx> "
259 "is not supported\n", addr);
260 return -EINVAL;
261
262 }
263 qp = 0;
264 }
265 if ((major_opcode == 0 || major_opcode == 1) &&
266 (kprobe_inst & (0x1UL << 33))) {
267 /* float Approximation instruction */
268 if (slot == 1 && qp) {
269 printk(KERN_WARNING "Kprobes on float Approx "
270 "instr at <0x%lx> is not supported\n",
271 addr);
272 return -EINVAL;
273 }
274 qp = 0;
275 }
276 }
277 return qp;
278}
279
280/*
210 * In this function we override the bundle with 281 * In this function we override the bundle with
211 * the break instruction at the given slot. 282 * the break instruction at the given slot.
212 */ 283 */
213static void __kprobes prepare_break_inst(uint template, uint slot, 284static void __kprobes prepare_break_inst(uint template, uint slot,
214 uint major_opcode, 285 uint major_opcode,
215 unsigned long kprobe_inst, 286 unsigned long kprobe_inst,
216 struct kprobe *p) 287 struct kprobe *p,
288 int qp)
217{ 289{
218 unsigned long break_inst = BREAK_INST; 290 unsigned long break_inst = BREAK_INST;
219 bundle_t *bundle = &p->opcode.bundle; 291 bundle_t *bundle = &p->opcode.bundle;
220 292
221 /* 293 /*
222 * Copy the original kprobe_inst qualifying predicate(qp) 294 * Copy the original kprobe_inst qualifying predicate(qp)
223 * to the break instruction iff !is_cmp_ctype_unc_inst 295 * to the break instruction
224 * because for cmp instruction with ctype equal to unc,
225 * which is a special instruction always needs to be
226 * executed regradless of qp
227 */ 296 */
228 if (!is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) 297 break_inst |= qp;
229 break_inst |= (0x3f & kprobe_inst);
230 298
231 switch (slot) { 299 switch (slot) {
232 case 0: 300 case 0:
@@ -422,6 +490,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
422 unsigned long kprobe_inst=0; 490 unsigned long kprobe_inst=0;
423 unsigned int slot = addr & 0xf, template, major_opcode = 0; 491 unsigned int slot = addr & 0xf, template, major_opcode = 0;
424 bundle_t *bundle; 492 bundle_t *bundle;
493 int qp;
425 494
426 bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle; 495 bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle;
427 template = bundle->quad0.template; 496 template = bundle->quad0.template;
@@ -436,9 +505,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
436 /* Get kprobe_inst and major_opcode from the bundle */ 505 /* Get kprobe_inst and major_opcode from the bundle */
437 get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode); 506 get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
438 507
439 if (unsupported_inst(template, slot, major_opcode, kprobe_inst, addr)) 508 qp = unsupported_inst(template, slot, major_opcode, kprobe_inst, addr);
440 return -EINVAL; 509 if (qp < 0)
441 510 return -EINVAL;
442 511
443 p->ainsn.insn = get_insn_slot(); 512 p->ainsn.insn = get_insn_slot();
444 if (!p->ainsn.insn) 513 if (!p->ainsn.insn)
@@ -446,7 +515,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
446 memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t)); 515 memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t));
447 memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t)); 516 memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t));
448 517
449 prepare_break_inst(template, slot, major_opcode, kprobe_inst, p); 518 prepare_break_inst(template, slot, major_opcode, kprobe_inst, p, qp);
450 519
451 return 0; 520 return 0;
452} 521}