mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
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: Jordan Niethe <jniethe5@gmail.com> Reviewed-by: Alistair Popple <alistair@popple.id.au> [mpe: Don't write to *inst on error] Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20200506034050.24806-15-jniethe5@gmail.com
This commit is contained in:
parent
7ba68b2172
commit
95b980a00d
3 changed files with 29 additions and 10 deletions
|
@ -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,
|
||||
struct ppc_inst __user *nip);
|
||||
|
||||
int probe_kernel_read_inst(struct ppc_inst *inst,
|
||||
struct ppc_inst *src);
|
||||
|
||||
#endif /* _ASM_POWERPC_INST_H */
|
||||
|
|
|
@ -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 */
|
||||
if (probe_kernel_read(&replaced, (void *)ip, MCOUNT_INSN_SIZE))
|
||||
if (probe_kernel_read_inst(&replaced, (void *)ip))
|
||||
return -EFAULT;
|
||||
|
||||
/* Make sure it is what we expect it to be */
|
||||
|
@ -130,7 +130,7 @@ __ftrace_make_nop(struct module *mod,
|
|||
struct ppc_inst op, pop;
|
||||
|
||||
/* 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");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ __ftrace_make_nop(struct module *mod,
|
|||
/* When using -mkernel_profile there is no load to jump over */
|
||||
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);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -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
|
||||
* 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");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ static int setup_mcount_compiler_tramp(unsigned long tramp)
|
|||
return -1;
|
||||
|
||||
/* 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");
|
||||
return -1;
|
||||
}
|
||||
|
@ -399,7 +399,7 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)
|
|||
struct ppc_inst op;
|
||||
|
||||
/* 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");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -526,7 +526,10 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
|||
struct module *mod = rec->arch.mod;
|
||||
|
||||
/* 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;
|
||||
|
||||
if (!expected_nop_sequence(ip, op[0], op[1])) {
|
||||
|
@ -589,7 +592,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
|||
unsigned long ip = rec->ip;
|
||||
|
||||
/* read where this goes */
|
||||
if (probe_kernel_read(&op, (void *)ip, MCOUNT_INSN_SIZE))
|
||||
if (probe_kernel_read_inst(&op, (void *)ip))
|
||||
return -EFAULT;
|
||||
|
||||
/* It should be pointing to a nop */
|
||||
|
@ -645,7 +648,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)
|
|||
}
|
||||
|
||||
/* 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);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -723,7 +726,7 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
|
|||
}
|
||||
|
||||
/* 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");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
|
|
@ -18,3 +18,16 @@ int probe_user_read_inst(struct ppc_inst *inst,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue