GNU Linux-libre 4.4.284-gnu1
[releases.git] / arch / powerpc / lib / code-patching.c
1 /*
2  *  Copyright 2008 Michael Ellerman, IBM Corporation.
3  *
4  *  This program is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU General Public License
6  *  as published by the Free Software Foundation; either version
7  *  2 of the License, or (at your option) any later version.
8  */
9
10 #include <linux/kernel.h>
11 #include <linux/vmalloc.h>
12 #include <linux/init.h>
13 #include <linux/mm.h>
14 #include <asm/page.h>
15 #include <asm/code-patching.h>
16 #include <asm/uaccess.h>
17 #include <asm/setup.h>
18 #include <asm/sections.h>
19
20
21 static inline bool is_init(unsigned int *addr)
22 {
23         return addr >= (unsigned int *)__init_begin && addr < (unsigned int *)__init_end;
24 }
25
26 int patch_instruction(unsigned int *addr, unsigned int instr)
27 {
28         int err;
29
30         /* Make sure we aren't patching a freed init section */
31         if (*PTRRELOC(&init_mem_is_free) && is_init(addr)) {
32                 pr_debug("Skipping init section patching addr: 0x%px\n", addr);
33                 return 0;
34         }
35
36         __put_user_size(instr, addr, 4, err);
37         if (err)
38                 return err;
39         asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr));
40         return 0;
41 }
42
43 int patch_branch(unsigned int *addr, unsigned long target, int flags)
44 {
45         return patch_instruction(addr, create_branch(addr, target, flags));
46 }
47
48 int patch_branch_site(s32 *site, unsigned long target, int flags)
49 {
50         unsigned int *addr;
51
52         addr = (unsigned int *)((unsigned long)site + *site);
53         return patch_instruction(addr, create_branch(addr, target, flags));
54 }
55
56 int patch_instruction_site(s32 *site, unsigned int instr)
57 {
58         unsigned int *addr;
59
60         addr = (unsigned int *)((unsigned long)site + *site);
61         return patch_instruction(addr, instr);
62 }
63
64 unsigned int create_branch(const unsigned int *addr,
65                            unsigned long target, int flags)
66 {
67         unsigned int instruction;
68         long offset;
69
70         offset = target;
71         if (! (flags & BRANCH_ABSOLUTE))
72                 offset = offset - (unsigned long)addr;
73
74         /* Check we can represent the target in the instruction format */
75         if (offset < -0x2000000 || offset > 0x1fffffc || offset & 0x3)
76                 return 0;
77
78         /* Mask out the flags and target, so they don't step on each other. */
79         instruction = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
80
81         return instruction;
82 }
83
84 unsigned int create_cond_branch(const unsigned int *addr,
85                                 unsigned long target, int flags)
86 {
87         unsigned int instruction;
88         long offset;
89
90         offset = target;
91         if (! (flags & BRANCH_ABSOLUTE))
92                 offset = offset - (unsigned long)addr;
93
94         /* Check we can represent the target in the instruction format */
95         if (offset < -0x8000 || offset > 0x7FFF || offset & 0x3)
96                 return 0;
97
98         /* Mask out the flags and target, so they don't step on each other. */
99         instruction = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
100
101         return instruction;
102 }
103
104 static unsigned int branch_opcode(unsigned int instr)
105 {
106         return (instr >> 26) & 0x3F;
107 }
108
109 static int instr_is_branch_iform(unsigned int instr)
110 {
111         return branch_opcode(instr) == 18;
112 }
113
114 static int instr_is_branch_bform(unsigned int instr)
115 {
116         return branch_opcode(instr) == 16;
117 }
118
119 int instr_is_relative_branch(unsigned int instr)
120 {
121         if (instr & BRANCH_ABSOLUTE)
122                 return 0;
123
124         return instr_is_branch_iform(instr) || instr_is_branch_bform(instr);
125 }
126
127 static unsigned long branch_iform_target(const unsigned int *instr)
128 {
129         signed long imm;
130
131         imm = *instr & 0x3FFFFFC;
132
133         /* If the top bit of the immediate value is set this is negative */
134         if (imm & 0x2000000)
135                 imm -= 0x4000000;
136
137         if ((*instr & BRANCH_ABSOLUTE) == 0)
138                 imm += (unsigned long)instr;
139
140         return (unsigned long)imm;
141 }
142
143 static unsigned long branch_bform_target(const unsigned int *instr)
144 {
145         signed long imm;
146
147         imm = *instr & 0xFFFC;
148
149         /* If the top bit of the immediate value is set this is negative */
150         if (imm & 0x8000)
151                 imm -= 0x10000;
152
153         if ((*instr & BRANCH_ABSOLUTE) == 0)
154                 imm += (unsigned long)instr;
155
156         return (unsigned long)imm;
157 }
158
159 unsigned long branch_target(const unsigned int *instr)
160 {
161         if (instr_is_branch_iform(*instr))
162                 return branch_iform_target(instr);
163         else if (instr_is_branch_bform(*instr))
164                 return branch_bform_target(instr);
165
166         return 0;
167 }
168
169 int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr)
170 {
171         if (instr_is_branch_iform(*instr) || instr_is_branch_bform(*instr))
172                 return branch_target(instr) == addr;
173
174         return 0;
175 }
176
177 unsigned int translate_branch(const unsigned int *dest, const unsigned int *src)
178 {
179         unsigned long target;
180
181         target = branch_target(src);
182
183         if (instr_is_branch_iform(*src))
184                 return create_branch(dest, target, *src);
185         else if (instr_is_branch_bform(*src))
186                 return create_cond_branch(dest, target, *src);
187
188         return 0;
189 }
190
191 #ifdef CONFIG_PPC_BOOK3E_64
192 void __patch_exception(int exc, unsigned long addr)
193 {
194         extern unsigned int interrupt_base_book3e;
195         unsigned int *ibase = &interrupt_base_book3e;
196
197         /* Our exceptions vectors start with a NOP and -then- a branch
198          * to deal with single stepping from userspace which stops on
199          * the second instruction. Thus we need to patch the second
200          * instruction of the exception, not the first one
201          */
202
203         patch_branch(ibase + (exc / 4) + 1, addr, 0);
204 }
205 #endif
206
207 #ifdef CONFIG_CODE_PATCHING_SELFTEST
208
209 static void __init test_trampoline(void)
210 {
211         asm ("nop;\n");
212 }
213
214 #define check(x)        \
215         if (!(x)) printk("code-patching: test failed at line %d\n", __LINE__);
216
217 static void __init test_branch_iform(void)
218 {
219         unsigned int instr;
220         unsigned long addr;
221
222         addr = (unsigned long)&instr;
223
224         /* The simplest case, branch to self, no flags */
225         check(instr_is_branch_iform(0x48000000));
226         /* All bits of target set, and flags */
227         check(instr_is_branch_iform(0x4bffffff));
228         /* High bit of opcode set, which is wrong */
229         check(!instr_is_branch_iform(0xcbffffff));
230         /* Middle bits of opcode set, which is wrong */
231         check(!instr_is_branch_iform(0x7bffffff));
232
233         /* Simplest case, branch to self with link */
234         check(instr_is_branch_iform(0x48000001));
235         /* All bits of targets set */
236         check(instr_is_branch_iform(0x4bfffffd));
237         /* Some bits of targets set */
238         check(instr_is_branch_iform(0x4bff00fd));
239         /* Must be a valid branch to start with */
240         check(!instr_is_branch_iform(0x7bfffffd));
241
242         /* Absolute branch to 0x100 */
243         instr = 0x48000103;
244         check(instr_is_branch_to_addr(&instr, 0x100));
245         /* Absolute branch to 0x420fc */
246         instr = 0x480420ff;
247         check(instr_is_branch_to_addr(&instr, 0x420fc));
248         /* Maximum positive relative branch, + 20MB - 4B */
249         instr = 0x49fffffc;
250         check(instr_is_branch_to_addr(&instr, addr + 0x1FFFFFC));
251         /* Smallest negative relative branch, - 4B */
252         instr = 0x4bfffffc;
253         check(instr_is_branch_to_addr(&instr, addr - 4));
254         /* Largest negative relative branch, - 32 MB */
255         instr = 0x4a000000;
256         check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
257
258         /* Branch to self, with link */
259         instr = create_branch(&instr, addr, BRANCH_SET_LINK);
260         check(instr_is_branch_to_addr(&instr, addr));
261
262         /* Branch to self - 0x100, with link */
263         instr = create_branch(&instr, addr - 0x100, BRANCH_SET_LINK);
264         check(instr_is_branch_to_addr(&instr, addr - 0x100));
265
266         /* Branch to self + 0x100, no link */
267         instr = create_branch(&instr, addr + 0x100, 0);
268         check(instr_is_branch_to_addr(&instr, addr + 0x100));
269
270         /* Maximum relative negative offset, - 32 MB */
271         instr = create_branch(&instr, addr - 0x2000000, BRANCH_SET_LINK);
272         check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
273
274         /* Out of range relative negative offset, - 32 MB + 4*/
275         instr = create_branch(&instr, addr - 0x2000004, BRANCH_SET_LINK);
276         check(instr == 0);
277
278         /* Out of range relative positive offset, + 32 MB */
279         instr = create_branch(&instr, addr + 0x2000000, BRANCH_SET_LINK);
280         check(instr == 0);
281
282         /* Unaligned target */
283         instr = create_branch(&instr, addr + 3, BRANCH_SET_LINK);
284         check(instr == 0);
285
286         /* Check flags are masked correctly */
287         instr = create_branch(&instr, addr, 0xFFFFFFFC);
288         check(instr_is_branch_to_addr(&instr, addr));
289         check(instr == 0x48000000);
290 }
291
292 static void __init test_create_function_call(void)
293 {
294         unsigned int *iptr;
295         unsigned long dest;
296
297         /* Check we can create a function call */
298         iptr = (unsigned int *)ppc_function_entry(test_trampoline);
299         dest = ppc_function_entry(test_create_function_call);
300         patch_instruction(iptr, create_branch(iptr, dest, BRANCH_SET_LINK));
301         check(instr_is_branch_to_addr(iptr, dest));
302 }
303
304 static void __init test_branch_bform(void)
305 {
306         unsigned long addr;
307         unsigned int *iptr, instr, flags;
308
309         iptr = &instr;
310         addr = (unsigned long)iptr;
311
312         /* The simplest case, branch to self, no flags */
313         check(instr_is_branch_bform(0x40000000));
314         /* All bits of target set, and flags */
315         check(instr_is_branch_bform(0x43ffffff));
316         /* High bit of opcode set, which is wrong */
317         check(!instr_is_branch_bform(0xc3ffffff));
318         /* Middle bits of opcode set, which is wrong */
319         check(!instr_is_branch_bform(0x7bffffff));
320
321         /* Absolute conditional branch to 0x100 */
322         instr = 0x43ff0103;
323         check(instr_is_branch_to_addr(&instr, 0x100));
324         /* Absolute conditional branch to 0x20fc */
325         instr = 0x43ff20ff;
326         check(instr_is_branch_to_addr(&instr, 0x20fc));
327         /* Maximum positive relative conditional branch, + 32 KB - 4B */
328         instr = 0x43ff7ffc;
329         check(instr_is_branch_to_addr(&instr, addr + 0x7FFC));
330         /* Smallest negative relative conditional branch, - 4B */
331         instr = 0x43fffffc;
332         check(instr_is_branch_to_addr(&instr, addr - 4));
333         /* Largest negative relative conditional branch, - 32 KB */
334         instr = 0x43ff8000;
335         check(instr_is_branch_to_addr(&instr, addr - 0x8000));
336
337         /* All condition code bits set & link */
338         flags = 0x3ff000 | BRANCH_SET_LINK;
339
340         /* Branch to self */
341         instr = create_cond_branch(iptr, addr, flags);
342         check(instr_is_branch_to_addr(&instr, addr));
343
344         /* Branch to self - 0x100 */
345         instr = create_cond_branch(iptr, addr - 0x100, flags);
346         check(instr_is_branch_to_addr(&instr, addr - 0x100));
347
348         /* Branch to self + 0x100 */
349         instr = create_cond_branch(iptr, addr + 0x100, flags);
350         check(instr_is_branch_to_addr(&instr, addr + 0x100));
351
352         /* Maximum relative negative offset, - 32 KB */
353         instr = create_cond_branch(iptr, addr - 0x8000, flags);
354         check(instr_is_branch_to_addr(&instr, addr - 0x8000));
355
356         /* Out of range relative negative offset, - 32 KB + 4*/
357         instr = create_cond_branch(iptr, addr - 0x8004, flags);
358         check(instr == 0);
359
360         /* Out of range relative positive offset, + 32 KB */
361         instr = create_cond_branch(iptr, addr + 0x8000, flags);
362         check(instr == 0);
363
364         /* Unaligned target */
365         instr = create_cond_branch(iptr, addr + 3, flags);
366         check(instr == 0);
367
368         /* Check flags are masked correctly */
369         instr = create_cond_branch(iptr, addr, 0xFFFFFFFC);
370         check(instr_is_branch_to_addr(&instr, addr));
371         check(instr == 0x43FF0000);
372 }
373
374 static void __init test_translate_branch(void)
375 {
376         unsigned long addr;
377         unsigned int *p, *q;
378         void *buf;
379
380         buf = vmalloc(PAGE_ALIGN(0x2000000 + 1));
381         check(buf);
382         if (!buf)
383                 return;
384
385         /* Simple case, branch to self moved a little */
386         p = buf;
387         addr = (unsigned long)p;
388         patch_branch(p, addr, 0);
389         check(instr_is_branch_to_addr(p, addr));
390         q = p + 1;
391         patch_instruction(q, translate_branch(q, p));
392         check(instr_is_branch_to_addr(q, addr));
393
394         /* Maximum negative case, move b . to addr + 32 MB */
395         p = buf;
396         addr = (unsigned long)p;
397         patch_branch(p, addr, 0);
398         q = buf + 0x2000000;
399         patch_instruction(q, translate_branch(q, p));
400         check(instr_is_branch_to_addr(p, addr));
401         check(instr_is_branch_to_addr(q, addr));
402         check(*q == 0x4a000000);
403
404         /* Maximum positive case, move x to x - 32 MB + 4 */
405         p = buf + 0x2000000;
406         addr = (unsigned long)p;
407         patch_branch(p, addr, 0);
408         q = buf + 4;
409         patch_instruction(q, translate_branch(q, p));
410         check(instr_is_branch_to_addr(p, addr));
411         check(instr_is_branch_to_addr(q, addr));
412         check(*q == 0x49fffffc);
413
414         /* Jump to x + 16 MB moved to x + 20 MB */
415         p = buf;
416         addr = 0x1000000 + (unsigned long)buf;
417         patch_branch(p, addr, BRANCH_SET_LINK);
418         q = buf + 0x1400000;
419         patch_instruction(q, translate_branch(q, p));
420         check(instr_is_branch_to_addr(p, addr));
421         check(instr_is_branch_to_addr(q, addr));
422
423         /* Jump to x + 16 MB moved to x - 16 MB + 4 */
424         p = buf + 0x1000000;
425         addr = 0x2000000 + (unsigned long)buf;
426         patch_branch(p, addr, 0);
427         q = buf + 4;
428         patch_instruction(q, translate_branch(q, p));
429         check(instr_is_branch_to_addr(p, addr));
430         check(instr_is_branch_to_addr(q, addr));
431
432
433         /* Conditional branch tests */
434
435         /* Simple case, branch to self moved a little */
436         p = buf;
437         addr = (unsigned long)p;
438         patch_instruction(p, create_cond_branch(p, addr, 0));
439         check(instr_is_branch_to_addr(p, addr));
440         q = p + 1;
441         patch_instruction(q, translate_branch(q, p));
442         check(instr_is_branch_to_addr(q, addr));
443
444         /* Maximum negative case, move b . to addr + 32 KB */
445         p = buf;
446         addr = (unsigned long)p;
447         patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC));
448         q = buf + 0x8000;
449         patch_instruction(q, translate_branch(q, p));
450         check(instr_is_branch_to_addr(p, addr));
451         check(instr_is_branch_to_addr(q, addr));
452         check(*q == 0x43ff8000);
453
454         /* Maximum positive case, move x to x - 32 KB + 4 */
455         p = buf + 0x8000;
456         addr = (unsigned long)p;
457         patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC));
458         q = buf + 4;
459         patch_instruction(q, translate_branch(q, p));
460         check(instr_is_branch_to_addr(p, addr));
461         check(instr_is_branch_to_addr(q, addr));
462         check(*q == 0x43ff7ffc);
463
464         /* Jump to x + 12 KB moved to x + 20 KB */
465         p = buf;
466         addr = 0x3000 + (unsigned long)buf;
467         patch_instruction(p, create_cond_branch(p, addr, BRANCH_SET_LINK));
468         q = buf + 0x5000;
469         patch_instruction(q, translate_branch(q, p));
470         check(instr_is_branch_to_addr(p, addr));
471         check(instr_is_branch_to_addr(q, addr));
472
473         /* Jump to x + 8 KB moved to x - 8 KB + 4 */
474         p = buf + 0x2000;
475         addr = 0x4000 + (unsigned long)buf;
476         patch_instruction(p, create_cond_branch(p, addr, 0));
477         q = buf + 4;
478         patch_instruction(q, translate_branch(q, p));
479         check(instr_is_branch_to_addr(p, addr));
480         check(instr_is_branch_to_addr(q, addr));
481
482         /* Free the buffer we were using */
483         vfree(buf);
484 }
485
486 static int __init test_code_patching(void)
487 {
488         printk(KERN_DEBUG "Running code patching self-tests ...\n");
489
490         test_branch_iform();
491         test_branch_bform();
492         test_create_function_call();
493         test_translate_branch();
494
495         return 0;
496 }
497 late_initcall(test_code_patching);
498
499 #endif /* CONFIG_CODE_PATCHING_SELFTEST */