@@ -347,6 +347,97 @@ static void __init test_prefixed_patching(void)
347
347
check (!memcmp (iptr , expected , sizeof (expected )));
348
348
}
349
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
+
350
441
static int __init test_code_patching (void )
351
442
{
352
443
pr_info ("Running code patching self-tests ...\n" );
@@ -356,6 +447,7 @@ static int __init test_code_patching(void)
356
447
test_create_function_call ();
357
448
test_translate_branch ();
358
449
test_prefixed_patching ();
450
+ test_multi_instruction_patching ();
359
451
360
452
return 0 ;
361
453
}
0 commit comments