hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
kernel/arch/powerpc/lib/code-patching.c
....@@ -1,10 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * 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.
84 */
95
106 #include <linux/kernel.h>
....@@ -15,30 +11,31 @@
1511 #include <linux/cpuhotplug.h>
1612 #include <linux/slab.h>
1713 #include <linux/uaccess.h>
18
-#include <linux/kprobes.h>
1914
20
-#include <asm/pgtable.h>
2115 #include <asm/tlbflush.h>
2216 #include <asm/page.h>
2317 #include <asm/code-patching.h>
2418 #include <asm/setup.h>
19
+#include <asm/inst.h>
2520
26
-static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
27
- unsigned int *patch_addr)
21
+static int __patch_instruction(struct ppc_inst *exec_addr, struct ppc_inst instr,
22
+ struct ppc_inst *patch_addr)
2823 {
29
- int err;
30
-
31
- __put_user_size(instr, patch_addr, 4, err);
32
- if (err)
33
- return err;
24
+ if (!ppc_inst_prefixed(instr))
25
+ __put_user_asm_goto(ppc_inst_val(instr), patch_addr, failed, "stw");
26
+ else
27
+ __put_user_asm_goto(ppc_inst_as_u64(instr), patch_addr, failed, "std");
3428
3529 asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
3630 "r" (exec_addr));
3731
3832 return 0;
33
+
34
+failed:
35
+ return -EFAULT;
3936 }
4037
41
-int raw_patch_instruction(unsigned int *addr, unsigned int instr)
38
+int raw_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr)
4239 {
4340 return __patch_instruction(addr, instr, addr);
4441 }
....@@ -93,13 +90,12 @@
9390 unsigned long pfn;
9491 int err;
9592
96
- if (is_vmalloc_addr(addr))
93
+ if (is_vmalloc_or_module_addr(addr))
9794 pfn = vmalloc_to_pfn(addr);
9895 else
9996 pfn = __pa_symbol(addr) >> PAGE_SHIFT;
10097
101
- err = map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT),
102
- pgprot_val(PAGE_KERNEL));
98
+ err = map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), PAGE_KERNEL);
10399
104100 pr_devel("Mapped addr %lx with pfn %lx:%d\n", text_poke_addr, pfn, err);
105101 if (err)
....@@ -113,13 +109,18 @@
113109 pte_t *ptep;
114110 pmd_t *pmdp;
115111 pud_t *pudp;
112
+ p4d_t *p4dp;
116113 pgd_t *pgdp;
117114
118115 pgdp = pgd_offset_k(addr);
119116 if (unlikely(!pgdp))
120117 return -EINVAL;
121118
122
- pudp = pud_offset(pgdp, addr);
119
+ p4dp = p4d_offset(pgdp, addr);
120
+ if (unlikely(!p4dp))
121
+ return -EINVAL;
122
+
123
+ pudp = pud_offset(p4dp, addr);
123124 if (unlikely(!pudp))
124125 return -EINVAL;
125126
....@@ -142,10 +143,10 @@
142143 return 0;
143144 }
144145
145
-static int do_patch_instruction(unsigned int *addr, unsigned int instr)
146
+static int do_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr)
146147 {
147148 int err;
148
- unsigned int *patch_addr = NULL;
149
+ struct ppc_inst *patch_addr = NULL;
149150 unsigned long flags;
150151 unsigned long text_poke_addr;
151152 unsigned long kaddr = (unsigned long)addr;
....@@ -166,8 +167,7 @@
166167 goto out;
167168 }
168169
169
- patch_addr = (unsigned int *)(text_poke_addr) +
170
- ((kaddr & ~PAGE_MASK) / sizeof(unsigned int));
170
+ patch_addr = (struct ppc_inst *)(text_poke_addr + (kaddr & ~PAGE_MASK));
171171
172172 __patch_instruction(addr, instr, patch_addr);
173173
....@@ -182,14 +182,14 @@
182182 }
183183 #else /* !CONFIG_STRICT_KERNEL_RWX */
184184
185
-static int do_patch_instruction(unsigned int *addr, unsigned int instr)
185
+static int do_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr)
186186 {
187187 return raw_patch_instruction(addr, instr);
188188 }
189189
190190 #endif /* CONFIG_STRICT_KERNEL_RWX */
191191
192
-int patch_instruction(unsigned int *addr, unsigned int instr)
192
+int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr)
193193 {
194194 /* Make sure we aren't patching a freed init section */
195195 if (init_mem_is_free && init_section_contains(addr, 4)) {
....@@ -200,24 +200,11 @@
200200 }
201201 NOKPROBE_SYMBOL(patch_instruction);
202202
203
-int patch_branch(unsigned int *addr, unsigned long target, int flags)
203
+int patch_branch(struct ppc_inst *addr, unsigned long target, int flags)
204204 {
205
- return patch_instruction(addr, create_branch(addr, target, flags));
206
-}
205
+ struct ppc_inst instr;
207206
208
-int patch_branch_site(s32 *site, unsigned long target, int flags)
209
-{
210
- unsigned int *addr;
211
-
212
- addr = (unsigned int *)((unsigned long)site + *site);
213
- return patch_instruction(addr, create_branch(addr, target, flags));
214
-}
215
-
216
-int patch_instruction_site(s32 *site, unsigned int instr)
217
-{
218
- unsigned int *addr;
219
-
220
- addr = (unsigned int *)((unsigned long)site + *site);
207
+ create_branch(&instr, addr, target, flags);
221208 return patch_instruction(addr, instr);
222209 }
223210
....@@ -252,14 +239,14 @@
252239 * Helper to check if a given instruction is a conditional branch
253240 * Derived from the conditional checks in analyse_instr()
254241 */
255
-bool is_conditional_branch(unsigned int instr)
242
+bool is_conditional_branch(struct ppc_inst instr)
256243 {
257
- unsigned int opcode = instr >> 26;
244
+ unsigned int opcode = ppc_inst_primary_opcode(instr);
258245
259246 if (opcode == 16) /* bc, bca, bcl, bcla */
260247 return true;
261248 if (opcode == 19) {
262
- switch ((instr >> 1) & 0x3ff) {
249
+ switch ((ppc_inst_val(instr) >> 1) & 0x3ff) {
263250 case 16: /* bclr, bclrl */
264251 case 528: /* bcctr, bcctrl */
265252 case 560: /* bctar, bctarl */
....@@ -270,30 +257,30 @@
270257 }
271258 NOKPROBE_SYMBOL(is_conditional_branch);
272259
273
-unsigned int create_branch(const unsigned int *addr,
274
- unsigned long target, int flags)
260
+int create_branch(struct ppc_inst *instr,
261
+ const struct ppc_inst *addr,
262
+ unsigned long target, int flags)
275263 {
276
- unsigned int instruction;
277264 long offset;
278265
266
+ *instr = ppc_inst(0);
279267 offset = target;
280268 if (! (flags & BRANCH_ABSOLUTE))
281269 offset = offset - (unsigned long)addr;
282270
283271 /* Check we can represent the target in the instruction format */
284272 if (!is_offset_in_branch_range(offset))
285
- return 0;
273
+ return 1;
286274
287275 /* Mask out the flags and target, so they don't step on each other. */
288
- instruction = 0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC);
276
+ *instr = ppc_inst(0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC));
289277
290
- return instruction;
278
+ return 0;
291279 }
292280
293
-unsigned int create_cond_branch(const unsigned int *addr,
294
- unsigned long target, int flags)
281
+int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
282
+ unsigned long target, int flags)
295283 {
296
- unsigned int instruction;
297284 long offset;
298285
299286 offset = target;
....@@ -302,104 +289,107 @@
302289
303290 /* Check we can represent the target in the instruction format */
304291 if (!is_offset_in_cond_branch_range(offset))
305
- return 0;
292
+ return 1;
306293
307294 /* Mask out the flags and target, so they don't step on each other. */
308
- instruction = 0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC);
295
+ *instr = ppc_inst(0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC));
309296
310
- return instruction;
297
+ return 0;
311298 }
312299
313
-static unsigned int branch_opcode(unsigned int instr)
300
+static unsigned int branch_opcode(struct ppc_inst instr)
314301 {
315
- return (instr >> 26) & 0x3F;
302
+ return ppc_inst_primary_opcode(instr) & 0x3F;
316303 }
317304
318
-static int instr_is_branch_iform(unsigned int instr)
305
+static int instr_is_branch_iform(struct ppc_inst instr)
319306 {
320307 return branch_opcode(instr) == 18;
321308 }
322309
323
-static int instr_is_branch_bform(unsigned int instr)
310
+static int instr_is_branch_bform(struct ppc_inst instr)
324311 {
325312 return branch_opcode(instr) == 16;
326313 }
327314
328
-int instr_is_relative_branch(unsigned int instr)
315
+int instr_is_relative_branch(struct ppc_inst instr)
329316 {
330
- if (instr & BRANCH_ABSOLUTE)
317
+ if (ppc_inst_val(instr) & BRANCH_ABSOLUTE)
331318 return 0;
332319
333320 return instr_is_branch_iform(instr) || instr_is_branch_bform(instr);
334321 }
335322
336
-int instr_is_relative_link_branch(unsigned int instr)
323
+int instr_is_relative_link_branch(struct ppc_inst instr)
337324 {
338
- return instr_is_relative_branch(instr) && (instr & BRANCH_SET_LINK);
325
+ return instr_is_relative_branch(instr) && (ppc_inst_val(instr) & BRANCH_SET_LINK);
339326 }
340327
341
-static unsigned long branch_iform_target(const unsigned int *instr)
328
+static unsigned long branch_iform_target(const struct ppc_inst *instr)
342329 {
343330 signed long imm;
344331
345
- imm = *instr & 0x3FFFFFC;
332
+ imm = ppc_inst_val(*instr) & 0x3FFFFFC;
346333
347334 /* If the top bit of the immediate value is set this is negative */
348335 if (imm & 0x2000000)
349336 imm -= 0x4000000;
350337
351
- if ((*instr & BRANCH_ABSOLUTE) == 0)
338
+ if ((ppc_inst_val(*instr) & BRANCH_ABSOLUTE) == 0)
352339 imm += (unsigned long)instr;
353340
354341 return (unsigned long)imm;
355342 }
356343
357
-static unsigned long branch_bform_target(const unsigned int *instr)
344
+static unsigned long branch_bform_target(const struct ppc_inst *instr)
358345 {
359346 signed long imm;
360347
361
- imm = *instr & 0xFFFC;
348
+ imm = ppc_inst_val(*instr) & 0xFFFC;
362349
363350 /* If the top bit of the immediate value is set this is negative */
364351 if (imm & 0x8000)
365352 imm -= 0x10000;
366353
367
- if ((*instr & BRANCH_ABSOLUTE) == 0)
354
+ if ((ppc_inst_val(*instr) & BRANCH_ABSOLUTE) == 0)
368355 imm += (unsigned long)instr;
369356
370357 return (unsigned long)imm;
371358 }
372359
373
-unsigned long branch_target(const unsigned int *instr)
360
+unsigned long branch_target(const struct ppc_inst *instr)
374361 {
375
- if (instr_is_branch_iform(*instr))
362
+ if (instr_is_branch_iform(ppc_inst_read(instr)))
376363 return branch_iform_target(instr);
377
- else if (instr_is_branch_bform(*instr))
364
+ else if (instr_is_branch_bform(ppc_inst_read(instr)))
378365 return branch_bform_target(instr);
379366
380367 return 0;
381368 }
382369
383
-int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr)
370
+int instr_is_branch_to_addr(const struct ppc_inst *instr, unsigned long addr)
384371 {
385
- if (instr_is_branch_iform(*instr) || instr_is_branch_bform(*instr))
372
+ if (instr_is_branch_iform(ppc_inst_read(instr)) ||
373
+ instr_is_branch_bform(ppc_inst_read(instr)))
386374 return branch_target(instr) == addr;
387375
388376 return 0;
389377 }
390378
391
-unsigned int translate_branch(const unsigned int *dest, const unsigned int *src)
379
+int translate_branch(struct ppc_inst *instr, const struct ppc_inst *dest,
380
+ const struct ppc_inst *src)
392381 {
393382 unsigned long target;
394
-
395383 target = branch_target(src);
396384
397
- if (instr_is_branch_iform(*src))
398
- return create_branch(dest, target, *src);
399
- else if (instr_is_branch_bform(*src))
400
- return create_cond_branch(dest, target, *src);
385
+ if (instr_is_branch_iform(ppc_inst_read(src)))
386
+ return create_branch(instr, dest, target,
387
+ ppc_inst_val(ppc_inst_read(src)));
388
+ else if (instr_is_branch_bform(ppc_inst_read(src)))
389
+ return create_cond_branch(instr, dest, target,
390
+ ppc_inst_val(ppc_inst_read(src)));
401391
402
- return 0;
392
+ return 1;
403393 }
404394
405395 #ifdef CONFIG_PPC_BOOK3E_64
....@@ -414,7 +404,7 @@
414404 * instruction of the exception, not the first one
415405 */
416406
417
- patch_branch(ibase + (exc / 4) + 1, addr, 0);
407
+ patch_branch((struct ppc_inst *)(ibase + (exc / 4) + 1), addr, 0);
418408 }
419409 #endif
420410
....@@ -430,165 +420,171 @@
430420
431421 static void __init test_branch_iform(void)
432422 {
433
- unsigned int instr;
423
+ int err;
424
+ struct ppc_inst instr;
434425 unsigned long addr;
435426
436427 addr = (unsigned long)&instr;
437428
438429 /* The simplest case, branch to self, no flags */
439
- check(instr_is_branch_iform(0x48000000));
430
+ check(instr_is_branch_iform(ppc_inst(0x48000000)));
440431 /* All bits of target set, and flags */
441
- check(instr_is_branch_iform(0x4bffffff));
432
+ check(instr_is_branch_iform(ppc_inst(0x4bffffff)));
442433 /* High bit of opcode set, which is wrong */
443
- check(!instr_is_branch_iform(0xcbffffff));
434
+ check(!instr_is_branch_iform(ppc_inst(0xcbffffff)));
444435 /* Middle bits of opcode set, which is wrong */
445
- check(!instr_is_branch_iform(0x7bffffff));
436
+ check(!instr_is_branch_iform(ppc_inst(0x7bffffff)));
446437
447438 /* Simplest case, branch to self with link */
448
- check(instr_is_branch_iform(0x48000001));
439
+ check(instr_is_branch_iform(ppc_inst(0x48000001)));
449440 /* All bits of targets set */
450
- check(instr_is_branch_iform(0x4bfffffd));
441
+ check(instr_is_branch_iform(ppc_inst(0x4bfffffd)));
451442 /* Some bits of targets set */
452
- check(instr_is_branch_iform(0x4bff00fd));
443
+ check(instr_is_branch_iform(ppc_inst(0x4bff00fd)));
453444 /* Must be a valid branch to start with */
454
- check(!instr_is_branch_iform(0x7bfffffd));
445
+ check(!instr_is_branch_iform(ppc_inst(0x7bfffffd)));
455446
456447 /* Absolute branch to 0x100 */
457
- instr = 0x48000103;
448
+ instr = ppc_inst(0x48000103);
458449 check(instr_is_branch_to_addr(&instr, 0x100));
459450 /* Absolute branch to 0x420fc */
460
- instr = 0x480420ff;
451
+ instr = ppc_inst(0x480420ff);
461452 check(instr_is_branch_to_addr(&instr, 0x420fc));
462453 /* Maximum positive relative branch, + 20MB - 4B */
463
- instr = 0x49fffffc;
454
+ instr = ppc_inst(0x49fffffc);
464455 check(instr_is_branch_to_addr(&instr, addr + 0x1FFFFFC));
465456 /* Smallest negative relative branch, - 4B */
466
- instr = 0x4bfffffc;
457
+ instr = ppc_inst(0x4bfffffc);
467458 check(instr_is_branch_to_addr(&instr, addr - 4));
468459 /* Largest negative relative branch, - 32 MB */
469
- instr = 0x4a000000;
460
+ instr = ppc_inst(0x4a000000);
470461 check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
471462
472463 /* Branch to self, with link */
473
- instr = create_branch(&instr, addr, BRANCH_SET_LINK);
464
+ err = create_branch(&instr, &instr, addr, BRANCH_SET_LINK);
474465 check(instr_is_branch_to_addr(&instr, addr));
475466
476467 /* Branch to self - 0x100, with link */
477
- instr = create_branch(&instr, addr - 0x100, BRANCH_SET_LINK);
468
+ err = create_branch(&instr, &instr, addr - 0x100, BRANCH_SET_LINK);
478469 check(instr_is_branch_to_addr(&instr, addr - 0x100));
479470
480471 /* Branch to self + 0x100, no link */
481
- instr = create_branch(&instr, addr + 0x100, 0);
472
+ err = create_branch(&instr, &instr, addr + 0x100, 0);
482473 check(instr_is_branch_to_addr(&instr, addr + 0x100));
483474
484475 /* Maximum relative negative offset, - 32 MB */
485
- instr = create_branch(&instr, addr - 0x2000000, BRANCH_SET_LINK);
476
+ err = create_branch(&instr, &instr, addr - 0x2000000, BRANCH_SET_LINK);
486477 check(instr_is_branch_to_addr(&instr, addr - 0x2000000));
487478
488479 /* Out of range relative negative offset, - 32 MB + 4*/
489
- instr = create_branch(&instr, addr - 0x2000004, BRANCH_SET_LINK);
490
- check(instr == 0);
480
+ err = create_branch(&instr, &instr, addr - 0x2000004, BRANCH_SET_LINK);
481
+ check(err);
491482
492483 /* Out of range relative positive offset, + 32 MB */
493
- instr = create_branch(&instr, addr + 0x2000000, BRANCH_SET_LINK);
494
- check(instr == 0);
484
+ err = create_branch(&instr, &instr, addr + 0x2000000, BRANCH_SET_LINK);
485
+ check(err);
495486
496487 /* Unaligned target */
497
- instr = create_branch(&instr, addr + 3, BRANCH_SET_LINK);
498
- check(instr == 0);
488
+ err = create_branch(&instr, &instr, addr + 3, BRANCH_SET_LINK);
489
+ check(err);
499490
500491 /* Check flags are masked correctly */
501
- instr = create_branch(&instr, addr, 0xFFFFFFFC);
492
+ err = create_branch(&instr, &instr, addr, 0xFFFFFFFC);
502493 check(instr_is_branch_to_addr(&instr, addr));
503
- check(instr == 0x48000000);
494
+ check(ppc_inst_equal(instr, ppc_inst(0x48000000)));
504495 }
505496
506497 static void __init test_create_function_call(void)
507498 {
508
- unsigned int *iptr;
499
+ struct ppc_inst *iptr;
509500 unsigned long dest;
501
+ struct ppc_inst instr;
510502
511503 /* Check we can create a function call */
512
- iptr = (unsigned int *)ppc_function_entry(test_trampoline);
504
+ iptr = (struct ppc_inst *)ppc_function_entry(test_trampoline);
513505 dest = ppc_function_entry(test_create_function_call);
514
- patch_instruction(iptr, create_branch(iptr, dest, BRANCH_SET_LINK));
506
+ create_branch(&instr, iptr, dest, BRANCH_SET_LINK);
507
+ patch_instruction(iptr, instr);
515508 check(instr_is_branch_to_addr(iptr, dest));
516509 }
517510
518511 static void __init test_branch_bform(void)
519512 {
513
+ int err;
520514 unsigned long addr;
521
- unsigned int *iptr, instr, flags;
515
+ struct ppc_inst *iptr, instr;
516
+ unsigned int flags;
522517
523518 iptr = &instr;
524519 addr = (unsigned long)iptr;
525520
526521 /* The simplest case, branch to self, no flags */
527
- check(instr_is_branch_bform(0x40000000));
522
+ check(instr_is_branch_bform(ppc_inst(0x40000000)));
528523 /* All bits of target set, and flags */
529
- check(instr_is_branch_bform(0x43ffffff));
524
+ check(instr_is_branch_bform(ppc_inst(0x43ffffff)));
530525 /* High bit of opcode set, which is wrong */
531
- check(!instr_is_branch_bform(0xc3ffffff));
526
+ check(!instr_is_branch_bform(ppc_inst(0xc3ffffff)));
532527 /* Middle bits of opcode set, which is wrong */
533
- check(!instr_is_branch_bform(0x7bffffff));
528
+ check(!instr_is_branch_bform(ppc_inst(0x7bffffff)));
534529
535530 /* Absolute conditional branch to 0x100 */
536
- instr = 0x43ff0103;
531
+ instr = ppc_inst(0x43ff0103);
537532 check(instr_is_branch_to_addr(&instr, 0x100));
538533 /* Absolute conditional branch to 0x20fc */
539
- instr = 0x43ff20ff;
534
+ instr = ppc_inst(0x43ff20ff);
540535 check(instr_is_branch_to_addr(&instr, 0x20fc));
541536 /* Maximum positive relative conditional branch, + 32 KB - 4B */
542
- instr = 0x43ff7ffc;
537
+ instr = ppc_inst(0x43ff7ffc);
543538 check(instr_is_branch_to_addr(&instr, addr + 0x7FFC));
544539 /* Smallest negative relative conditional branch, - 4B */
545
- instr = 0x43fffffc;
540
+ instr = ppc_inst(0x43fffffc);
546541 check(instr_is_branch_to_addr(&instr, addr - 4));
547542 /* Largest negative relative conditional branch, - 32 KB */
548
- instr = 0x43ff8000;
543
+ instr = ppc_inst(0x43ff8000);
549544 check(instr_is_branch_to_addr(&instr, addr - 0x8000));
550545
551546 /* All condition code bits set & link */
552547 flags = 0x3ff000 | BRANCH_SET_LINK;
553548
554549 /* Branch to self */
555
- instr = create_cond_branch(iptr, addr, flags);
550
+ err = create_cond_branch(&instr, iptr, addr, flags);
556551 check(instr_is_branch_to_addr(&instr, addr));
557552
558553 /* Branch to self - 0x100 */
559
- instr = create_cond_branch(iptr, addr - 0x100, flags);
554
+ err = create_cond_branch(&instr, iptr, addr - 0x100, flags);
560555 check(instr_is_branch_to_addr(&instr, addr - 0x100));
561556
562557 /* Branch to self + 0x100 */
563
- instr = create_cond_branch(iptr, addr + 0x100, flags);
558
+ err = create_cond_branch(&instr, iptr, addr + 0x100, flags);
564559 check(instr_is_branch_to_addr(&instr, addr + 0x100));
565560
566561 /* Maximum relative negative offset, - 32 KB */
567
- instr = create_cond_branch(iptr, addr - 0x8000, flags);
562
+ err = create_cond_branch(&instr, iptr, addr - 0x8000, flags);
568563 check(instr_is_branch_to_addr(&instr, addr - 0x8000));
569564
570565 /* Out of range relative negative offset, - 32 KB + 4*/
571
- instr = create_cond_branch(iptr, addr - 0x8004, flags);
572
- check(instr == 0);
566
+ err = create_cond_branch(&instr, iptr, addr - 0x8004, flags);
567
+ check(err);
573568
574569 /* Out of range relative positive offset, + 32 KB */
575
- instr = create_cond_branch(iptr, addr + 0x8000, flags);
576
- check(instr == 0);
570
+ err = create_cond_branch(&instr, iptr, addr + 0x8000, flags);
571
+ check(err);
577572
578573 /* Unaligned target */
579
- instr = create_cond_branch(iptr, addr + 3, flags);
580
- check(instr == 0);
574
+ err = create_cond_branch(&instr, iptr, addr + 3, flags);
575
+ check(err);
581576
582577 /* Check flags are masked correctly */
583
- instr = create_cond_branch(iptr, addr, 0xFFFFFFFC);
578
+ err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
584579 check(instr_is_branch_to_addr(&instr, addr));
585
- check(instr == 0x43FF0000);
580
+ check(ppc_inst_equal(instr, ppc_inst(0x43FF0000)));
586581 }
587582
588583 static void __init test_translate_branch(void)
589584 {
590585 unsigned long addr;
591
- unsigned int *p, *q;
586
+ void *p, *q;
587
+ struct ppc_inst instr;
592588 void *buf;
593589
594590 buf = vmalloc(PAGE_ALIGN(0x2000000 + 1));
....@@ -601,8 +597,9 @@
601597 addr = (unsigned long)p;
602598 patch_branch(p, addr, 0);
603599 check(instr_is_branch_to_addr(p, addr));
604
- q = p + 1;
605
- patch_instruction(q, translate_branch(q, p));
600
+ q = p + 4;
601
+ translate_branch(&instr, q, p);
602
+ patch_instruction(q, instr);
606603 check(instr_is_branch_to_addr(q, addr));
607604
608605 /* Maximum negative case, move b . to addr + 32 MB */
....@@ -610,27 +607,30 @@
610607 addr = (unsigned long)p;
611608 patch_branch(p, addr, 0);
612609 q = buf + 0x2000000;
613
- patch_instruction(q, translate_branch(q, p));
610
+ translate_branch(&instr, q, p);
611
+ patch_instruction(q, instr);
614612 check(instr_is_branch_to_addr(p, addr));
615613 check(instr_is_branch_to_addr(q, addr));
616
- check(*q == 0x4a000000);
614
+ check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x4a000000)));
617615
618616 /* Maximum positive case, move x to x - 32 MB + 4 */
619617 p = buf + 0x2000000;
620618 addr = (unsigned long)p;
621619 patch_branch(p, addr, 0);
622620 q = buf + 4;
623
- patch_instruction(q, translate_branch(q, p));
621
+ translate_branch(&instr, q, p);
622
+ patch_instruction(q, instr);
624623 check(instr_is_branch_to_addr(p, addr));
625624 check(instr_is_branch_to_addr(q, addr));
626
- check(*q == 0x49fffffc);
625
+ check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x49fffffc)));
627626
628627 /* Jump to x + 16 MB moved to x + 20 MB */
629628 p = buf;
630629 addr = 0x1000000 + (unsigned long)buf;
631630 patch_branch(p, addr, BRANCH_SET_LINK);
632631 q = buf + 0x1400000;
633
- patch_instruction(q, translate_branch(q, p));
632
+ translate_branch(&instr, q, p);
633
+ patch_instruction(q, instr);
634634 check(instr_is_branch_to_addr(p, addr));
635635 check(instr_is_branch_to_addr(q, addr));
636636
....@@ -639,7 +639,8 @@
639639 addr = 0x2000000 + (unsigned long)buf;
640640 patch_branch(p, addr, 0);
641641 q = buf + 4;
642
- patch_instruction(q, translate_branch(q, p));
642
+ translate_branch(&instr, q, p);
643
+ patch_instruction(q, instr);
643644 check(instr_is_branch_to_addr(p, addr));
644645 check(instr_is_branch_to_addr(q, addr));
645646
....@@ -649,53 +650,83 @@
649650 /* Simple case, branch to self moved a little */
650651 p = buf;
651652 addr = (unsigned long)p;
652
- patch_instruction(p, create_cond_branch(p, addr, 0));
653
+ create_cond_branch(&instr, p, addr, 0);
654
+ patch_instruction(p, instr);
653655 check(instr_is_branch_to_addr(p, addr));
654
- q = p + 1;
655
- patch_instruction(q, translate_branch(q, p));
656
+ q = buf + 4;
657
+ translate_branch(&instr, q, p);
658
+ patch_instruction(q, instr);
656659 check(instr_is_branch_to_addr(q, addr));
657660
658661 /* Maximum negative case, move b . to addr + 32 KB */
659662 p = buf;
660663 addr = (unsigned long)p;
661
- patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC));
664
+ create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
665
+ patch_instruction(p, instr);
662666 q = buf + 0x8000;
663
- patch_instruction(q, translate_branch(q, p));
667
+ translate_branch(&instr, q, p);
668
+ patch_instruction(q, instr);
664669 check(instr_is_branch_to_addr(p, addr));
665670 check(instr_is_branch_to_addr(q, addr));
666
- check(*q == 0x43ff8000);
671
+ check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff8000)));
667672
668673 /* Maximum positive case, move x to x - 32 KB + 4 */
669674 p = buf + 0x8000;
670675 addr = (unsigned long)p;
671
- patch_instruction(p, create_cond_branch(p, addr, 0xFFFFFFFC));
676
+ create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
677
+ patch_instruction(p, instr);
672678 q = buf + 4;
673
- patch_instruction(q, translate_branch(q, p));
679
+ translate_branch(&instr, q, p);
680
+ patch_instruction(q, instr);
674681 check(instr_is_branch_to_addr(p, addr));
675682 check(instr_is_branch_to_addr(q, addr));
676
- check(*q == 0x43ff7ffc);
683
+ check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff7ffc)));
677684
678685 /* Jump to x + 12 KB moved to x + 20 KB */
679686 p = buf;
680687 addr = 0x3000 + (unsigned long)buf;
681
- patch_instruction(p, create_cond_branch(p, addr, BRANCH_SET_LINK));
688
+ create_cond_branch(&instr, p, addr, BRANCH_SET_LINK);
689
+ patch_instruction(p, instr);
682690 q = buf + 0x5000;
683
- patch_instruction(q, translate_branch(q, p));
691
+ translate_branch(&instr, q, p);
692
+ patch_instruction(q, instr);
684693 check(instr_is_branch_to_addr(p, addr));
685694 check(instr_is_branch_to_addr(q, addr));
686695
687696 /* Jump to x + 8 KB moved to x - 8 KB + 4 */
688697 p = buf + 0x2000;
689698 addr = 0x4000 + (unsigned long)buf;
690
- patch_instruction(p, create_cond_branch(p, addr, 0));
699
+ create_cond_branch(&instr, p, addr, 0);
700
+ patch_instruction(p, instr);
691701 q = buf + 4;
692
- patch_instruction(q, translate_branch(q, p));
702
+ translate_branch(&instr, q, p);
703
+ patch_instruction(q, instr);
693704 check(instr_is_branch_to_addr(p, addr));
694705 check(instr_is_branch_to_addr(q, addr));
695706
696707 /* Free the buffer we were using */
697708 vfree(buf);
698709 }
710
+
711
+#ifdef CONFIG_PPC64
712
+static void __init test_prefixed_patching(void)
713
+{
714
+ extern unsigned int code_patching_test1[];
715
+ extern unsigned int code_patching_test1_expected[];
716
+ extern unsigned int end_code_patching_test1[];
717
+
718
+ __patch_instruction((struct ppc_inst *)code_patching_test1,
719
+ ppc_inst_prefix(OP_PREFIX << 26, 0x00000000),
720
+ (struct ppc_inst *)code_patching_test1);
721
+
722
+ check(!memcmp(code_patching_test1,
723
+ code_patching_test1_expected,
724
+ sizeof(unsigned int) *
725
+ (end_code_patching_test1 - code_patching_test1)));
726
+}
727
+#else
728
+static inline void test_prefixed_patching(void) {}
729
+#endif
699730
700731 static int __init test_code_patching(void)
701732 {
....@@ -705,6 +736,7 @@
705736 test_branch_bform();
706737 test_create_function_call();
707738 test_translate_branch();
739
+ test_prefixed_patching();
708740
709741 return 0;
710742 }