cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

code-patching.c (7684B)


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