[IA64] enable trap code on slot 1

Because slot 1 of one instr bundle crosses border of two consecutive
8-bytes, kprobe on slot 1 is disabled. This patch enables kprobe on
slot1, it only replaces higher 8-bytes of the instruction bundle and
changes the exception code to ignore the low 12 bits of the break
number (which is across the border in the lower 8-bytes of the bundle).

For those instructions which must execute regardless qp bits,
kprobe on slot 1 is still disabled.

Signed-off-by: bibo,mao <bibo.mao@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>

Tony Luck 08ed38b6 75f6a1de

+42 -17
+2 -1
arch/ia64/kernel/jprobes.S
··· 45 * to the correct location. 46 */ 47 #include <asm/asmmacro.h> 48 49 /* 50 * void jprobe_break(void) 51 */ 52 .section .kprobes.text, "ax" 53 ENTRY(jprobe_break) 54 - break.m 0x80300 55 END(jprobe_break) 56 57 /*
··· 45 * to the correct location. 46 */ 47 #include <asm/asmmacro.h> 48 + #include <asm-ia64/break.h> 49 50 /* 51 * void jprobe_break(void) 52 */ 53 .section .kprobes.text, "ax" 54 ENTRY(jprobe_break) 55 + break.m __IA64_BREAK_JPROBE 56 END(jprobe_break) 57 58 /*
+37 -14
arch/ia64/kernel/kprobes.c
··· 88 { 89 p->ainsn.inst_flag = 0; 90 p->ainsn.target_br_reg = 0; 91 92 /* Check for Break instruction 93 * Bits 37:40 Major opcode to be zero ··· 297 return -EINVAL; 298 } 299 300 - if (slot == 1 && bundle_encoding[template][1] != L) { 301 - printk(KERN_WARNING "Inserting kprobes on slot #1 " 302 - "is not supported\n"); 303 - return -EINVAL; 304 - } 305 - 306 return 0; 307 } 308 ··· 453 454 void __kprobes arch_arm_kprobe(struct kprobe *p) 455 { 456 - unsigned long addr = (unsigned long)p->addr; 457 - unsigned long arm_addr = addr & ~0xFULL; 458 459 flush_icache_range((unsigned long)p->ainsn.insn, 460 (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t)); 461 - memcpy((char *)arm_addr, &p->opcode, sizeof(kprobe_opcode_t)); 462 flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t)); 463 } 464 465 void __kprobes arch_disarm_kprobe(struct kprobe *p) 466 { 467 - unsigned long addr = (unsigned long)p->addr; 468 - unsigned long arm_addr = addr & ~0xFULL; 469 470 /* p->ainsn.insn contains the original unaltered kprobe_opcode_t */ 471 - memcpy((char *) arm_addr, (char *) p->ainsn.insn, 472 - sizeof(kprobe_opcode_t)); 473 flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t)); 474 } 475 ··· 828 switch(val) { 829 case DIE_BREAK: 830 /* err is break number from ia64_bad_break() */ 831 - if (args->err == 0x80200 || args->err == 0x80300 || args->err == 0) 832 if (pre_kprobes_handler(args)) 833 ret = NOTIFY_STOP; 834 break;
··· 88 { 89 p->ainsn.inst_flag = 0; 90 p->ainsn.target_br_reg = 0; 91 + p->ainsn.slot = slot; 92 93 /* Check for Break instruction 94 * Bits 37:40 Major opcode to be zero ··· 296 return -EINVAL; 297 } 298 299 return 0; 300 } 301 ··· 458 459 void __kprobes arch_arm_kprobe(struct kprobe *p) 460 { 461 + unsigned long arm_addr; 462 + bundle_t *src, *dest; 463 + 464 + arm_addr = ((unsigned long)p->addr) & ~0xFUL; 465 + dest = &((kprobe_opcode_t *)arm_addr)->bundle; 466 + src = &p->opcode.bundle; 467 468 flush_icache_range((unsigned long)p->ainsn.insn, 469 (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t)); 470 + switch (p->ainsn.slot) { 471 + case 0: 472 + dest->quad0.slot0 = src->quad0.slot0; 473 + break; 474 + case 1: 475 + dest->quad1.slot1_p1 = src->quad1.slot1_p1; 476 + break; 477 + case 2: 478 + dest->quad1.slot2 = src->quad1.slot2; 479 + break; 480 + } 481 flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t)); 482 } 483 484 void __kprobes arch_disarm_kprobe(struct kprobe *p) 485 { 486 + unsigned long arm_addr; 487 + bundle_t *src, *dest; 488 489 + arm_addr = ((unsigned long)p->addr) & ~0xFUL; 490 + dest = &((kprobe_opcode_t *)arm_addr)->bundle; 491 /* p->ainsn.insn contains the original unaltered kprobe_opcode_t */ 492 + src = &p->ainsn.insn->bundle; 493 + switch (p->ainsn.slot) { 494 + case 0: 495 + dest->quad0.slot0 = src->quad0.slot0; 496 + break; 497 + case 1: 498 + dest->quad1.slot1_p1 = src->quad1.slot1_p1; 499 + break; 500 + case 2: 501 + dest->quad1.slot2 = src->quad1.slot2; 502 + break; 503 + } 504 flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t)); 505 } 506 ··· 807 switch(val) { 808 case DIE_BREAK: 809 /* err is break number from ia64_bad_break() */ 810 + if ((args->err >> 12) == (__IA64_BREAK_KPROBE >> 12) 811 + || args->err == __IA64_BREAK_JPROBE 812 + || args->err == 0) 813 if (pre_kprobes_handler(args)) 814 ret = NOTIFY_STOP; 815 break;
+2 -2
include/asm-ia64/break.h
··· 12 * OS-specific debug break numbers: 13 */ 14 #define __IA64_BREAK_KDB 0x80100 15 - #define __IA64_BREAK_KPROBE 0x80200 16 - #define __IA64_BREAK_JPROBE 0x80300 17 18 /* 19 * OS-specific break numbers:
··· 12 * OS-specific debug break numbers: 13 */ 14 #define __IA64_BREAK_KDB 0x80100 15 + #define __IA64_BREAK_KPROBE 0x81000 /* .. 0x81fff */ 16 + #define __IA64_BREAK_JPROBE 0x82000 17 18 /* 19 * OS-specific break numbers:
+1
include/asm-ia64/kprobes.h
··· 115 #define INST_FLAG_BREAK_INST 4 116 unsigned long inst_flag; 117 unsigned short target_br_reg; 118 }; 119 120 extern int kprobe_exceptions_notify(struct notifier_block *self,
··· 115 #define INST_FLAG_BREAK_INST 4 116 unsigned long inst_flag; 117 unsigned short target_br_reg; 118 + unsigned short slot; 119 }; 120 121 extern int kprobe_exceptions_notify(struct notifier_block *self,