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