Commit 95b980a0 authored by Jordan Niethe's avatar Jordan Niethe Committed by Michael Ellerman

powerpc: Add a probe_kernel_read_inst() function

Introduce a probe_kernel_read_inst() function to use in cases where
probe_kernel_read() is used for getting an instruction. This will be
more useful for prefixed instructions.
Signed-off-by: default avatarJordan Niethe <jniethe5@gmail.com>
Reviewed-by: default avatarAlistair Popple <alistair@popple.id.au>
[mpe: Don't write to *inst on error]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200506034050.24806-15-jniethe5@gmail.com
parent 7ba68b21
...@@ -40,4 +40,7 @@ static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y) ...@@ -40,4 +40,7 @@ static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
int probe_user_read_inst(struct ppc_inst *inst, int probe_user_read_inst(struct ppc_inst *inst,
struct ppc_inst __user *nip); struct ppc_inst __user *nip);
int probe_kernel_read_inst(struct ppc_inst *inst,
struct ppc_inst *src);
#endif /* _ASM_POWERPC_INST_H */ #endif /* _ASM_POWERPC_INST_H */
...@@ -68,7 +68,7 @@ ftrace_modify_code(unsigned long ip, struct ppc_inst old, struct ppc_inst new) ...@@ -68,7 +68,7 @@ ftrace_modify_code(unsigned long ip, struct ppc_inst old, struct ppc_inst new)
*/ */
/* read the text we want to modify */ /* read the text we want to modify */
if (probe_kernel_read(&replaced, (void *)ip, MCOUNT_INSN_SIZE)) if (probe_kernel_read_inst(&replaced, (void *)ip))
return -EFAULT; return -EFAULT;
/* Make sure it is what we expect it to be */ /* Make sure it is what we expect it to be */
...@@ -130,7 +130,7 @@ __ftrace_make_nop(struct module *mod, ...@@ -130,7 +130,7 @@ __ftrace_make_nop(struct module *mod,
struct ppc_inst op, pop; struct ppc_inst op, pop;
/* read where this goes */ /* read where this goes */
if (probe_kernel_read(&op, (void *)ip, sizeof(int))) { if (probe_kernel_read_inst(&op, (void *)ip)) {
pr_err("Fetching opcode failed.\n"); pr_err("Fetching opcode failed.\n");
return -EFAULT; return -EFAULT;
} }
...@@ -164,7 +164,7 @@ __ftrace_make_nop(struct module *mod, ...@@ -164,7 +164,7 @@ __ftrace_make_nop(struct module *mod,
/* When using -mkernel_profile there is no load to jump over */ /* When using -mkernel_profile there is no load to jump over */
pop = ppc_inst(PPC_INST_NOP); pop = ppc_inst(PPC_INST_NOP);
if (probe_kernel_read(&op, (void *)(ip - 4), 4)) { if (probe_kernel_read_inst(&op, (void *)(ip - 4))) {
pr_err("Fetching instruction at %lx failed.\n", ip - 4); pr_err("Fetching instruction at %lx failed.\n", ip - 4);
return -EFAULT; return -EFAULT;
} }
...@@ -197,7 +197,7 @@ __ftrace_make_nop(struct module *mod, ...@@ -197,7 +197,7 @@ __ftrace_make_nop(struct module *mod,
* Check what is in the next instruction. We can see ld r2,40(r1), but * Check what is in the next instruction. We can see ld r2,40(r1), but
* on first pass after boot we will see mflr r0. * on first pass after boot we will see mflr r0.
*/ */
if (probe_kernel_read(&op, (void *)(ip+4), MCOUNT_INSN_SIZE)) { if (probe_kernel_read_inst(&op, (void *)(ip + 4))) {
pr_err("Fetching op failed.\n"); pr_err("Fetching op failed.\n");
return -EFAULT; return -EFAULT;
} }
...@@ -349,7 +349,7 @@ static int setup_mcount_compiler_tramp(unsigned long tramp) ...@@ -349,7 +349,7 @@ static int setup_mcount_compiler_tramp(unsigned long tramp)
return -1; return -1;
/* New trampoline -- read where this goes */ /* New trampoline -- read where this goes */
if (probe_kernel_read(&op, (void *)tramp, sizeof(int))) { if (probe_kernel_read_inst(&op, (void *)tramp)) {
pr_debug("Fetching opcode failed.\n"); pr_debug("Fetching opcode failed.\n");
return -1; return -1;
} }
...@@ -399,7 +399,7 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr) ...@@ -399,7 +399,7 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)
struct ppc_inst op; struct ppc_inst op;
/* Read where this goes */ /* Read where this goes */
if (probe_kernel_read(&op, (void *)ip, sizeof(int))) { if (probe_kernel_read_inst(&op, (void *)ip)) {
pr_err("Fetching opcode failed.\n"); pr_err("Fetching opcode failed.\n");
return -EFAULT; return -EFAULT;
} }
...@@ -526,7 +526,10 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) ...@@ -526,7 +526,10 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
struct module *mod = rec->arch.mod; struct module *mod = rec->arch.mod;
/* read where this goes */ /* read where this goes */
if (probe_kernel_read(op, ip, sizeof(op))) if (probe_kernel_read_inst(op, ip))
return -EFAULT;
if (probe_kernel_read_inst(op + 1, ip + 4))
return -EFAULT; return -EFAULT;
if (!expected_nop_sequence(ip, op[0], op[1])) { if (!expected_nop_sequence(ip, op[0], op[1])) {
...@@ -589,7 +592,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) ...@@ -589,7 +592,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
unsigned long ip = rec->ip; unsigned long ip = rec->ip;
/* read where this goes */ /* read where this goes */
if (probe_kernel_read(&op, (void *)ip, MCOUNT_INSN_SIZE)) if (probe_kernel_read_inst(&op, (void *)ip))
return -EFAULT; return -EFAULT;
/* It should be pointing to a nop */ /* It should be pointing to a nop */
...@@ -645,7 +648,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr) ...@@ -645,7 +648,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)
} }
/* Make sure we have a nop */ /* Make sure we have a nop */
if (probe_kernel_read(&op, ip, sizeof(op))) { if (probe_kernel_read_inst(&op, ip)) {
pr_err("Unable to read ftrace location %p\n", ip); pr_err("Unable to read ftrace location %p\n", ip);
return -EFAULT; return -EFAULT;
} }
...@@ -723,7 +726,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, ...@@ -723,7 +726,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
} }
/* read where this goes */ /* read where this goes */
if (probe_kernel_read(&op, (void *)ip, sizeof(int))) { if (probe_kernel_read_inst(&op, (void *)ip)) {
pr_err("Fetching opcode failed.\n"); pr_err("Fetching opcode failed.\n");
return -EFAULT; return -EFAULT;
} }
......
...@@ -18,3 +18,16 @@ int probe_user_read_inst(struct ppc_inst *inst, ...@@ -18,3 +18,16 @@ int probe_user_read_inst(struct ppc_inst *inst,
return err; return err;
} }
int probe_kernel_read_inst(struct ppc_inst *inst,
struct ppc_inst *src)
{
unsigned int val;
int err;
err = probe_kernel_read(&val, src, sizeof(val));
if (!err)
*inst = ppc_inst(val);
return err;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment