diff --git a/drivers/misc/lkdtm/Makefile b/drivers/misc/lkdtm/Makefile index 03ebe33185f9..4e58d16fc01e 100644 --- a/drivers/misc/lkdtm/Makefile +++ b/drivers/misc/lkdtm/Makefile @@ -11,7 +11,7 @@ lkdtm-$(CONFIG_LKDTM) += usercopy.o lkdtm-$(CONFIG_LKDTM) += kstack_erase.o lkdtm-$(CONFIG_LKDTM) += cfi.o lkdtm-$(CONFIG_LKDTM) += fortify.o -lkdtm-$(CONFIG_PPC_64S_HASH_MMU) += powerpc.o +lkdtm-$(CONFIG_PPC_BOOK3S_64) += powerpc.o KASAN_SANITIZE_stackleak.o := n diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c index 5732fd59a227..ededa32d6744 100644 --- a/drivers/misc/lkdtm/core.c +++ b/drivers/misc/lkdtm/core.c @@ -96,7 +96,7 @@ static const struct crashtype_category *crashtype_categories[] = { &stackleak_crashtypes, &cfi_crashtypes, &fortify_crashtypes, -#ifdef CONFIG_PPC_64S_HASH_MMU +#ifdef CONFIG_PPC_BOOK3S_64 &powerpc_crashtypes, #endif }; diff --git a/drivers/misc/lkdtm/powerpc.c b/drivers/misc/lkdtm/powerpc.c index ef07e5201edf..6eaac79ea26b 100644 --- a/drivers/misc/lkdtm/powerpc.c +++ b/drivers/misc/lkdtm/powerpc.c @@ -5,6 +5,7 @@ #include #include +#ifdef CONFIG_PPC_64S_HASH_MMU /* Inserts new slb entries */ static void insert_slb_entry(unsigned long p, int ssize, int page_size) { @@ -104,9 +105,35 @@ static void insert_dup_slb_entry_0(void) preempt_enable(); } +#endif /* CONFIG_PPC_64S_HASH_MMU */ + +static __always_inline void tlbiel_va(unsigned long va, + unsigned long pid, + unsigned long ap, + unsigned long ric) +{ + unsigned long rb, rs, prs, r; + + rb = va & ~(PPC_BITMASK(52, 63)); + rb |= ap << PPC_BITLSHIFT(58); + rs = pid << PPC_BITLSHIFT(31); + + prs = 1; /* process scoped */ + r = 1; /* radix format */ + + /* + * Trigger an MCE by issuing radix tlbiel with an invalid operand combination. + * The combination of RIC = 2 with IS = 0 (Invalidation selector specified + * in the RB register) is invalid. + * This invalid combination causes hardware to raise a machine check. + */ + asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1) + : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); +} static void lkdtm_PPC_SLB_MULTIHIT(void) { +#ifdef CONFIG_PPC_64S_HASH_MMU if (!radix_enabled()) { pr_info("Injecting SLB multihit errors\n"); /* @@ -122,10 +149,27 @@ static void lkdtm_PPC_SLB_MULTIHIT(void) } else { pr_err("XFAIL: This test is for ppc64 and with hash mode MMU only\n"); } +#else + pr_err("XFAIL: This test requires CONFIG_PPC_64S_HASH_MMU\n"); +#endif +} + +static void lkdtm_PPC_RADIX_TLBIEL(void) +{ + unsigned long addr = PAGE_OFFSET; + + if (radix_enabled()) { + pr_info("Injecting Radix TLB invalidation MCE\n"); + tlbiel_va(addr, 0, 0, RIC_FLUSH_ALL); + pr_info("Recovered from radix tlbiel attempt\n"); + } else { + pr_err("XFAIL: This test is for ppc64 and with radix mode MMU only\n"); + } } static struct crashtype crashtypes[] = { CRASHTYPE(PPC_SLB_MULTIHIT), + CRASHTYPE(PPC_RADIX_TLBIEL), }; struct crashtype_category powerpc_crashtypes = { diff --git a/tools/testing/selftests/lkdtm/tests.txt b/tools/testing/selftests/lkdtm/tests.txt index 3245032db34d..d8180bbe31e8 100644 --- a/tools/testing/selftests/lkdtm/tests.txt +++ b/tools/testing/selftests/lkdtm/tests.txt @@ -86,3 +86,4 @@ FORTIFY_STR_MEMBER detected buffer overflow FORTIFY_MEM_OBJECT detected buffer overflow FORTIFY_MEM_MEMBER detected field-spanning write PPC_SLB_MULTIHIT Recovered +#PPC_RADIX_TLBIEL Triggers unrecoverable MCE