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/powerpc.c            | 39 +++++++++++++++++++++++++
 tools/testing/selftests/lkdtm/tests.txt |  1 +
 3 files changed, 41 insertions(+), 1 deletion(-)

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/powerpc.c b/drivers/misc/lkdtm/powerpc.c
index ef07e5201edf..3d56b56f5e0c 100644
--- a/drivers/misc/lkdtm/powerpc.c
+++ b/drivers/misc/lkdtm/powerpc.c
@@ -105,6 +105,31 @@ static void insert_dup_slb_entry_0(void)
        preempt_enable();
 }
 
+static 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.
+        * Using PRS=1 (process-scoped) with kernel address does not correspond 
to
+        * any valid process-scoped translation.
+        * This results in an invalid tlbiel operation, causing 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)
 {
        if (!radix_enabled()) {
@@ -124,8 +149,22 @@ static void lkdtm_PPC_SLB_MULTIHIT(void)
        }
 }
 
+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