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.

Reviewed-by: Alistair Popple <alist...@popple.id.au>
Signed-off-by: Jordan Niethe <jniet...@gmail.com>
---
v6: - This was previously just in ftrace.c
---
 arch/powerpc/include/asm/inst.h    |  2 ++
 arch/powerpc/kernel/trace/ftrace.c | 23 +++++++++++++----------
 arch/powerpc/lib/inst.c            | 11 +++++++++++
 3 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 3e9a58420151..0d581b332c20 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -39,5 +39,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 *nip);
+int probe_kernel_read_inst(struct ppc_inst *inst,
+                          struct ppc_inst *src);
 
 #endif /* _ASM_INST_H */
diff --git a/arch/powerpc/kernel/trace/ftrace.c 
b/arch/powerpc/kernel/trace/ftrace.c
index acd5b889815f..5e399628f51a 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -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;
        }
diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c
index eaf786afad2b..08dedd927268 100644
--- a/arch/powerpc/lib/inst.c
+++ b/arch/powerpc/lib/inst.c
@@ -16,3 +16,14 @@ int probe_user_read_inst(struct ppc_inst *inst,
        *inst = ppc_inst(val);
        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));
+       *inst = ppc_inst(val);
+       return err;
+}
-- 
2.17.1

Reply via email to