]> Git Repo - J-linux.git/blob - arch/powerpc/lib/code-patching.c
powerpc/code-patching: Use WARN_ON and fix check in poking_init
[J-linux.git] / arch / powerpc / lib / code-patching.c
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
18 static 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
35 failed:
36         return -EPERM;
37 }
38
39 int 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
45 static DEFINE_PER_CPU(struct vm_struct *, text_poke_area);
46
47 static int map_patch_area(void *addr, unsigned long text_poke_addr);
48 static void unmap_patch_area(unsigned long addr);
49
50 static 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
76 static int text_area_cpu_down(unsigned int cpu)
77 {
78         free_vm_area(this_cpu_read(text_poke_area));
79         return 0;
80 }
81
82 static __ro_after_init DEFINE_STATIC_KEY_FALSE(poking_init_done);
83
84 void __init poking_init(void)
85 {
86         int ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
87                                     "powerpc/text_poke:online",
88                                     text_area_cpu_up,
89                                     text_area_cpu_down);
90
91         /* cpuhp_setup_state returns >= 0 on success */
92         if (WARN_ON(ret < 0))
93                 return;
94
95         static_branch_enable(&poking_init_done);
96 }
97
98 static unsigned long get_patch_pfn(void *addr)
99 {
100         if (IS_ENABLED(CONFIG_MODULES) && is_vmalloc_or_module_addr(addr))
101                 return vmalloc_to_pfn(addr);
102         else
103                 return __pa_symbol(addr) >> PAGE_SHIFT;
104 }
105
106 /*
107  * This can be called for kernel text or a module.
108  */
109 static int map_patch_area(void *addr, unsigned long text_poke_addr)
110 {
111         unsigned long pfn = get_patch_pfn(addr);
112
113         return map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), PAGE_KERNEL);
114 }
115
116 static void unmap_patch_area(unsigned long addr)
117 {
118         pte_t *ptep;
119         pmd_t *pmdp;
120         pud_t *pudp;
121         p4d_t *p4dp;
122         pgd_t *pgdp;
123
124         pgdp = pgd_offset_k(addr);
125         if (WARN_ON(pgd_none(*pgdp)))
126                 return;
127
128         p4dp = p4d_offset(pgdp, addr);
129         if (WARN_ON(p4d_none(*p4dp)))
130                 return;
131
132         pudp = pud_offset(p4dp, addr);
133         if (WARN_ON(pud_none(*pudp)))
134                 return;
135
136         pmdp = pmd_offset(pudp, addr);
137         if (WARN_ON(pmd_none(*pmdp)))
138                 return;
139
140         ptep = pte_offset_kernel(pmdp, addr);
141         if (WARN_ON(pte_none(*ptep)))
142                 return;
143
144         /*
145          * In hash, pte_clear flushes the tlb, in radix, we have to
146          */
147         pte_clear(&init_mm, addr, ptep);
148         flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
149 }
150
151 static int __do_patch_instruction(u32 *addr, ppc_inst_t instr)
152 {
153         int err;
154         u32 *patch_addr;
155         unsigned long text_poke_addr;
156         pte_t *pte;
157         unsigned long pfn = get_patch_pfn(addr);
158
159         text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr & PAGE_MASK;
160         patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr));
161
162         pte = virt_to_kpte(text_poke_addr);
163         __set_pte_at(&init_mm, text_poke_addr, pte, pfn_pte(pfn, PAGE_KERNEL), 0);
164         /* See ptesync comment in radix__set_pte_at() */
165         if (radix_enabled())
166                 asm volatile("ptesync": : :"memory");
167
168         err = __patch_instruction(addr, instr, patch_addr);
169
170         pte_clear(&init_mm, text_poke_addr, pte);
171         flush_tlb_kernel_range(text_poke_addr, text_poke_addr + PAGE_SIZE);
172
173         return err;
174 }
175
176 static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
177 {
178         int err;
179         unsigned long flags;
180
181         /*
182          * During early early boot patch_instruction is called
183          * when text_poke_area is not ready, but we still need
184          * to allow patching. We just do the plain old patching
185          */
186         if (!static_branch_likely(&poking_init_done))
187                 return raw_patch_instruction(addr, instr);
188
189         local_irq_save(flags);
190         err = __do_patch_instruction(addr, instr);
191         local_irq_restore(flags);
192
193         return err;
194 }
195 #else /* !CONFIG_STRICT_KERNEL_RWX */
196
197 static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
198 {
199         return raw_patch_instruction(addr, instr);
200 }
201
202 #endif /* CONFIG_STRICT_KERNEL_RWX */
203
204 __ro_after_init DEFINE_STATIC_KEY_FALSE(init_mem_is_free);
205
206 int patch_instruction(u32 *addr, ppc_inst_t instr)
207 {
208         /* Make sure we aren't patching a freed init section */
209         if (static_branch_likely(&init_mem_is_free) && init_section_contains(addr, 4))
210                 return 0;
211
212         return do_patch_instruction(addr, instr);
213 }
214 NOKPROBE_SYMBOL(patch_instruction);
215
216 int patch_branch(u32 *addr, unsigned long target, int flags)
217 {
218         ppc_inst_t instr;
219
220         if (create_branch(&instr, addr, target, flags))
221                 return -ERANGE;
222
223         return patch_instruction(addr, instr);
224 }
225
226 /*
227  * Helper to check if a given instruction is a conditional branch
228  * Derived from the conditional checks in analyse_instr()
229  */
230 bool is_conditional_branch(ppc_inst_t instr)
231 {
232         unsigned int opcode = ppc_inst_primary_opcode(instr);
233
234         if (opcode == 16)       /* bc, bca, bcl, bcla */
235                 return true;
236         if (opcode == 19) {
237                 switch ((ppc_inst_val(instr) >> 1) & 0x3ff) {
238                 case 16:        /* bclr, bclrl */
239                 case 528:       /* bcctr, bcctrl */
240                 case 560:       /* bctar, bctarl */
241                         return true;
242                 }
243         }
244         return false;
245 }
246 NOKPROBE_SYMBOL(is_conditional_branch);
247
248 int create_cond_branch(ppc_inst_t *instr, const u32 *addr,
249                        unsigned long target, int flags)
250 {
251         long offset;
252
253         offset = target;
254         if (! (flags & BRANCH_ABSOLUTE))
255                 offset = offset - (unsigned long)addr;
256
257         /* Check we can represent the target in the instruction format */
258         if (!is_offset_in_cond_branch_range(offset))
259                 return 1;
260
261         /* Mask out the flags and target, so they don't step on each other. */
262         *instr = ppc_inst(0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC));
263
264         return 0;
265 }
266
267 int instr_is_relative_branch(ppc_inst_t instr)
268 {
269         if (ppc_inst_val(instr) & BRANCH_ABSOLUTE)
270                 return 0;
271
272         return instr_is_branch_iform(instr) || instr_is_branch_bform(instr);
273 }
274
275 int instr_is_relative_link_branch(ppc_inst_t instr)
276 {
277         return instr_is_relative_branch(instr) && (ppc_inst_val(instr) & BRANCH_SET_LINK);
278 }
279
280 static unsigned long branch_iform_target(const u32 *instr)
281 {
282         signed long imm;
283
284         imm = ppc_inst_val(ppc_inst_read(instr)) & 0x3FFFFFC;
285
286         /* If the top bit of the immediate value is set this is negative */
287         if (imm & 0x2000000)
288                 imm -= 0x4000000;
289
290         if ((ppc_inst_val(ppc_inst_read(instr)) & BRANCH_ABSOLUTE) == 0)
291                 imm += (unsigned long)instr;
292
293         return (unsigned long)imm;
294 }
295
296 static unsigned long branch_bform_target(const u32 *instr)
297 {
298         signed long imm;
299
300         imm = ppc_inst_val(ppc_inst_read(instr)) & 0xFFFC;
301
302         /* If the top bit of the immediate value is set this is negative */
303         if (imm & 0x8000)
304                 imm -= 0x10000;
305
306         if ((ppc_inst_val(ppc_inst_read(instr)) & BRANCH_ABSOLUTE) == 0)
307                 imm += (unsigned long)instr;
308
309         return (unsigned long)imm;
310 }
311
312 unsigned long branch_target(const u32 *instr)
313 {
314         if (instr_is_branch_iform(ppc_inst_read(instr)))
315                 return branch_iform_target(instr);
316         else if (instr_is_branch_bform(ppc_inst_read(instr)))
317                 return branch_bform_target(instr);
318
319         return 0;
320 }
321
322 int translate_branch(ppc_inst_t *instr, const u32 *dest, const u32 *src)
323 {
324         unsigned long target;
325         target = branch_target(src);
326
327         if (instr_is_branch_iform(ppc_inst_read(src)))
328                 return create_branch(instr, dest, target,
329                                      ppc_inst_val(ppc_inst_read(src)));
330         else if (instr_is_branch_bform(ppc_inst_read(src)))
331                 return create_cond_branch(instr, dest, target,
332                                           ppc_inst_val(ppc_inst_read(src)));
333
334         return 1;
335 }
This page took 0.048625 seconds and 4 git commands to generate.