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