]> git.baikalelectronics.ru Git - kernel.git/commitdiff
powerpc: Do not dereference code as 'struct ppc_inst' (uprobe, code-patching, feature...
authorChristophe Leroy <christophe.leroy@csgroup.eu>
Thu, 20 May 2021 13:50:42 +0000 (13:50 +0000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 16 Jun 2021 13:35:57 +0000 (23:35 +1000)
'struct ppc_inst' is an internal structure to represent an instruction,
it is not directly the representation of that instruction in text code.
It is not meant to map and dereference code.

Dereferencing code directly through 'struct ppc_inst' has two main issues:
- On powerpc, structs are expected to be 8 bytes aligned while code is
spread every 4 byte.
- Should a non prefixed instruction lie at the end of the page and the
following page not be mapped, it would generate a page fault.

In-memory code must be accessed with ppc_inst_read().

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/c9a1201dd0a66b4a0f91f0fb46d9385cbf030feb.1621516826.git.christophe.leroy@csgroup.eu
arch/powerpc/kernel/uprobes.c
arch/powerpc/lib/code-patching.c
arch/powerpc/lib/feature-fixups.c

index 186f69b11e94d2e70518ca9aa761e43aac04a322..46971bb41d057492eb137bd0c9e75645fb5c0399 100644 (file)
@@ -42,7 +42,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe,
                return -EINVAL;
 
        if (cpu_has_feature(CPU_FTR_ARCH_31) &&
-           ppc_inst_prefixed(auprobe->insn) &&
+           ppc_inst_prefixed(ppc_inst_read(&auprobe->insn)) &&
            (addr & 0x3f) == 60) {
                pr_info_ratelimited("Cannot register a uprobe on 64 byte unaligned prefixed instruction\n");
                return -EINVAL;
index 870b30d9be2f85ca00c73fd7baf27804386bae41..0308429b0d1a356f87b0d9b02d850ab6fb68650c 100644 (file)
@@ -329,13 +329,13 @@ static unsigned long branch_iform_target(const struct ppc_inst *instr)
 {
        signed long imm;
 
-       imm = ppc_inst_val(*instr) & 0x3FFFFFC;
+       imm = ppc_inst_val(ppc_inst_read(instr)) & 0x3FFFFFC;
 
        /* If the top bit of the immediate value is set this is negative */
        if (imm & 0x2000000)
                imm -= 0x4000000;
 
-       if ((ppc_inst_val(*instr) & BRANCH_ABSOLUTE) == 0)
+       if ((ppc_inst_val(ppc_inst_read(instr)) & BRANCH_ABSOLUTE) == 0)
                imm += (unsigned long)instr;
 
        return (unsigned long)imm;
@@ -345,13 +345,13 @@ static unsigned long branch_bform_target(const struct ppc_inst *instr)
 {
        signed long imm;
 
-       imm = ppc_inst_val(*instr) & 0xFFFC;
+       imm = ppc_inst_val(ppc_inst_read(instr)) & 0xFFFC;
 
        /* If the top bit of the immediate value is set this is negative */
        if (imm & 0x8000)
                imm -= 0x10000;
 
-       if ((ppc_inst_val(*instr) & BRANCH_ABSOLUTE) == 0)
+       if ((ppc_inst_val(ppc_inst_read(instr)) & BRANCH_ABSOLUTE) == 0)
                imm += (unsigned long)instr;
 
        return (unsigned long)imm;
index 91bd2000d1802229d488563898fe04db258fff5a..5a4bdede11409ed3b3718bd62413c464d6139bec 100644 (file)
@@ -51,7 +51,7 @@ static int patch_alt_instruction(struct ppc_inst *src, struct ppc_inst *dest,
 
        instr = ppc_inst_read(src);
 
-       if (instr_is_relative_branch(*src)) {
+       if (instr_is_relative_branch(ppc_inst_read(src))) {
                struct ppc_inst *target = (struct ppc_inst *)branch_target(src);
 
                /* Branch within the section doesn't need translating */