2 * Copyright 2008 Michael Ellerman, IBM Corporation.
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.
10 #include <linux/kernel.h>
11 #include <linux/vmalloc.h>
12 #include <linux/init.h>
15 #include <asm/code-patching.h>
16 #include <linux/uaccess.h>
19 int patch_instruction(unsigned int *addr
, unsigned int instr
)
23 __put_user_size(instr
, addr
, 4, err
);
26 asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr
));
30 int patch_branch(unsigned int *addr
, unsigned long target
, int flags
)
32 return patch_instruction(addr
, create_branch(addr
, target
, flags
));
35 bool is_offset_in_branch_range(long offset
)
38 * Powerpc branch instruction is :
41 * +---------+----------------+---+---+
42 * | opcode | LI |AA |LK |
43 * +---------+----------------+---+---+
44 * Where AA = 0 and LK = 0
46 * LI is a signed 24 bits integer. The real branch offset is computed
47 * by: imm32 = SignExtend(LI:'0b00', 32);
49 * So the maximum forward branch should be:
50 * (0x007fffff << 2) = 0x01fffffc = 0x1fffffc
51 * The maximum backward branch should be:
52 * (0xff800000 << 2) = 0xfe000000 = -0x2000000
54 return (offset
>= -0x2000000 && offset
<= 0x1fffffc && !(offset
& 0x3));
57 unsigned int create_branch(const unsigned int *addr
,
58 unsigned long target
, int flags
)
60 unsigned int instruction
;
64 if (! (flags
& BRANCH_ABSOLUTE
))
65 offset
= offset
- (unsigned long)addr
;
67 /* Check we can represent the target in the instruction format */
68 if (!is_offset_in_branch_range(offset
))
71 /* Mask out the flags and target, so they don't step on each other. */
72 instruction
= 0x48000000 | (flags
& 0x3) | (offset
& 0x03FFFFFC);
77 unsigned int create_cond_branch(const unsigned int *addr
,
78 unsigned long target
, int flags
)
80 unsigned int instruction
;
84 if (! (flags
& BRANCH_ABSOLUTE
))
85 offset
= offset
- (unsigned long)addr
;
87 /* Check we can represent the target in the instruction format */
88 if (offset
< -0x8000 || offset
> 0x7FFF || offset
& 0x3)
91 /* Mask out the flags and target, so they don't step on each other. */
92 instruction
= 0x40000000 | (flags
& 0x3FF0003) | (offset
& 0xFFFC);
97 static unsigned int branch_opcode(unsigned int instr
)
99 return (instr
>> 26) & 0x3F;
102 static int instr_is_branch_iform(unsigned int instr
)
104 return branch_opcode(instr
) == 18;
107 static int instr_is_branch_bform(unsigned int instr
)
109 return branch_opcode(instr
) == 16;
112 int instr_is_relative_branch(unsigned int instr
)
114 if (instr
& BRANCH_ABSOLUTE
)
117 return instr_is_branch_iform(instr
) || instr_is_branch_bform(instr
);
120 static unsigned long branch_iform_target(const unsigned int *instr
)
124 imm
= *instr
& 0x3FFFFFC;
126 /* If the top bit of the immediate value is set this is negative */
130 if ((*instr
& BRANCH_ABSOLUTE
) == 0)
131 imm
+= (unsigned long)instr
;
133 return (unsigned long)imm
;
136 static unsigned long branch_bform_target(const unsigned int *instr
)
140 imm
= *instr
& 0xFFFC;
142 /* If the top bit of the immediate value is set this is negative */
146 if ((*instr
& BRANCH_ABSOLUTE
) == 0)
147 imm
+= (unsigned long)instr
;
149 return (unsigned long)imm
;
152 unsigned long branch_target(const unsigned int *instr
)
154 if (instr_is_branch_iform(*instr
))
155 return branch_iform_target(instr
);
156 else if (instr_is_branch_bform(*instr
))
157 return branch_bform_target(instr
);
162 int instr_is_branch_to_addr(const unsigned int *instr
, unsigned long addr
)
164 if (instr_is_branch_iform(*instr
) || instr_is_branch_bform(*instr
))
165 return branch_target(instr
) == addr
;
170 unsigned int translate_branch(const unsigned int *dest
, const unsigned int *src
)
172 unsigned long target
;
174 target
= branch_target(src
);
176 if (instr_is_branch_iform(*src
))
177 return create_branch(dest
, target
, *src
);
178 else if (instr_is_branch_bform(*src
))
179 return create_cond_branch(dest
, target
, *src
);
184 #ifdef CONFIG_PPC_BOOK3E_64
185 void __patch_exception(int exc
, unsigned long addr
)
187 extern unsigned int interrupt_base_book3e
;
188 unsigned int *ibase
= &interrupt_base_book3e
;
190 /* Our exceptions vectors start with a NOP and -then- a branch
191 * to deal with single stepping from userspace which stops on
192 * the second instruction. Thus we need to patch the second
193 * instruction of the exception, not the first one
196 patch_branch(ibase
+ (exc
/ 4) + 1, addr
, 0);
200 #ifdef CONFIG_CODE_PATCHING_SELFTEST
202 static void __init
test_trampoline(void)
208 if (!(x)) printk("code-patching: test failed at line %d\n", __LINE__);
210 static void __init
test_branch_iform(void)
215 addr
= (unsigned long)&instr
;
217 /* The simplest case, branch to self, no flags */
218 check(instr_is_branch_iform(0x48000000));
219 /* All bits of target set, and flags */
220 check(instr_is_branch_iform(0x4bffffff));
221 /* High bit of opcode set, which is wrong */
222 check(!instr_is_branch_iform(0xcbffffff));
223 /* Middle bits of opcode set, which is wrong */
224 check(!instr_is_branch_iform(0x7bffffff));
226 /* Simplest case, branch to self with link */
227 check(instr_is_branch_iform(0x48000001));
228 /* All bits of targets set */
229 check(instr_is_branch_iform(0x4bfffffd));
230 /* Some bits of targets set */
231 check(instr_is_branch_iform(0x4bff00fd));
232 /* Must be a valid branch to start with */
233 check(!instr_is_branch_iform(0x7bfffffd));
235 /* Absolute branch to 0x100 */
237 check(instr_is_branch_to_addr(&instr
, 0x100));
238 /* Absolute branch to 0x420fc */
240 check(instr_is_branch_to_addr(&instr
, 0x420fc));
241 /* Maximum positive relative branch, + 20MB - 4B */
243 check(instr_is_branch_to_addr(&instr
, addr
+ 0x1FFFFFC));
244 /* Smallest negative relative branch, - 4B */
246 check(instr_is_branch_to_addr(&instr
, addr
- 4));
247 /* Largest negative relative branch, - 32 MB */
249 check(instr_is_branch_to_addr(&instr
, addr
- 0x2000000));
251 /* Branch to self, with link */
252 instr
= create_branch(&instr
, addr
, BRANCH_SET_LINK
);
253 check(instr_is_branch_to_addr(&instr
, addr
));
255 /* Branch to self - 0x100, with link */
256 instr
= create_branch(&instr
, addr
- 0x100, BRANCH_SET_LINK
);
257 check(instr_is_branch_to_addr(&instr
, addr
- 0x100));
259 /* Branch to self + 0x100, no link */
260 instr
= create_branch(&instr
, addr
+ 0x100, 0);
261 check(instr_is_branch_to_addr(&instr
, addr
+ 0x100));
263 /* Maximum relative negative offset, - 32 MB */
264 instr
= create_branch(&instr
, addr
- 0x2000000, BRANCH_SET_LINK
);
265 check(instr_is_branch_to_addr(&instr
, addr
- 0x2000000));
267 /* Out of range relative negative offset, - 32 MB + 4*/
268 instr
= create_branch(&instr
, addr
- 0x2000004, BRANCH_SET_LINK
);
271 /* Out of range relative positive offset, + 32 MB */
272 instr
= create_branch(&instr
, addr
+ 0x2000000, BRANCH_SET_LINK
);
275 /* Unaligned target */
276 instr
= create_branch(&instr
, addr
+ 3, BRANCH_SET_LINK
);
279 /* Check flags are masked correctly */
280 instr
= create_branch(&instr
, addr
, 0xFFFFFFFC);
281 check(instr_is_branch_to_addr(&instr
, addr
));
282 check(instr
== 0x48000000);
285 static void __init
test_create_function_call(void)
290 /* Check we can create a function call */
291 iptr
= (unsigned int *)ppc_function_entry(test_trampoline
);
292 dest
= ppc_function_entry(test_create_function_call
);
293 patch_instruction(iptr
, create_branch(iptr
, dest
, BRANCH_SET_LINK
));
294 check(instr_is_branch_to_addr(iptr
, dest
));
297 static void __init
test_branch_bform(void)
300 unsigned int *iptr
, instr
, flags
;
303 addr
= (unsigned long)iptr
;
305 /* The simplest case, branch to self, no flags */
306 check(instr_is_branch_bform(0x40000000));
307 /* All bits of target set, and flags */
308 check(instr_is_branch_bform(0x43ffffff));
309 /* High bit of opcode set, which is wrong */
310 check(!instr_is_branch_bform(0xc3ffffff));
311 /* Middle bits of opcode set, which is wrong */
312 check(!instr_is_branch_bform(0x7bffffff));
314 /* Absolute conditional branch to 0x100 */
316 check(instr_is_branch_to_addr(&instr
, 0x100));
317 /* Absolute conditional branch to 0x20fc */
319 check(instr_is_branch_to_addr(&instr
, 0x20fc));
320 /* Maximum positive relative conditional branch, + 32 KB - 4B */
322 check(instr_is_branch_to_addr(&instr
, addr
+ 0x7FFC));
323 /* Smallest negative relative conditional branch, - 4B */
325 check(instr_is_branch_to_addr(&instr
, addr
- 4));
326 /* Largest negative relative conditional branch, - 32 KB */
328 check(instr_is_branch_to_addr(&instr
, addr
- 0x8000));
330 /* All condition code bits set & link */
331 flags
= 0x3ff000 | BRANCH_SET_LINK
;
334 instr
= create_cond_branch(iptr
, addr
, flags
);
335 check(instr_is_branch_to_addr(&instr
, addr
));
337 /* Branch to self - 0x100 */
338 instr
= create_cond_branch(iptr
, addr
- 0x100, flags
);
339 check(instr_is_branch_to_addr(&instr
, addr
- 0x100));
341 /* Branch to self + 0x100 */
342 instr
= create_cond_branch(iptr
, addr
+ 0x100, flags
);
343 check(instr_is_branch_to_addr(&instr
, addr
+ 0x100));
345 /* Maximum relative negative offset, - 32 KB */
346 instr
= create_cond_branch(iptr
, addr
- 0x8000, flags
);
347 check(instr_is_branch_to_addr(&instr
, addr
- 0x8000));
349 /* Out of range relative negative offset, - 32 KB + 4*/
350 instr
= create_cond_branch(iptr
, addr
- 0x8004, flags
);
353 /* Out of range relative positive offset, + 32 KB */
354 instr
= create_cond_branch(iptr
, addr
+ 0x8000, flags
);
357 /* Unaligned target */
358 instr
= create_cond_branch(iptr
, addr
+ 3, flags
);
361 /* Check flags are masked correctly */
362 instr
= create_cond_branch(iptr
, addr
, 0xFFFFFFFC);
363 check(instr_is_branch_to_addr(&instr
, addr
));
364 check(instr
== 0x43FF0000);
367 static void __init
test_translate_branch(void)
373 buf
= vmalloc(PAGE_ALIGN(0x2000000 + 1));
378 /* Simple case, branch to self moved a little */
380 addr
= (unsigned long)p
;
381 patch_branch(p
, addr
, 0);
382 check(instr_is_branch_to_addr(p
, addr
));
384 patch_instruction(q
, translate_branch(q
, p
));
385 check(instr_is_branch_to_addr(q
, addr
));
387 /* Maximum negative case, move b . to addr + 32 MB */
389 addr
= (unsigned long)p
;
390 patch_branch(p
, addr
, 0);
392 patch_instruction(q
, translate_branch(q
, p
));
393 check(instr_is_branch_to_addr(p
, addr
));
394 check(instr_is_branch_to_addr(q
, addr
));
395 check(*q
== 0x4a000000);
397 /* Maximum positive case, move x to x - 32 MB + 4 */
399 addr
= (unsigned long)p
;
400 patch_branch(p
, addr
, 0);
402 patch_instruction(q
, translate_branch(q
, p
));
403 check(instr_is_branch_to_addr(p
, addr
));
404 check(instr_is_branch_to_addr(q
, addr
));
405 check(*q
== 0x49fffffc);
407 /* Jump to x + 16 MB moved to x + 20 MB */
409 addr
= 0x1000000 + (unsigned long)buf
;
410 patch_branch(p
, addr
, BRANCH_SET_LINK
);
412 patch_instruction(q
, translate_branch(q
, p
));
413 check(instr_is_branch_to_addr(p
, addr
));
414 check(instr_is_branch_to_addr(q
, addr
));
416 /* Jump to x + 16 MB moved to x - 16 MB + 4 */
418 addr
= 0x2000000 + (unsigned long)buf
;
419 patch_branch(p
, addr
, 0);
421 patch_instruction(q
, translate_branch(q
, p
));
422 check(instr_is_branch_to_addr(p
, addr
));
423 check(instr_is_branch_to_addr(q
, addr
));
426 /* Conditional branch tests */
428 /* Simple case, branch to self moved a little */
430 addr
= (unsigned long)p
;
431 patch_instruction(p
, create_cond_branch(p
, addr
, 0));
432 check(instr_is_branch_to_addr(p
, addr
));
434 patch_instruction(q
, translate_branch(q
, p
));
435 check(instr_is_branch_to_addr(q
, addr
));
437 /* Maximum negative case, move b . to addr + 32 KB */
439 addr
= (unsigned long)p
;
440 patch_instruction(p
, create_cond_branch(p
, addr
, 0xFFFFFFFC));
442 patch_instruction(q
, translate_branch(q
, p
));
443 check(instr_is_branch_to_addr(p
, addr
));
444 check(instr_is_branch_to_addr(q
, addr
));
445 check(*q
== 0x43ff8000);
447 /* Maximum positive case, move x to x - 32 KB + 4 */
449 addr
= (unsigned long)p
;
450 patch_instruction(p
, create_cond_branch(p
, addr
, 0xFFFFFFFC));
452 patch_instruction(q
, translate_branch(q
, p
));
453 check(instr_is_branch_to_addr(p
, addr
));
454 check(instr_is_branch_to_addr(q
, addr
));
455 check(*q
== 0x43ff7ffc);
457 /* Jump to x + 12 KB moved to x + 20 KB */
459 addr
= 0x3000 + (unsigned long)buf
;
460 patch_instruction(p
, create_cond_branch(p
, addr
, BRANCH_SET_LINK
));
462 patch_instruction(q
, translate_branch(q
, p
));
463 check(instr_is_branch_to_addr(p
, addr
));
464 check(instr_is_branch_to_addr(q
, addr
));
466 /* Jump to x + 8 KB moved to x - 8 KB + 4 */
468 addr
= 0x4000 + (unsigned long)buf
;
469 patch_instruction(p
, create_cond_branch(p
, addr
, 0));
471 patch_instruction(q
, translate_branch(q
, p
));
472 check(instr_is_branch_to_addr(p
, addr
));
473 check(instr_is_branch_to_addr(q
, addr
));
475 /* Free the buffer we were using */
479 static int __init
test_code_patching(void)
481 printk(KERN_DEBUG
"Running code patching self-tests ...\n");
485 test_create_function_call();
486 test_translate_branch();
490 late_initcall(test_code_patching
);
492 #endif /* CONFIG_CODE_PATCHING_SELFTEST */