Add a new LKDTM trigger (PPC_RADIX_TLBIEL) that executes a process-scoped
radix TLBIEL instruction to exercise the radix MMU behaviour and
associated machine check exception (MCE) handling paths.

This provides a way to validate MCE handling in radix mode. Currently,
there is no dedicated LKDTM test that exercises this path or allows
triggering radix-specific machine check behaviour for validation.

The test is only enabled on ppc64 systems with radix MMU
support and If radix is not active, the trigger is skipped and reported as
XFAIL.

Co-developed-by: Ritesh Harjani (IBM) <[email protected]>
Signed-off-by: Ritesh Harjani (IBM) <[email protected]>
Signed-off-by: Sayali Patil <[email protected]>
---
 drivers/misc/lkdtm/Makefile             |  2 +-
 drivers/misc/lkdtm/core.c               |  2 +-
 drivers/misc/lkdtm/powerpc.c            | 44 +++++++++++++++++++++++++
 tools/testing/selftests/lkdtm/tests.txt |  1 +
 4 files changed, 47 insertions(+), 2 deletions(-)

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 <linux/vmalloc.h>
 #include <asm/mmu.h>
 
+#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
-- 
2.52.0


Reply via email to