Loading arch/s390/kernel/ftrace.c +49 −46 Original line number Diff line number Diff line Loading @@ -59,62 +59,65 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { struct ftrace_insn insn; unsigned short op; void *from, *to; size_t size; ftrace_generate_nop_insn(&insn); size = sizeof(insn); from = &insn; to = (void *) rec->ip; if (probe_kernel_read(&op, (void *) rec->ip, sizeof(op))) struct ftrace_insn orig, new, old; if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old))) return -EFAULT; if (addr == MCOUNT_ADDR) { /* Initial code replacement; we expect to see stg r14,8(r15) */ orig.opc = 0xe3e0; orig.disp = 0xf0080024; ftrace_generate_nop_insn(&new); } else if (old.opc == BREAKPOINT_INSTRUCTION) { /* * If we find a breakpoint instruction, a kprobe has been placed * at the beginning of the function. We write the constant * KPROBE_ON_FTRACE_NOP into the remaining four bytes of the original * instruction so that the kprobes handler can execute a nop, if it * reaches this breakpoint. * If we find a breakpoint instruction, a kprobe has been * placed at the beginning of the function. We write the * constant KPROBE_ON_FTRACE_NOP into the remaining four * bytes of the original instruction so that the kprobes * handler can execute a nop, if it reaches this breakpoint. */ if (op == BREAKPOINT_INSTRUCTION) { size -= 2; from += 2; to += 2; insn.disp = KPROBE_ON_FTRACE_NOP; new.opc = orig.opc = BREAKPOINT_INSTRUCTION; orig.disp = KPROBE_ON_FTRACE_CALL; new.disp = KPROBE_ON_FTRACE_NOP; } else { /* Replace ftrace call with a nop. */ ftrace_generate_call_insn(&orig, rec->ip); ftrace_generate_nop_insn(&new); } if (probe_kernel_write(to, from, size)) /* Verify that the to be replaced code matches what we expect. */ if (memcmp(&orig, &old, sizeof(old))) return -EINVAL; if (probe_kernel_write((void *) rec->ip, &new, sizeof(new))) return -EPERM; return 0; } int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) { struct ftrace_insn insn; unsigned short op; void *from, *to; size_t size; ftrace_generate_call_insn(&insn, rec->ip); size = sizeof(insn); from = &insn; to = (void *) rec->ip; if (probe_kernel_read(&op, (void *) rec->ip, sizeof(op))) struct ftrace_insn orig, new, old; if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old))) return -EFAULT; if (old.opc == BREAKPOINT_INSTRUCTION) { /* * If we find a breakpoint instruction, a kprobe has been placed * at the beginning of the function. We write the constant * KPROBE_ON_FTRACE_CALL into the remaining four bytes of the original * instruction so that the kprobes handler can execute a brasl if it * reaches this breakpoint. * If we find a breakpoint instruction, a kprobe has been * placed at the beginning of the function. We write the * constant KPROBE_ON_FTRACE_CALL into the remaining four * bytes of the original instruction so that the kprobes * handler can execute a brasl if it reaches this breakpoint. */ if (op == BREAKPOINT_INSTRUCTION) { size -= 2; from += 2; to += 2; insn.disp = KPROBE_ON_FTRACE_CALL; new.opc = orig.opc = BREAKPOINT_INSTRUCTION; orig.disp = KPROBE_ON_FTRACE_NOP; new.disp = KPROBE_ON_FTRACE_CALL; } else { /* Replace nop with an ftrace call. */ ftrace_generate_nop_insn(&orig); ftrace_generate_call_insn(&new, rec->ip); } if (probe_kernel_write(to, from, size)) /* Verify that the to be replaced code matches what we expect. */ if (memcmp(&orig, &old, sizeof(old))) return -EINVAL; if (probe_kernel_write((void *) rec->ip, &new, sizeof(new))) return -EPERM; return 0; } Loading Loading
arch/s390/kernel/ftrace.c +49 −46 Original line number Diff line number Diff line Loading @@ -59,62 +59,65 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { struct ftrace_insn insn; unsigned short op; void *from, *to; size_t size; ftrace_generate_nop_insn(&insn); size = sizeof(insn); from = &insn; to = (void *) rec->ip; if (probe_kernel_read(&op, (void *) rec->ip, sizeof(op))) struct ftrace_insn orig, new, old; if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old))) return -EFAULT; if (addr == MCOUNT_ADDR) { /* Initial code replacement; we expect to see stg r14,8(r15) */ orig.opc = 0xe3e0; orig.disp = 0xf0080024; ftrace_generate_nop_insn(&new); } else if (old.opc == BREAKPOINT_INSTRUCTION) { /* * If we find a breakpoint instruction, a kprobe has been placed * at the beginning of the function. We write the constant * KPROBE_ON_FTRACE_NOP into the remaining four bytes of the original * instruction so that the kprobes handler can execute a nop, if it * reaches this breakpoint. * If we find a breakpoint instruction, a kprobe has been * placed at the beginning of the function. We write the * constant KPROBE_ON_FTRACE_NOP into the remaining four * bytes of the original instruction so that the kprobes * handler can execute a nop, if it reaches this breakpoint. */ if (op == BREAKPOINT_INSTRUCTION) { size -= 2; from += 2; to += 2; insn.disp = KPROBE_ON_FTRACE_NOP; new.opc = orig.opc = BREAKPOINT_INSTRUCTION; orig.disp = KPROBE_ON_FTRACE_CALL; new.disp = KPROBE_ON_FTRACE_NOP; } else { /* Replace ftrace call with a nop. */ ftrace_generate_call_insn(&orig, rec->ip); ftrace_generate_nop_insn(&new); } if (probe_kernel_write(to, from, size)) /* Verify that the to be replaced code matches what we expect. */ if (memcmp(&orig, &old, sizeof(old))) return -EINVAL; if (probe_kernel_write((void *) rec->ip, &new, sizeof(new))) return -EPERM; return 0; } int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) { struct ftrace_insn insn; unsigned short op; void *from, *to; size_t size; ftrace_generate_call_insn(&insn, rec->ip); size = sizeof(insn); from = &insn; to = (void *) rec->ip; if (probe_kernel_read(&op, (void *) rec->ip, sizeof(op))) struct ftrace_insn orig, new, old; if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old))) return -EFAULT; if (old.opc == BREAKPOINT_INSTRUCTION) { /* * If we find a breakpoint instruction, a kprobe has been placed * at the beginning of the function. We write the constant * KPROBE_ON_FTRACE_CALL into the remaining four bytes of the original * instruction so that the kprobes handler can execute a brasl if it * reaches this breakpoint. * If we find a breakpoint instruction, a kprobe has been * placed at the beginning of the function. We write the * constant KPROBE_ON_FTRACE_CALL into the remaining four * bytes of the original instruction so that the kprobes * handler can execute a brasl if it reaches this breakpoint. */ if (op == BREAKPOINT_INSTRUCTION) { size -= 2; from += 2; to += 2; insn.disp = KPROBE_ON_FTRACE_CALL; new.opc = orig.opc = BREAKPOINT_INSTRUCTION; orig.disp = KPROBE_ON_FTRACE_NOP; new.disp = KPROBE_ON_FTRACE_CALL; } else { /* Replace nop with an ftrace call. */ ftrace_generate_nop_insn(&orig); ftrace_generate_call_insn(&new, rec->ip); } if (probe_kernel_write(to, from, size)) /* Verify that the to be replaced code matches what we expect. */ if (memcmp(&orig, &old, sizeof(old))) return -EINVAL; if (probe_kernel_write((void *) rec->ip, &new, sizeof(new))) return -EPERM; return 0; } Loading