kprobes.c (c39f2d9db0fd81ea20bb5cce9b3f082ca63753e2) | kprobes.c (657480d9c01574d1e11bbb29e725db9907daf782) |
---|---|
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Kernel Probes (KProbes) 4 * 5 * Copyright IBM Corp. 2002, 2006 6 * 7 * s390 port, used ppc64 as template. Mike Grundy <grundym@us.ibm.com> 8 */ --- 42 unchanged lines hidden (view full) --- 51 .alloc = alloc_s390_insn_page, 52 .free = free_s390_insn_page, 53 .pages = LIST_HEAD_INIT(kprobe_s390_insn_slots.pages), 54 .insn_size = MAX_INSN_SIZE, 55}; 56 57static void copy_instruction(struct kprobe *p) 58{ | 1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Kernel Probes (KProbes) 4 * 5 * Copyright IBM Corp. 2002, 2006 6 * 7 * s390 port, used ppc64 as template. Mike Grundy <grundym@us.ibm.com> 8 */ --- 42 unchanged lines hidden (view full) --- 51 .alloc = alloc_s390_insn_page, 52 .free = free_s390_insn_page, 53 .pages = LIST_HEAD_INIT(kprobe_s390_insn_slots.pages), 54 .insn_size = MAX_INSN_SIZE, 55}; 56 57static void copy_instruction(struct kprobe *p) 58{ |
59 unsigned long ip = (unsigned long) p->addr; | |
60 s64 disp, new_disp; 61 u64 addr, new_addr; 62 | 59 s64 disp, new_disp; 60 u64 addr, new_addr; 61 |
63 if (ftrace_location(ip) == ip) { 64 /* 65 * If kprobes patches the instruction that is morphed by 66 * ftrace make sure that kprobes always sees the branch 67 * "jg .+24" that skips the mcount block or the "brcl 0,0" 68 * in case of hotpatch. 69 */ 70 ftrace_generate_nop_insn((struct ftrace_insn *)p->ainsn.insn); 71 p->ainsn.is_ftrace_insn = 1; 72 } else 73 memcpy(p->ainsn.insn, p->addr, insn_length(*p->addr >> 8)); | 62 memcpy(p->ainsn.insn, p->addr, insn_length(*p->addr >> 8)); |
74 p->opcode = p->ainsn.insn[0]; 75 if (!probe_is_insn_relative_long(p->ainsn.insn)) 76 return; 77 /* 78 * For pc-relative instructions in RIL-b or RIL-c format patch the 79 * RI2 displacement field. We have already made sure that the insn 80 * slot for the patched instruction is within the same 2GB area 81 * as the original instruction (either kernel image or module area). --- 49 unchanged lines hidden (view full) --- 131 return -EINVAL; 132 if (s390_get_insn_slot(p)) 133 return -ENOMEM; 134 copy_instruction(p); 135 return 0; 136} 137NOKPROBE_SYMBOL(arch_prepare_kprobe); 138 | 63 p->opcode = p->ainsn.insn[0]; 64 if (!probe_is_insn_relative_long(p->ainsn.insn)) 65 return; 66 /* 67 * For pc-relative instructions in RIL-b or RIL-c format patch the 68 * RI2 displacement field. We have already made sure that the insn 69 * slot for the patched instruction is within the same 2GB area 70 * as the original instruction (either kernel image or module area). --- 49 unchanged lines hidden (view full) --- 120 return -EINVAL; 121 if (s390_get_insn_slot(p)) 122 return -ENOMEM; 123 copy_instruction(p); 124 return 0; 125} 126NOKPROBE_SYMBOL(arch_prepare_kprobe); 127 |
139int arch_check_ftrace_location(struct kprobe *p) 140{ 141 return 0; 142} 143 | |
144struct swap_insn_args { 145 struct kprobe *p; 146 unsigned int arm_kprobe : 1; 147}; 148 149static int swap_instruction(void *data) 150{ 151 struct swap_insn_args *args = data; | 128struct swap_insn_args { 129 struct kprobe *p; 130 unsigned int arm_kprobe : 1; 131}; 132 133static int swap_instruction(void *data) 134{ 135 struct swap_insn_args *args = data; |
152 struct ftrace_insn new_insn, *insn; | |
153 struct kprobe *p = args->p; | 136 struct kprobe *p = args->p; |
154 size_t len; | 137 u16 opc; |
155 | 138 |
156 new_insn.opc = args->arm_kprobe ? BREAKPOINT_INSTRUCTION : p->opcode; 157 len = sizeof(new_insn.opc); 158 if (!p->ainsn.is_ftrace_insn) 159 goto skip_ftrace; 160 len = sizeof(new_insn); 161 insn = (struct ftrace_insn *) p->addr; 162 if (args->arm_kprobe) { 163 if (is_ftrace_nop(insn)) 164 new_insn.disp = KPROBE_ON_FTRACE_NOP; 165 else 166 new_insn.disp = KPROBE_ON_FTRACE_CALL; 167 } else { 168 ftrace_generate_call_insn(&new_insn, (unsigned long)p->addr); 169 if (insn->disp == KPROBE_ON_FTRACE_NOP) 170 ftrace_generate_nop_insn(&new_insn); 171 } 172skip_ftrace: 173 s390_kernel_write(p->addr, &new_insn, len); | 139 opc = args->arm_kprobe ? BREAKPOINT_INSTRUCTION : p->opcode; 140 s390_kernel_write(p->addr, &opc, sizeof(opc)); |
174 return 0; 175} 176NOKPROBE_SYMBOL(swap_instruction); 177 178void arch_arm_kprobe(struct kprobe *p) 179{ 180 struct swap_insn_args args = {.p = p, .arm_kprobe = 1}; 181 --- 277 unchanged lines hidden (view full) --- 459 * copy is p->ainsn.insn. 460 */ 461static void resume_execution(struct kprobe *p, struct pt_regs *regs) 462{ 463 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 464 unsigned long ip = regs->psw.addr; 465 int fixup = probe_get_fixup_type(p->ainsn.insn); 466 | 141 return 0; 142} 143NOKPROBE_SYMBOL(swap_instruction); 144 145void arch_arm_kprobe(struct kprobe *p) 146{ 147 struct swap_insn_args args = {.p = p, .arm_kprobe = 1}; 148 --- 277 unchanged lines hidden (view full) --- 426 * copy is p->ainsn.insn. 427 */ 428static void resume_execution(struct kprobe *p, struct pt_regs *regs) 429{ 430 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 431 unsigned long ip = regs->psw.addr; 432 int fixup = probe_get_fixup_type(p->ainsn.insn); 433 |
467 /* Check if the kprobes location is an enabled ftrace caller */ 468 if (p->ainsn.is_ftrace_insn) { 469 struct ftrace_insn *insn = (struct ftrace_insn *) p->addr; 470 struct ftrace_insn call_insn; 471 472 ftrace_generate_call_insn(&call_insn, (unsigned long) p->addr); 473 /* 474 * A kprobe on an enabled ftrace call site actually single 475 * stepped an unconditional branch (ftrace nop equivalent). 476 * Now we need to fixup things and pretend that a brasl r0,... 477 * was executed instead. 478 */ 479 if (insn->disp == KPROBE_ON_FTRACE_CALL) { 480 ip += call_insn.disp * 2 - MCOUNT_INSN_SIZE; 481 regs->gprs[0] = (unsigned long)p->addr + sizeof(*insn); 482 } 483 } 484 | |
485 if (fixup & FIXUP_PSW_NORMAL) 486 ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn; 487 488 if (fixup & FIXUP_BRANCH_NOT_TAKEN) { 489 int ilen = insn_length(p->ainsn.insn[0] >> 8); 490 if (ip - (unsigned long) p->ainsn.insn == ilen) 491 ip = (unsigned long) p->addr + ilen; 492 } --- 167 unchanged lines hidden --- | 434 if (fixup & FIXUP_PSW_NORMAL) 435 ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn; 436 437 if (fixup & FIXUP_BRANCH_NOT_TAKEN) { 438 int ilen = insn_length(p->ainsn.insn[0] >> 8); 439 if (ip - (unsigned long) p->ainsn.insn == ilen) 440 ip = (unsigned long) p->addr + ilen; 441 } --- 167 unchanged lines hidden --- |