diff options
Diffstat (limited to 'arch/ia64')
-rw-r--r-- | arch/ia64/kernel/kprobes.c | 89 |
1 files changed, 45 insertions, 44 deletions
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 169ec3a7156c..9c9c8fcdfbdc 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -90,7 +90,7 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot, | |||
90 | p->ainsn.target_br_reg = 0; | 90 | p->ainsn.target_br_reg = 0; |
91 | 91 | ||
92 | /* Check for Break instruction | 92 | /* Check for Break instruction |
93 | * Bits 37:40 Major opcode to be zero | 93 | * Bits 37:40 Major opcode to be zero |
94 | * Bits 27:32 X6 to be zero | 94 | * Bits 27:32 X6 to be zero |
95 | * Bits 32:35 X3 to be zero | 95 | * Bits 32:35 X3 to be zero |
96 | */ | 96 | */ |
@@ -104,19 +104,19 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot, | |||
104 | switch (major_opcode) { | 104 | switch (major_opcode) { |
105 | case INDIRECT_CALL_OPCODE: | 105 | case INDIRECT_CALL_OPCODE: |
106 | p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG; | 106 | p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG; |
107 | p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7); | 107 | p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7); |
108 | break; | 108 | break; |
109 | case IP_RELATIVE_PREDICT_OPCODE: | 109 | case IP_RELATIVE_PREDICT_OPCODE: |
110 | case IP_RELATIVE_BRANCH_OPCODE: | 110 | case IP_RELATIVE_BRANCH_OPCODE: |
111 | p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR; | 111 | p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR; |
112 | break; | 112 | break; |
113 | case IP_RELATIVE_CALL_OPCODE: | 113 | case IP_RELATIVE_CALL_OPCODE: |
114 | p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR; | 114 | p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR; |
115 | p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG; | 115 | p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG; |
116 | p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7); | 116 | p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7); |
117 | break; | 117 | break; |
118 | } | 118 | } |
119 | } else if (bundle_encoding[template][slot] == X) { | 119 | } else if (bundle_encoding[template][slot] == X) { |
120 | switch (major_opcode) { | 120 | switch (major_opcode) { |
121 | case LONG_CALL_OPCODE: | 121 | case LONG_CALL_OPCODE: |
122 | p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG; | 122 | p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG; |
@@ -258,18 +258,18 @@ static void __kprobes get_kprobe_inst(bundle_t *bundle, uint slot, | |||
258 | 258 | ||
259 | switch (slot) { | 259 | switch (slot) { |
260 | case 0: | 260 | case 0: |
261 | *major_opcode = (bundle->quad0.slot0 >> SLOT0_OPCODE_SHIFT); | 261 | *major_opcode = (bundle->quad0.slot0 >> SLOT0_OPCODE_SHIFT); |
262 | *kprobe_inst = bundle->quad0.slot0; | 262 | *kprobe_inst = bundle->quad0.slot0; |
263 | break; | 263 | break; |
264 | case 1: | 264 | case 1: |
265 | *major_opcode = (bundle->quad1.slot1_p1 >> SLOT1_p1_OPCODE_SHIFT); | 265 | *major_opcode = (bundle->quad1.slot1_p1 >> SLOT1_p1_OPCODE_SHIFT); |
266 | kprobe_inst_p0 = bundle->quad0.slot1_p0; | 266 | kprobe_inst_p0 = bundle->quad0.slot1_p0; |
267 | kprobe_inst_p1 = bundle->quad1.slot1_p1; | 267 | kprobe_inst_p1 = bundle->quad1.slot1_p1; |
268 | *kprobe_inst = kprobe_inst_p0 | (kprobe_inst_p1 << (64-46)); | 268 | *kprobe_inst = kprobe_inst_p0 | (kprobe_inst_p1 << (64-46)); |
269 | break; | 269 | break; |
270 | case 2: | 270 | case 2: |
271 | *major_opcode = (bundle->quad1.slot2 >> SLOT2_OPCODE_SHIFT); | 271 | *major_opcode = (bundle->quad1.slot2 >> SLOT2_OPCODE_SHIFT); |
272 | *kprobe_inst = bundle->quad1.slot2; | 272 | *kprobe_inst = bundle->quad1.slot2; |
273 | break; | 273 | break; |
274 | } | 274 | } |
275 | } | 275 | } |
@@ -290,11 +290,11 @@ static int __kprobes valid_kprobe_addr(int template, int slot, | |||
290 | return -EINVAL; | 290 | return -EINVAL; |
291 | } | 291 | } |
292 | 292 | ||
293 | if (in_ivt_functions(addr)) { | 293 | if (in_ivt_functions(addr)) { |
294 | printk(KERN_WARNING "Kprobes can't be inserted inside " | 294 | printk(KERN_WARNING "Kprobes can't be inserted inside " |
295 | "IVT functions at 0x%lx\n", addr); | 295 | "IVT functions at 0x%lx\n", addr); |
296 | return -EINVAL; | 296 | return -EINVAL; |
297 | } | 297 | } |
298 | 298 | ||
299 | if (slot == 1 && bundle_encoding[template][1] != L) { | 299 | if (slot == 1 && bundle_encoding[template][1] != L) { |
300 | printk(KERN_WARNING "Inserting kprobes on slot #1 " | 300 | printk(KERN_WARNING "Inserting kprobes on slot #1 " |
@@ -424,14 +424,14 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
424 | bundle_t *bundle; | 424 | bundle_t *bundle; |
425 | 425 | ||
426 | bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle; | 426 | bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle; |
427 | template = bundle->quad0.template; | 427 | template = bundle->quad0.template; |
428 | 428 | ||
429 | if(valid_kprobe_addr(template, slot, addr)) | 429 | if(valid_kprobe_addr(template, slot, addr)) |
430 | return -EINVAL; | 430 | return -EINVAL; |
431 | 431 | ||
432 | /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */ | 432 | /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */ |
433 | if (slot == 1 && bundle_encoding[template][1] == L) | 433 | if (slot == 1 && bundle_encoding[template][1] == L) |
434 | slot++; | 434 | slot++; |
435 | 435 | ||
436 | /* Get kprobe_inst and major_opcode from the bundle */ | 436 | /* Get kprobe_inst and major_opcode from the bundle */ |
437 | get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode); | 437 | get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode); |
@@ -489,21 +489,22 @@ void __kprobes arch_remove_kprobe(struct kprobe *p) | |||
489 | */ | 489 | */ |
490 | static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) | 490 | static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) |
491 | { | 491 | { |
492 | unsigned long bundle_addr = (unsigned long) (&p->ainsn.insn->bundle); | 492 | unsigned long bundle_addr = (unsigned long) (&p->ainsn.insn->bundle); |
493 | unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL; | 493 | unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL; |
494 | unsigned long template; | 494 | unsigned long template; |
495 | int slot = ((unsigned long)p->addr & 0xf); | 495 | int slot = ((unsigned long)p->addr & 0xf); |
496 | 496 | ||
497 | template = p->ainsn.insn->bundle.quad0.template; | 497 | template = p->ainsn.insn->bundle.quad0.template; |
498 | 498 | ||
499 | if (slot == 1 && bundle_encoding[template][1] == L) | 499 | if (slot == 1 && bundle_encoding[template][1] == L) |
500 | slot = 2; | 500 | slot = 2; |
501 | 501 | ||
502 | if (p->ainsn.inst_flag) { | 502 | if (p->ainsn.inst_flag) { |
503 | 503 | ||
504 | if (p->ainsn.inst_flag & INST_FLAG_FIX_RELATIVE_IP_ADDR) { | 504 | if (p->ainsn.inst_flag & INST_FLAG_FIX_RELATIVE_IP_ADDR) { |
505 | /* Fix relative IP address */ | 505 | /* Fix relative IP address */ |
506 | regs->cr_iip = (regs->cr_iip - bundle_addr) + resume_addr; | 506 | regs->cr_iip = (regs->cr_iip - bundle_addr) + |
507 | resume_addr; | ||
507 | } | 508 | } |
508 | 509 | ||
509 | if (p->ainsn.inst_flag & INST_FLAG_FIX_BRANCH_REG) { | 510 | if (p->ainsn.inst_flag & INST_FLAG_FIX_BRANCH_REG) { |
@@ -540,18 +541,18 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) | |||
540 | } | 541 | } |
541 | 542 | ||
542 | if (slot == 2) { | 543 | if (slot == 2) { |
543 | if (regs->cr_iip == bundle_addr + 0x10) { | 544 | if (regs->cr_iip == bundle_addr + 0x10) { |
544 | regs->cr_iip = resume_addr + 0x10; | 545 | regs->cr_iip = resume_addr + 0x10; |
545 | } | 546 | } |
546 | } else { | 547 | } else { |
547 | if (regs->cr_iip == bundle_addr) { | 548 | if (regs->cr_iip == bundle_addr) { |
548 | regs->cr_iip = resume_addr; | 549 | regs->cr_iip = resume_addr; |
549 | } | 550 | } |
550 | } | 551 | } |
551 | 552 | ||
552 | turn_ss_off: | 553 | turn_ss_off: |
553 | /* Turn off Single Step bit */ | 554 | /* Turn off Single Step bit */ |
554 | ia64_psr(regs)->ss = 0; | 555 | ia64_psr(regs)->ss = 0; |
555 | } | 556 | } |
556 | 557 | ||
557 | static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs) | 558 | static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs) |
@@ -587,7 +588,7 @@ static int __kprobes is_ia64_break_inst(struct pt_regs *regs) | |||
587 | 588 | ||
588 | /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */ | 589 | /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */ |
589 | if (slot == 1 && bundle_encoding[template][1] == L) | 590 | if (slot == 1 && bundle_encoding[template][1] == L) |
590 | slot++; | 591 | slot++; |
591 | 592 | ||
592 | /* Get Kprobe probe instruction at given slot*/ | 593 | /* Get Kprobe probe instruction at given slot*/ |
593 | get_kprobe_inst(&bundle, slot, &kprobe_inst, &major_opcode); | 594 | get_kprobe_inst(&bundle, slot, &kprobe_inst, &major_opcode); |
@@ -627,7 +628,7 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) | |||
627 | if (p) { | 628 | if (p) { |
628 | if ((kcb->kprobe_status == KPROBE_HIT_SS) && | 629 | if ((kcb->kprobe_status == KPROBE_HIT_SS) && |
629 | (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) { | 630 | (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) { |
630 | ia64_psr(regs)->ss = 0; | 631 | ia64_psr(regs)->ss = 0; |
631 | goto no_kprobe; | 632 | goto no_kprobe; |
632 | } | 633 | } |
633 | /* We have reentered the pre_kprobe_handler(), since | 634 | /* We have reentered the pre_kprobe_handler(), since |
@@ -887,7 +888,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
887 | * fix the return address to our jprobe_inst_return() function | 888 | * fix the return address to our jprobe_inst_return() function |
888 | * in the jprobes.S file | 889 | * in the jprobes.S file |
889 | */ | 890 | */ |
890 | regs->b0 = ((struct fnptr *)(jprobe_inst_return))->ip; | 891 | regs->b0 = ((struct fnptr *)(jprobe_inst_return))->ip; |
891 | 892 | ||
892 | return 1; | 893 | return 1; |
893 | } | 894 | } |