Skip to content

Commit c5ef5e3

Browse files
BenjaminGrayNp1mpe
authored andcommitted
powerpc/code-patching: Test patch_instructions() during boot
patch_instructions() introduces new behaviour with a couple of variations. Test each case of * a repeated 32-bit instruction, * a repeated 64-bit instruction (ppc64), and * a copied sequence of instructions for both on a single page and when it crosses a page boundary. Signed-off-by: Benjamin Gray <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://msgid.link/[email protected]
1 parent 295454e commit c5ef5e3

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

arch/powerpc/lib/test-code-patching.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
350441
static 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

Comments
 (0)