xref: /linux/arch/powerpc/lib/test-code-patching.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Copyright 2008 Michael Ellerman, IBM Corporation.
4  */
5 
6 #include <linux/vmalloc.h>
7 #include <linux/init.h>
8 
9 #include <asm/text-patching.h>
10 
11 static int __init instr_is_branch_to_addr(const u32 *instr, unsigned long addr)
12 {
13 	if (instr_is_branch_iform(ppc_inst_read(instr)) ||
14 	    instr_is_branch_bform(ppc_inst_read(instr)))
15 		return branch_target(instr) == addr;
16 
17 	return 0;
18 }
19 
20 static void __init test_trampoline(void)
21 {
22 	asm ("nop;nop;\n");
23 }
24 
25 #define check(x)	do {	\
26 	if (!(x))		\
27 		pr_err("code-patching: test failed at line %d\n", __LINE__); \
28 } while (0)
29 
30 static void __init test_branch_iform(void)
31 {
32 	int err;
33 	ppc_inst_t instr;
34 	u32 tmp[2];
35 	u32 *iptr = tmp;
36 	unsigned long addr = (unsigned long)tmp;
37 
38 	/* The simplest case, branch to self, no flags */
39 	check(instr_is_branch_iform(ppc_inst(0x48000000)));
40 	/* All bits of target set, and flags */
41 	check(instr_is_branch_iform(ppc_inst(0x4bffffff)));
42 	/* High bit of opcode set, which is wrong */
43 	check(!instr_is_branch_iform(ppc_inst(0xcbffffff)));
44 	/* Middle bits of opcode set, which is wrong */
45 	check(!instr_is_branch_iform(ppc_inst(0x7bffffff)));
46 
47 	/* Simplest case, branch to self with link */
48 	check(instr_is_branch_iform(ppc_inst(0x48000001)));
49 	/* All bits of targets set */
50 	check(instr_is_branch_iform(ppc_inst(0x4bfffffd)));
51 	/* Some bits of targets set */
52 	check(instr_is_branch_iform(ppc_inst(0x4bff00fd)));
53 	/* Must be a valid branch to start with */
54 	check(!instr_is_branch_iform(ppc_inst(0x7bfffffd)));
55 
56 	/* Absolute branch to 0x100 */
57 	ppc_inst_write(iptr, ppc_inst(0x48000103));
58 	check(instr_is_branch_to_addr(iptr, 0x100));
59 	/* Absolute branch to 0x420fc */
60 	ppc_inst_write(iptr, ppc_inst(0x480420ff));
61 	check(instr_is_branch_to_addr(iptr, 0x420fc));
62 	/* Maximum positive relative branch, + 20MB - 4B */
63 	ppc_inst_write(iptr, ppc_inst(0x49fffffc));
64 	check(instr_is_branch_to_addr(iptr, addr + 0x1FFFFFC));
65 	/* Smallest negative relative branch, - 4B */
66 	ppc_inst_write(iptr, ppc_inst(0x4bfffffc));
67 	check(instr_is_branch_to_addr(iptr, addr - 4));
68 	/* Largest negative relative branch, - 32 MB */
69 	ppc_inst_write(iptr, ppc_inst(0x4a000000));
70 	check(instr_is_branch_to_addr(iptr, addr - 0x2000000));
71 
72 	/* Branch to self, with link */
73 	err = create_branch(&instr, iptr, addr, BRANCH_SET_LINK);
74 	ppc_inst_write(iptr, instr);
75 	check(instr_is_branch_to_addr(iptr, addr));
76 
77 	/* Branch to self - 0x100, with link */
78 	err = create_branch(&instr, iptr, addr - 0x100, BRANCH_SET_LINK);
79 	ppc_inst_write(iptr, instr);
80 	check(instr_is_branch_to_addr(iptr, addr - 0x100));
81 
82 	/* Branch to self + 0x100, no link */
83 	err = create_branch(&instr, iptr, addr + 0x100, 0);
84 	ppc_inst_write(iptr, instr);
85 	check(instr_is_branch_to_addr(iptr, addr + 0x100));
86 
87 	/* Maximum relative negative offset, - 32 MB */
88 	err = create_branch(&instr, iptr, addr - 0x2000000, BRANCH_SET_LINK);
89 	ppc_inst_write(iptr, instr);
90 	check(instr_is_branch_to_addr(iptr, addr - 0x2000000));
91 
92 	/* Out of range relative negative offset, - 32 MB + 4*/
93 	err = create_branch(&instr, iptr, addr - 0x2000004, BRANCH_SET_LINK);
94 	check(err);
95 
96 	/* Out of range relative positive offset, + 32 MB */
97 	err = create_branch(&instr, iptr, addr + 0x2000000, BRANCH_SET_LINK);
98 	check(err);
99 
100 	/* Unaligned target */
101 	err = create_branch(&instr, iptr, addr + 3, BRANCH_SET_LINK);
102 	check(err);
103 
104 	/* Check flags are masked correctly */
105 	err = create_branch(&instr, iptr, addr, 0xFFFFFFFC);
106 	ppc_inst_write(iptr, instr);
107 	check(instr_is_branch_to_addr(iptr, addr));
108 	check(ppc_inst_equal(instr, ppc_inst(0x48000000)));
109 }
110 
111 static void __init test_create_function_call(void)
112 {
113 	u32 *iptr;
114 	unsigned long dest;
115 	ppc_inst_t instr;
116 
117 	/* Check we can create a function call */
118 	iptr = (u32 *)ppc_function_entry(test_trampoline);
119 	dest = ppc_function_entry(test_create_function_call);
120 	create_branch(&instr, iptr, dest, BRANCH_SET_LINK);
121 	patch_instruction(iptr, instr);
122 	check(instr_is_branch_to_addr(iptr, dest));
123 }
124 
125 static void __init test_branch_bform(void)
126 {
127 	int err;
128 	unsigned long addr;
129 	ppc_inst_t instr;
130 	u32 tmp[2];
131 	u32 *iptr = tmp;
132 	unsigned int flags;
133 
134 	addr = (unsigned long)iptr;
135 
136 	/* The simplest case, branch to self, no flags */
137 	check(instr_is_branch_bform(ppc_inst(0x40000000)));
138 	/* All bits of target set, and flags */
139 	check(instr_is_branch_bform(ppc_inst(0x43ffffff)));
140 	/* High bit of opcode set, which is wrong */
141 	check(!instr_is_branch_bform(ppc_inst(0xc3ffffff)));
142 	/* Middle bits of opcode set, which is wrong */
143 	check(!instr_is_branch_bform(ppc_inst(0x7bffffff)));
144 
145 	/* Absolute conditional branch to 0x100 */
146 	ppc_inst_write(iptr, ppc_inst(0x43ff0103));
147 	check(instr_is_branch_to_addr(iptr, 0x100));
148 	/* Absolute conditional branch to 0x20fc */
149 	ppc_inst_write(iptr, ppc_inst(0x43ff20ff));
150 	check(instr_is_branch_to_addr(iptr, 0x20fc));
151 	/* Maximum positive relative conditional branch, + 32 KB - 4B */
152 	ppc_inst_write(iptr, ppc_inst(0x43ff7ffc));
153 	check(instr_is_branch_to_addr(iptr, addr + 0x7FFC));
154 	/* Smallest negative relative conditional branch, - 4B */
155 	ppc_inst_write(iptr, ppc_inst(0x43fffffc));
156 	check(instr_is_branch_to_addr(iptr, addr - 4));
157 	/* Largest negative relative conditional branch, - 32 KB */
158 	ppc_inst_write(iptr, ppc_inst(0x43ff8000));
159 	check(instr_is_branch_to_addr(iptr, addr - 0x8000));
160 
161 	/* All condition code bits set & link */
162 	flags = 0x3ff000 | BRANCH_SET_LINK;
163 
164 	/* Branch to self */
165 	err = create_cond_branch(&instr, iptr, addr, flags);
166 	ppc_inst_write(iptr, instr);
167 	check(instr_is_branch_to_addr(iptr, addr));
168 
169 	/* Branch to self - 0x100 */
170 	err = create_cond_branch(&instr, iptr, addr - 0x100, flags);
171 	ppc_inst_write(iptr, instr);
172 	check(instr_is_branch_to_addr(iptr, addr - 0x100));
173 
174 	/* Branch to self + 0x100 */
175 	err = create_cond_branch(&instr, iptr, addr + 0x100, flags);
176 	ppc_inst_write(iptr, instr);
177 	check(instr_is_branch_to_addr(iptr, addr + 0x100));
178 
179 	/* Maximum relative negative offset, - 32 KB */
180 	err = create_cond_branch(&instr, iptr, addr - 0x8000, flags);
181 	ppc_inst_write(iptr, instr);
182 	check(instr_is_branch_to_addr(iptr, addr - 0x8000));
183 
184 	/* Out of range relative negative offset, - 32 KB + 4*/
185 	err = create_cond_branch(&instr, iptr, addr - 0x8004, flags);
186 	check(err);
187 
188 	/* Out of range relative positive offset, + 32 KB */
189 	err = create_cond_branch(&instr, iptr, addr + 0x8000, flags);
190 	check(err);
191 
192 	/* Unaligned target */
193 	err = create_cond_branch(&instr, iptr, addr + 3, flags);
194 	check(err);
195 
196 	/* Check flags are masked correctly */
197 	err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
198 	ppc_inst_write(iptr, instr);
199 	check(instr_is_branch_to_addr(iptr, addr));
200 	check(ppc_inst_equal(instr, ppc_inst(0x43FF0000)));
201 }
202 
203 static void __init test_translate_branch(void)
204 {
205 	unsigned long addr;
206 	void *p, *q;
207 	ppc_inst_t instr;
208 	void *buf;
209 
210 	buf = vmalloc(PAGE_ALIGN(0x2000000 + 1));
211 	check(buf);
212 	if (!buf)
213 		return;
214 
215 	/* Simple case, branch to self moved a little */
216 	p = buf;
217 	addr = (unsigned long)p;
218 	create_branch(&instr, p, addr, 0);
219 	ppc_inst_write(p, instr);
220 	check(instr_is_branch_to_addr(p, addr));
221 	q = p + 4;
222 	translate_branch(&instr, q, p);
223 	ppc_inst_write(q, instr);
224 	check(instr_is_branch_to_addr(q, addr));
225 
226 	/* Maximum negative case, move b . to addr + 32 MB */
227 	p = buf;
228 	addr = (unsigned long)p;
229 	create_branch(&instr, p, addr, 0);
230 	ppc_inst_write(p, instr);
231 	q = buf + 0x2000000;
232 	translate_branch(&instr, q, p);
233 	ppc_inst_write(q, instr);
234 	check(instr_is_branch_to_addr(p, addr));
235 	check(instr_is_branch_to_addr(q, addr));
236 	check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x4a000000)));
237 
238 	/* Maximum positive case, move x to x - 32 MB + 4 */
239 	p = buf + 0x2000000;
240 	addr = (unsigned long)p;
241 	create_branch(&instr, p, addr, 0);
242 	ppc_inst_write(p, instr);
243 	q = buf + 4;
244 	translate_branch(&instr, q, p);
245 	ppc_inst_write(q, instr);
246 	check(instr_is_branch_to_addr(p, addr));
247 	check(instr_is_branch_to_addr(q, addr));
248 	check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x49fffffc)));
249 
250 	/* Jump to x + 16 MB moved to x + 20 MB */
251 	p = buf;
252 	addr = 0x1000000 + (unsigned long)buf;
253 	create_branch(&instr, p, addr, BRANCH_SET_LINK);
254 	ppc_inst_write(p, instr);
255 	q = buf + 0x1400000;
256 	translate_branch(&instr, q, p);
257 	ppc_inst_write(q, instr);
258 	check(instr_is_branch_to_addr(p, addr));
259 	check(instr_is_branch_to_addr(q, addr));
260 
261 	/* Jump to x + 16 MB moved to x - 16 MB + 4 */
262 	p = buf + 0x1000000;
263 	addr = 0x2000000 + (unsigned long)buf;
264 	create_branch(&instr, p, addr, 0);
265 	ppc_inst_write(p, instr);
266 	q = buf + 4;
267 	translate_branch(&instr, q, p);
268 	ppc_inst_write(q, instr);
269 	check(instr_is_branch_to_addr(p, addr));
270 	check(instr_is_branch_to_addr(q, addr));
271 
272 
273 	/* Conditional branch tests */
274 
275 	/* Simple case, branch to self moved a little */
276 	p = buf;
277 	addr = (unsigned long)p;
278 	create_cond_branch(&instr, p, addr, 0);
279 	ppc_inst_write(p, instr);
280 	check(instr_is_branch_to_addr(p, addr));
281 	q = buf + 4;
282 	translate_branch(&instr, q, p);
283 	ppc_inst_write(q, instr);
284 	check(instr_is_branch_to_addr(q, addr));
285 
286 	/* Maximum negative case, move b . to addr + 32 KB */
287 	p = buf;
288 	addr = (unsigned long)p;
289 	create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
290 	ppc_inst_write(p, instr);
291 	q = buf + 0x8000;
292 	translate_branch(&instr, q, p);
293 	ppc_inst_write(q, instr);
294 	check(instr_is_branch_to_addr(p, addr));
295 	check(instr_is_branch_to_addr(q, addr));
296 	check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff8000)));
297 
298 	/* Maximum positive case, move x to x - 32 KB + 4 */
299 	p = buf + 0x8000;
300 	addr = (unsigned long)p;
301 	create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
302 	ppc_inst_write(p, instr);
303 	q = buf + 4;
304 	translate_branch(&instr, q, p);
305 	ppc_inst_write(q, instr);
306 	check(instr_is_branch_to_addr(p, addr));
307 	check(instr_is_branch_to_addr(q, addr));
308 	check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff7ffc)));
309 
310 	/* Jump to x + 12 KB moved to x + 20 KB */
311 	p = buf;
312 	addr = 0x3000 + (unsigned long)buf;
313 	create_cond_branch(&instr, p, addr, BRANCH_SET_LINK);
314 	ppc_inst_write(p, instr);
315 	q = buf + 0x5000;
316 	translate_branch(&instr, q, p);
317 	ppc_inst_write(q, instr);
318 	check(instr_is_branch_to_addr(p, addr));
319 	check(instr_is_branch_to_addr(q, addr));
320 
321 	/* Jump to x + 8 KB moved to x - 8 KB + 4 */
322 	p = buf + 0x2000;
323 	addr = 0x4000 + (unsigned long)buf;
324 	create_cond_branch(&instr, p, addr, 0);
325 	ppc_inst_write(p, instr);
326 	q = buf + 4;
327 	translate_branch(&instr, q, p);
328 	ppc_inst_write(q, instr);
329 	check(instr_is_branch_to_addr(p, addr));
330 	check(instr_is_branch_to_addr(q, addr));
331 
332 	/* Free the buffer we were using */
333 	vfree(buf);
334 }
335 
336 static void __init test_prefixed_patching(void)
337 {
338 	u32 *iptr = (u32 *)ppc_function_entry(test_trampoline);
339 	u32 expected[2] = {OP_PREFIX << 26, 0};
340 	ppc_inst_t inst = ppc_inst_prefix(OP_PREFIX << 26, 0);
341 
342 	if (!IS_ENABLED(CONFIG_PPC64))
343 		return;
344 
345 	patch_instruction(iptr, inst);
346 
347 	check(!memcmp(iptr, expected, sizeof(expected)));
348 }
349 
350 static void __init test_multi_instruction_patching(void)
351 {
352 	u32 code[32];
353 	void *buf;
354 	u32 *addr32;
355 	u64 *addr64;
356 	ppc_inst_t inst64 = ppc_inst_prefix(OP_PREFIX << 26 | 3UL << 24, PPC_RAW_TRAP());
357 	u32 inst32 = PPC_RAW_NOP();
358 
359 	buf = vzalloc(PAGE_SIZE * 8);
360 	check(buf);
361 	if (!buf)
362 		return;
363 
364 	/* Test single page 32-bit repeated instruction */
365 	addr32 = buf + PAGE_SIZE;
366 	check(!patch_instructions(addr32 + 1, &inst32, 12, true));
367 
368 	check(addr32[0] == 0);
369 	check(addr32[1] == inst32);
370 	check(addr32[2] == inst32);
371 	check(addr32[3] == inst32);
372 	check(addr32[4] == 0);
373 
374 	/* Test single page 64-bit repeated instruction */
375 	if (IS_ENABLED(CONFIG_PPC64)) {
376 		check(ppc_inst_prefixed(inst64));
377 
378 		addr64 = buf + PAGE_SIZE * 2;
379 		ppc_inst_write(code, inst64);
380 		check(!patch_instructions((u32 *)(addr64 + 1), code, 24, true));
381 
382 		check(addr64[0] == 0);
383 		check(ppc_inst_equal(ppc_inst_read((u32 *)&addr64[1]), inst64));
384 		check(ppc_inst_equal(ppc_inst_read((u32 *)&addr64[2]), inst64));
385 		check(ppc_inst_equal(ppc_inst_read((u32 *)&addr64[3]), inst64));
386 		check(addr64[4] == 0);
387 	}
388 
389 	/* Test single page memcpy */
390 	addr32 = buf + PAGE_SIZE * 3;
391 
392 	for (int i = 0; i < ARRAY_SIZE(code); i++)
393 		code[i] = i + 1;
394 
395 	check(!patch_instructions(addr32 + 1, code, sizeof(code), false));
396 
397 	check(addr32[0] == 0);
398 	check(!memcmp(&addr32[1], code, sizeof(code)));
399 	check(addr32[ARRAY_SIZE(code) + 1] == 0);
400 
401 	/* Test multipage 32-bit repeated instruction */
402 	addr32 = buf + PAGE_SIZE * 4 - 8;
403 	check(!patch_instructions(addr32 + 1, &inst32, 12, true));
404 
405 	check(addr32[0] == 0);
406 	check(addr32[1] == inst32);
407 	check(addr32[2] == inst32);
408 	check(addr32[3] == inst32);
409 	check(addr32[4] == 0);
410 
411 	/* Test multipage 64-bit repeated instruction */
412 	if (IS_ENABLED(CONFIG_PPC64)) {
413 		check(ppc_inst_prefixed(inst64));
414 
415 		addr64 = buf + PAGE_SIZE * 5 - 8;
416 		ppc_inst_write(code, inst64);
417 		check(!patch_instructions((u32 *)(addr64 + 1), code, 24, true));
418 
419 		check(addr64[0] == 0);
420 		check(ppc_inst_equal(ppc_inst_read((u32 *)&addr64[1]), inst64));
421 		check(ppc_inst_equal(ppc_inst_read((u32 *)&addr64[2]), inst64));
422 		check(ppc_inst_equal(ppc_inst_read((u32 *)&addr64[3]), inst64));
423 		check(addr64[4] == 0);
424 	}
425 
426 	/* Test multipage memcpy */
427 	addr32 = buf + PAGE_SIZE * 6 - 12;
428 
429 	for (int i = 0; i < ARRAY_SIZE(code); i++)
430 		code[i] = i + 1;
431 
432 	check(!patch_instructions(addr32 + 1, code, sizeof(code), false));
433 
434 	check(addr32[0] == 0);
435 	check(!memcmp(&addr32[1], code, sizeof(code)));
436 	check(addr32[ARRAY_SIZE(code) + 1] == 0);
437 
438 	vfree(buf);
439 }
440 
441 static void __init test_data_patching(void)
442 {
443 	void *buf;
444 	u32 *addr32;
445 
446 	buf = vzalloc(PAGE_SIZE);
447 	check(buf);
448 	if (!buf)
449 		return;
450 
451 	addr32 = buf + 128;
452 
453 	addr32[1] = 0xA0A1A2A3;
454 	addr32[2] = 0xB0B1B2B3;
455 
456 	check(!patch_uint(&addr32[1], 0xC0C1C2C3));
457 
458 	check(addr32[0] == 0);
459 	check(addr32[1] == 0xC0C1C2C3);
460 	check(addr32[2] == 0xB0B1B2B3);
461 	check(addr32[3] == 0);
462 
463 	/* Unaligned patch_ulong() should fail */
464 	if (IS_ENABLED(CONFIG_PPC64))
465 		check(patch_ulong(&addr32[1], 0xD0D1D2D3) == -EINVAL);
466 
467 	check(!patch_ulong(&addr32[2], 0xD0D1D2D3));
468 
469 	check(addr32[0] == 0);
470 	check(addr32[1] == 0xC0C1C2C3);
471 	check(*(unsigned long *)(&addr32[2]) == 0xD0D1D2D3);
472 
473 	if (!IS_ENABLED(CONFIG_PPC64))
474 		check(addr32[3] == 0);
475 
476 	check(addr32[4] == 0);
477 
478 	vfree(buf);
479 }
480 
481 static int __init test_code_patching(void)
482 {
483 	pr_info("Running code patching self-tests ...\n");
484 
485 	test_branch_iform();
486 	test_branch_bform();
487 	test_create_function_call();
488 	test_translate_branch();
489 	test_prefixed_patching();
490 	test_multi_instruction_patching();
491 	test_data_patching();
492 
493 	return 0;
494 }
495 late_initcall(test_code_patching);
496