@@ -347,6 +347,97 @@ static void __init test_prefixed_patching(void)
347347 check (!memcmp (iptr , expected , sizeof (expected )));
348348}
349349
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+
350441static int __init test_code_patching (void )
351442{
352443 pr_info ("Running code patching self-tests ...\n" );
@@ -356,6 +447,7 @@ static int __init test_code_patching(void)
356447 test_create_function_call ();
357448 test_translate_branch ();
358449 test_prefixed_patching ();
450+ test_multi_instruction_patching ();
359451
360452 return 0 ;
361453}
0 commit comments