linux/arch/powerpc/lib/code-patching.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Copyright 2008 Michael Ellerman, IBM Corporation.
   4 */
   5
   6#include <linux/kprobes.h>
   7#include <linux/vmalloc.h>
   8#include <linux/init.h>
   9#include <linux/cpuhotplug.h>
  10#include <linux/uaccess.h>
  11
  12#include <asm/tlbflush.h>
  13#include <asm/page.h>
  14#include <asm/code-patching.h>
  15#include <asm/inst.h>
  16
  17static int __patch_instruction(u32 *exec_addr, ppc_inst_t instr, u32 *patch_addr)
  18{
  19        if (!ppc_inst_prefixed(instr)) {
  20                u32 val = ppc_inst_val(instr);
  21
  22                __put_kernel_nofault(patch_addr, &val, u32, failed);
  23        } else {
  24                u64 val = ppc_inst_as_ulong(instr);
  25
  26                __put_kernel_nofault(patch_addr, &val, u64, failed);
  27        }
  28
  29        asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
  30                                                            "r" (exec_addr));
  31
  32        return 0;
  33
  34failed:
  35        return -EFAULT;
  36}
  37
  38int raw_patch_instruction(u32 *addr, ppc_inst_t instr)
  39{
  40        return __patch_instruction(addr, instr, addr);
  41}
  42
  43#ifdef CONFIG_STRICT_KERNEL_RWX
  44static DEFINE_PER_CPU(struct vm_struct *, text_poke_area);
  45
  46static int map_patch_area(void *addr, unsigned long text_poke_addr);
  47static void unmap_patch_area(unsigned long addr);
  48
  49static int text_area_cpu_up(unsigned int cpu)
  50{
  51        struct vm_struct *area;
  52        unsigned long addr;
  53        int err;
  54
  55        area = get_vm_area(PAGE_SIZE, VM_ALLOC);
  56        if (!area) {
  57                WARN_ONCE(1, "Failed to create text area for cpu %d\n",
  58                        cpu);
  59                return -1;
  60        }
  61
  62        // Map/unmap the area to ensure all page tables are pre-allocated
  63        addr = (unsigned long)area->addr;
  64        err = map_patch_area(empty_zero_page, addr);
  65        if (err)
  66                return err;
  67
  68        unmap_patch_area(addr);
  69
  70        this_cpu_write(text_poke_area, area);
  71
  72        return 0;
  73}
  74
  75static int text_area_cpu_down(unsigned int cpu)
  76{
  77        free_vm_area(this_cpu_read(text_poke_area));
  78        return 0;
  79}
  80
  81/*
  82 * Although BUG_ON() is rude, in this case it should only happen if ENOMEM, and
  83 * we judge it as being preferable to a kernel that will crash later when
  84 * someone tries to use patch_instruction().
  85 */
  86void __init poking_init(void)
  87{
  88        BUG_ON(!cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
  89                "powerpc/text_poke:online", text_area_cpu_up,
  90                text_area_cpu_down));
  91}
  92
  93/*
  94 * This can be called for kernel text or a module.
  95 */
  96static int map_patch_area(void *addr, unsigned long text_poke_addr)
  97{
  98        unsigned long pfn;
  99
 100        if (is_vmalloc_or_module_addr(addr))
 101                pfn = vmalloc_to_pfn(addr);
 102        else
 103                pfn = __pa_symbol(addr) >> PAGE_SHIFT;
 104
 105        return map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), PAGE_KERNEL);
 106}
 107
 108static void unmap_patch_area(unsigned long addr)
 109{
 110        pte_t *ptep;
 111        pmd_t *pmdp;
 112        pud_t *pudp;
 113        p4d_t *p4dp;
 114        pgd_t *pgdp;
 115
 116        pgdp = pgd_offset_k(addr);
 117        if (WARN_ON(pgd_none(*pgdp)))
 118                return;
 119
 120        p4dp = p4d_offset(pgdp, addr);
 121        if (WARN_ON(p4d_none(*p4dp)))
 122                return;
 123
 124        pudp = pud_offset(p4dp, addr);
 125        if (WARN_ON(pud_none(*pudp)))
 126                return;
 127
 128        pmdp = pmd_offset(pudp, addr);
 129        if (WARN_ON(pmd_none(*pmdp)))
 130                return;
 131
 132        ptep = pte_offset_kernel(pmdp, addr);
 133        if (WARN_ON(pte_none(*ptep)))
 134                return;
 135
 136        /*
 137         * In hash, pte_clear flushes the tlb, in radix, we have to
 138         */
 139        pte_clear(&init_mm, addr, ptep);
 140        flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
 141}
 142
 143static int __do_patch_instruction(u32 *addr, ppc_inst_t instr)
 144{
 145        int err;
 146        u32 *patch_addr;
 147        unsigned long text_poke_addr;
 148
 149        text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr;
 150        patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr));
 151
 152        err = map_patch_area(addr, text_poke_addr);
 153        if (err)
 154                return err;
 155
 156        err = __patch_instruction(addr, instr, patch_addr);
 157
 158        unmap_patch_area(text_poke_addr);
 159
 160        return err;
 161}
 162
 163static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
 164{
 165        int err;
 166        unsigned long flags;
 167
 168        /*
 169         * During early early boot patch_instruction is called
 170         * when text_poke_area is not ready, but we still need
 171         * to allow patching. We just do the plain old patching
 172         */
 173        if (!this_cpu_read(text_poke_area))
 174                return raw_patch_instruction(addr, instr);
 175
 176        local_irq_save(flags);
 177        err = __do_patch_instruction(addr, instr);
 178        local_irq_restore(flags);
 179
 180        return err;
 181}
 182#else /* !CONFIG_STRICT_KERNEL_RWX */
 183
 184static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
 185{
 186        return raw_patch_instruction(addr, instr);
 187}
 188
 189#endif /* CONFIG_STRICT_KERNEL_RWX */
 190
 191int patch_instruction(u32 *addr, ppc_inst_t instr)
 192{
 193        /* Make sure we aren't patching a freed init section */
 194        if (system_state >= SYSTEM_FREEING_INITMEM && init_section_contains(addr, 4))
 195                return 0;
 196
 197        return do_patch_instruction(addr, instr);
 198}
 199NOKPROBE_SYMBOL(patch_instruction);
 200
 201int patch_branch(u32 *addr, unsigned long target, int flags)
 202{
 203        ppc_inst_t instr;
 204
 205        if (create_branch(&instr, addr, target, flags))
 206                return -ERANGE;
 207
 208        return patch_instruction(addr, instr);
 209}
 210
 211bool is_offset_in_branch_range(long offset)
 212{
 213        /*
 214         * Powerpc branch instruction is :
 215         *
 216         *  0         6                 30   31
 217         *  +---------+----------------+---+---+
 218         *  | opcode  |     LI         |AA |LK |
 219         *  +---------+----------------+---+---+
 220         *  Where AA = 0 and LK = 0
 221         *
 222         * LI is a signed 24 bits integer. The real branch offset is computed
 223         * by: imm32 = SignExtend(LI:'0b00', 32);
 224         *
 225         * So the maximum forward branch should be:
 226         *   (0x007fffff << 2) = 0x01fffffc =  0x1fffffc
 227         * The maximum backward branch should be:
 228         *   (0xff800000 << 2) = 0xfe000000 = -0x2000000
 229         */
 230        return (offset >= -0x2000000 && offset <= 0x1fffffc && !(offset & 0x3));
 231}
 232
 233bool is_offset_in_cond_branch_range(long offset)
 234{
 235        return offset >= -0x8000 && offset <= 0x7fff && !(offset & 0x3);
 236}
 237
 238/*
 239 * Helper to check if a given instruction is a conditional branch
 240 * Derived from the conditional checks in analyse_instr()
 241 */
 242bool is_conditional_branch(ppc_inst_t instr)
 243{
 244        unsigned int opcode = ppc_inst_primary_opcode(instr);
 245
 246        if (opcode == 16)       /* bc, bca, bcl, bcla */
 247                return true;
 248        if (opcode == 19) {
 249                switch ((ppc_inst_val(instr) >> 1) & 0x3ff) {
 250                case 16:        /* bclr, bclrl */
 251                case 528:       /* bcctr, bcctrl */
 252                case 560:       /* bctar, bctarl */
 253                        return true;
 254                }
 255        }
 256        return false;
 257}
 258NOKPROBE_SYMBOL(is_conditional_branch);
 259
 260int create_branch(ppc_inst_t *instr, const u32 *addr,
 261                  unsigned long target, int flags)
 262{
 263        long offset;
 264
 265        *instr = ppc_inst(0);
 266        offset = target;
 267        if (! (flags & BRANCH_ABSOLUTE))
 268                offset = offset - (unsigned long)addr;
 269
 270        /* Check we can represent the target in the instruction format */
 271        if (!is_offset_in_branch_range(offset))
 272                return 1;
 273
 274        /* Mask out the flags and target, so they don't step on each other. */
 275        *instr = ppc_inst(0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC));
 276
 277        return 0;
 278}
 279
 280int create_cond_branch(ppc_inst_t *instr, const u32 *addr,
 281                       unsigned long target, int flags)
 282{
 283        long offset;
 284
 285        offset = target;
 286        if (! (flags & BRANCH_ABSOLUTE))
 287                offset = offset - (unsigned long)addr;
 288
 289        /* Check we can represent the target in the instruction format */
 290        if (!is_offset_in_cond_branch_range(offset))
 291                return 1;
 292
 293        /* Mask out the flags and target, so they don't step on each other. */
 294        *instr = ppc_inst(0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC));
 295
 296        return 0;
 297}
 298
 299int instr_is_relative_branch(ppc_inst_t instr)
 300{
 301        if (ppc_inst_val(instr) & BRANCH_ABSOLUTE)
 302                return 0;
 303
 304        return instr_is_branch_iform(instr) || instr_is_branch_bform(instr);
 305}
 306
 307int instr_is_relative_link_branch(ppc_inst_t instr)
 308{
 309        return instr_is_relative_branch(instr) && (ppc_inst_val(instr) & BRANCH_SET_LINK);
 310}
 311
 312static unsigned long branch_iform_target(const u32 *instr)
 313{
 314        signed long imm;
 315
 316        imm = ppc_inst_val(ppc_inst_read(instr)) & 0x3FFFFFC;
 317
 318        /* If the top bit of the immediate value is set this is negative */
 319        if (imm & 0x2000000)
 320                imm -= 0x4000000;
 321
 322        if ((ppc_inst_val(ppc_inst_read(instr)) & BRANCH_ABSOLUTE) == 0)
 323                imm += (unsigned long)instr;
 324
 325        return (unsigned long)imm;
 326}
 327
 328static unsigned long branch_bform_target(const u32 *instr)
 329{
 330        signed long imm;
 331
 332        imm = ppc_inst_val(ppc_inst_read(instr)) & 0xFFFC;
 333
 334        /* If the top bit of the immediate value is set this is negative */
 335        if (imm & 0x8000)
 336                imm -= 0x10000;
 337
 338        if ((ppc_inst_val(ppc_inst_read(instr)) & BRANCH_ABSOLUTE) == 0)
 339                imm += (unsigned long)instr;
 340
 341        return (unsigned long)imm;
 342}
 343
 344unsigned long branch_target(const u32 *instr)
 345{
 346        if (instr_is_branch_iform(ppc_inst_read(instr)))
 347                return branch_iform_target(instr);
 348        else if (instr_is_branch_bform(ppc_inst_read(instr)))
 349                return branch_bform_target(instr);
 350
 351        return 0;
 352}
 353
 354int translate_branch(ppc_inst_t *instr, const u32 *dest, const u32 *src)
 355{
 356        unsigned long target;
 357        target = branch_target(src);
 358
 359        if (instr_is_branch_iform(ppc_inst_read(src)))
 360                return create_branch(instr, dest, target,
 361                                     ppc_inst_val(ppc_inst_read(src)));
 362        else if (instr_is_branch_bform(ppc_inst_read(src)))
 363                return create_cond_branch(instr, dest, target,
 364                                          ppc_inst_val(ppc_inst_read(src)));
 365
 366        return 1;
 367}
 368