@@ -205,9 +205,6 @@ void __init poking_init(void)
205
205
{
206
206
int ret ;
207
207
208
- if (!IS_ENABLED (CONFIG_STRICT_KERNEL_RWX ))
209
- return ;
210
-
211
208
if (mm_patch_enabled ())
212
209
ret = cpuhp_setup_state (CPUHP_AP_ONLINE_DYN ,
213
210
"powerpc/text_poke_mm:online" ,
@@ -375,6 +372,144 @@ int patch_instruction(u32 *addr, ppc_inst_t instr)
375
372
}
376
373
NOKPROBE_SYMBOL (patch_instruction );
377
374
375
+ static int __patch_instructions (u32 * patch_addr , u32 * code , size_t len , bool repeat_instr )
376
+ {
377
+ unsigned long start = (unsigned long )patch_addr ;
378
+
379
+ /* Repeat instruction */
380
+ if (repeat_instr ) {
381
+ ppc_inst_t instr = ppc_inst_read (code );
382
+
383
+ if (ppc_inst_prefixed (instr )) {
384
+ u64 val = ppc_inst_as_ulong (instr );
385
+
386
+ memset64 ((u64 * )patch_addr , val , len / 8 );
387
+ } else {
388
+ u32 val = ppc_inst_val (instr );
389
+
390
+ memset32 (patch_addr , val , len / 4 );
391
+ }
392
+ } else {
393
+ memcpy (patch_addr , code , len );
394
+ }
395
+
396
+ smp_wmb (); /* smp write barrier */
397
+ flush_icache_range (start , start + len );
398
+ return 0 ;
399
+ }
400
+
401
+ /*
402
+ * A page is mapped and instructions that fit the page are patched.
403
+ * Assumes 'len' to be (PAGE_SIZE - offset_in_page(addr)) or below.
404
+ */
405
+ static int __do_patch_instructions_mm (u32 * addr , u32 * code , size_t len , bool repeat_instr )
406
+ {
407
+ struct mm_struct * patching_mm , * orig_mm ;
408
+ unsigned long pfn = get_patch_pfn (addr );
409
+ unsigned long text_poke_addr ;
410
+ spinlock_t * ptl ;
411
+ u32 * patch_addr ;
412
+ pte_t * pte ;
413
+ int err ;
414
+
415
+ patching_mm = __this_cpu_read (cpu_patching_context .mm );
416
+ text_poke_addr = __this_cpu_read (cpu_patching_context .addr );
417
+ patch_addr = (u32 * )(text_poke_addr + offset_in_page (addr ));
418
+
419
+ pte = get_locked_pte (patching_mm , text_poke_addr , & ptl );
420
+ if (!pte )
421
+ return - ENOMEM ;
422
+
423
+ __set_pte_at (patching_mm , text_poke_addr , pte , pfn_pte (pfn , PAGE_KERNEL ), 0 );
424
+
425
+ /* order PTE update before use, also serves as the hwsync */
426
+ asm volatile ("ptesync" ::: "memory" );
427
+
428
+ /* order context switch after arbitrary prior code */
429
+ isync ();
430
+
431
+ orig_mm = start_using_temp_mm (patching_mm );
432
+
433
+ err = __patch_instructions (patch_addr , code , len , repeat_instr );
434
+
435
+ /* context synchronisation performed by __patch_instructions */
436
+ stop_using_temp_mm (patching_mm , orig_mm );
437
+
438
+ pte_clear (patching_mm , text_poke_addr , pte );
439
+ /*
440
+ * ptesync to order PTE update before TLB invalidation done
441
+ * by radix__local_flush_tlb_page_psize (in _tlbiel_va)
442
+ */
443
+ local_flush_tlb_page_psize (patching_mm , text_poke_addr , mmu_virtual_psize );
444
+
445
+ pte_unmap_unlock (pte , ptl );
446
+
447
+ return err ;
448
+ }
449
+
450
+ /*
451
+ * A page is mapped and instructions that fit the page are patched.
452
+ * Assumes 'len' to be (PAGE_SIZE - offset_in_page(addr)) or below.
453
+ */
454
+ static int __do_patch_instructions (u32 * addr , u32 * code , size_t len , bool repeat_instr )
455
+ {
456
+ unsigned long pfn = get_patch_pfn (addr );
457
+ unsigned long text_poke_addr ;
458
+ u32 * patch_addr ;
459
+ pte_t * pte ;
460
+ int err ;
461
+
462
+ text_poke_addr = (unsigned long )__this_cpu_read (cpu_patching_context .addr ) & PAGE_MASK ;
463
+ patch_addr = (u32 * )(text_poke_addr + offset_in_page (addr ));
464
+
465
+ pte = __this_cpu_read (cpu_patching_context .pte );
466
+ __set_pte_at (& init_mm , text_poke_addr , pte , pfn_pte (pfn , PAGE_KERNEL ), 0 );
467
+ /* See ptesync comment in radix__set_pte_at() */
468
+ if (radix_enabled ())
469
+ asm volatile ("ptesync" ::: "memory" );
470
+
471
+ err = __patch_instructions (patch_addr , code , len , repeat_instr );
472
+
473
+ pte_clear (& init_mm , text_poke_addr , pte );
474
+ flush_tlb_kernel_range (text_poke_addr , text_poke_addr + PAGE_SIZE );
475
+
476
+ return err ;
477
+ }
478
+
479
+ /*
480
+ * Patch 'addr' with 'len' bytes of instructions from 'code'.
481
+ *
482
+ * If repeat_instr is true, the same instruction is filled for
483
+ * 'len' bytes.
484
+ */
485
+ int patch_instructions (u32 * addr , u32 * code , size_t len , bool repeat_instr )
486
+ {
487
+ while (len > 0 ) {
488
+ unsigned long flags ;
489
+ size_t plen ;
490
+ int err ;
491
+
492
+ plen = min_t (size_t , PAGE_SIZE - offset_in_page (addr ), len );
493
+
494
+ local_irq_save (flags );
495
+ if (mm_patch_enabled ())
496
+ err = __do_patch_instructions_mm (addr , code , plen , repeat_instr );
497
+ else
498
+ err = __do_patch_instructions (addr , code , plen , repeat_instr );
499
+ local_irq_restore (flags );
500
+ if (err )
501
+ return err ;
502
+
503
+ len -= plen ;
504
+ addr = (u32 * )((unsigned long )addr + plen );
505
+ if (!repeat_instr )
506
+ code = (u32 * )((unsigned long )code + plen );
507
+ }
508
+
509
+ return 0 ;
510
+ }
511
+ NOKPROBE_SYMBOL (patch_instructions );
512
+
378
513
int patch_branch (u32 * addr , unsigned long target , int flags )
379
514
{
380
515
ppc_inst_t instr ;
0 commit comments