Extend the SMMPT system-test coverage to the two larger RV64 memory
protection schemes: Smmpt52 (4-level MPT, 52-bit SPA) and Smmpt64
(5-level MPT, 64-bit SPA with a 32 KiB / 32 KiB-aligned root table).

Both tests reuse the mode-independent harness in smmpt-common.S and only
differ in the number of radix levels and, for Smmpt64, the root-table
size and alignment. They exercise the same permission and structural
checks (all XWR encodings for load and store, V=0 and reserved-bit
leaves, and NAPOT leaves with a valid and a reserved G field) and are
wired into the Makefile as run-test-smmpt52 and run-test-smmpt64.

Signed-off-by: LIU Zhiwei <[email protected]>
---
 tests/tcg/riscv64/Makefile.softmmu-target |  8 ++
 tests/tcg/riscv64/test-smmpt52.S          | 91 +++++++++++++++++++++
 tests/tcg/riscv64/test-smmpt64.S          | 98 +++++++++++++++++++++++
 3 files changed, 197 insertions(+)
 create mode 100644 tests/tcg/riscv64/test-smmpt52.S
 create mode 100644 tests/tcg/riscv64/test-smmpt64.S

diff --git a/tests/tcg/riscv64/Makefile.softmmu-target 
b/tests/tcg/riscv64/Makefile.softmmu-target
index 18da9c6299..6bbec02ed2 100644
--- a/tests/tcg/riscv64/Makefile.softmmu-target
+++ b/tests/tcg/riscv64/Makefile.softmmu-target
@@ -45,5 +45,13 @@ EXTRA_RUNS += run-test-smmpt
 run-test-smmpt: test-smmpt
        $(call run-test, $<, $(QEMU) -cpu rv64$(comma)x-smmpt=true 
$(QEMU_OPTS)$<)
 
+EXTRA_RUNS += run-test-smmpt52
+run-test-smmpt52: test-smmpt52
+       $(call run-test, $<, $(QEMU) -cpu rv64$(comma)x-smmpt=true 
$(QEMU_OPTS)$<)
+
+EXTRA_RUNS += run-test-smmpt64
+run-test-smmpt64: test-smmpt64
+       $(call run-test, $<, $(QEMU) -cpu rv64$(comma)x-smmpt=true 
$(QEMU_OPTS)$<)
+
 # We don't currently support the multiarch system tests
 undefine MULTIARCH_TESTS
diff --git a/tests/tcg/riscv64/test-smmpt52.S b/tests/tcg/riscv64/test-smmpt52.S
new file mode 100644
index 0000000000..445ba50d22
--- /dev/null
+++ b/tests/tcg/riscv64/test-smmpt52.S
@@ -0,0 +1,91 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Test for the Smmpt52 (Supervisor Memory Protection Table) extension,
+ * per SMMTT specification v0.4.9.
+ *
+ * Smmpt52 uses a 4-level MPT with 8-byte entries (16 pages per leaf,
+ * pi = SPA[15:12], pn[i] 9 bits at SPA[16 + i*9 +: 9]).  It shares the MPTE
+ * formats and the permission-lookup algorithm with Smmpt43, only adding one
+ * more radix level.  See smmpt-common.S for the MPRV trick, the shared
+ * address layout and the exit-code convention.
+ *
+ * For the low (< 4 GiB) addresses exercised here pn[3] and pn[2] are 0, so
+ * the upper levels are single-entry chains:
+ *
+ *   L3 (root) @ 0x8040_0000 : entry[0]  -> non-leaf, PPN(L2)=0x80410
+ *   L2        @ 0x8041_0000 : entry[0]  -> non-leaf, PPN(L1)=0x80420
+ *   L1        @ 0x8042_0000 : entry[64] -> non-leaf, PPN(L0)=0x80430
+ *   L0        @ 0x8043_0000 :
+ *     entry[80]  -> non-NAPOT leaf (LEAF_ALL_XWR)  covering 0x8050_0000+
+ *     entry[81]  -> V=0 (invalid)                  covering 0x8051_0000
+ *     entry[82]  -> leaf with a reserved bit set    covering 0x8052_0000
+ *     entry[96]  -> NAPOT leaf, G=4, XWR=RW         covering 0x8060_0000
+ *     entry[128] -> NAPOT leaf, reserved G=5        covering 0x8080_0000
+ *
+ *   mmpt = MODE(2=Smmpt52)<<60 | PPN(0x80400)
+ */
+
+#include "smmpt-common.S"
+
+       .option norvc
+
+       .text
+       .global _start
+_start:
+       /* Install the M-mode trap handler */
+       lla     t0, mtrap
+       csrw    mtvec, t0
+       csrw    medeleg, zero
+
+       /* PMP entry 0: NAPOT covering the whole space, RWX. */
+       li      t0, -1
+       csrw    pmpaddr0, t0
+       li      t0, 0x1f
+       csrw    pmpcfg0, t0
+
+       /* Build the MPT tables (M-mode stores bypass the MPT). */
+       /* L3[0] = non-leaf -> L2 (PPN 0x80410) */
+       li      t0, 0x80400000
+       li      t1, 0x20104001
+       sd      t1, 0(t0)
+       /* L2[0] = non-leaf -> L1 (PPN 0x80420) */
+       li      t0, 0x80410000
+       li      t1, 0x20108001
+       sd      t1, 0(t0)
+       /* L1[64] = non-leaf -> L0 (PPN 0x80430) */
+       li      t0, 0x80420000
+       li      t1, 0x2010C001
+       sd      t1, 0x200(t0)           /* 64 * 8 = 0x200 */
+
+       li      t0, 0x80430000
+       /* L0[80] = non-NAPOT leaf carrying all XWR encodings (pi0..pi7) */
+       li      t1, LEAF_ALL_XWR
+       sd      t1, 0x280(t0)           /* 80 * 8 = 0x280 */
+       /* L0[81] = 0: invalid entry (V=0) */
+       sd      x0, 0x288(t0)           /* 81 * 8 = 0x288 */
+       /* L0[82] = leaf with reserved bit 3 set */
+       li      t1, 0x30B
+       sd      t1, 0x290(t0)           /* 82 * 8 = 0x290 */
+       /* L0[96] = NAPOT leaf: V|L|N | XWR=RW | G=4 */
+       li      t1, 0x4307
+       sd      t1, 0x300(t0)           /* 96 * 8 = 0x300 */
+       /* L0[128] = NAPOT leaf with reserved G=5 */
+       li      t1, 0x5307
+       sd      t1, 0x400(t0)           /* 128 * 8 = 0x400 */
+
+       /* Program mmpt: MODE=2 (Smmpt52), PPN = 0x80400 */
+       li      t0, 0x2000000000080400
+       csrw    0x382, t0               /* CSR_MMPT */
+
+       /* mfence.pa must not fault in M-mode */
+       TEST_MFENCE_PA 1
+
+       /* Run the shared permission and structural checks */
+       RUN_LEAF_CHECKS
+
+       /* All tests passed */
+       li      a0, 0
+       j       _exit
+
+       SMMPT_HARNESS
diff --git a/tests/tcg/riscv64/test-smmpt64.S b/tests/tcg/riscv64/test-smmpt64.S
new file mode 100644
index 0000000000..d67035aabb
--- /dev/null
+++ b/tests/tcg/riscv64/test-smmpt64.S
@@ -0,0 +1,98 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Test for the Smmpt64 (Supervisor Memory Protection Table) extension,
+ * per SMMTT specification v0.4.9.
+ *
+ * Smmpt64 uses a 5-level MPT with 8-byte entries.  Unlike the other RV64
+ * modes its root table is 32 KiB (2^12 entries, pn[4] = SPA[63:52], 12 bits)
+ * and must be aligned to a 32 KiB boundary; the non-root levels are the usual
+ * 4 KiB / 9-bit tables (16 pages per leaf, pi = SPA[15:12]).  See
+ * smmpt-common.S for the MPRV trick, the shared address layout and the
+ * exit-code convention.
+ *
+ * For the low (< 4 GiB) addresses exercised here pn[4], pn[3] and pn[2] are
+ * 0, so the upper levels are single-entry chains:
+ *
+ *   L4 (root) @ 0x8040_0000 : entry[0]  -> non-leaf, PPN(L3)=0x80410
+ *                             (32 KiB / 32 KiB-aligned)
+ *   L3        @ 0x8041_0000 : entry[0]  -> non-leaf, PPN(L2)=0x80420
+ *   L2        @ 0x8042_0000 : entry[0]  -> non-leaf, PPN(L1)=0x80430
+ *   L1        @ 0x8043_0000 : entry[64] -> non-leaf, PPN(L0)=0x80440
+ *   L0        @ 0x8044_0000 :
+ *     entry[80]  -> non-NAPOT leaf (LEAF_ALL_XWR)  covering 0x8050_0000+
+ *     entry[81]  -> V=0 (invalid)                  covering 0x8051_0000
+ *     entry[82]  -> leaf with a reserved bit set    covering 0x8052_0000
+ *     entry[96]  -> NAPOT leaf, G=4, XWR=RW         covering 0x8060_0000
+ *     entry[128] -> NAPOT leaf, reserved G=5        covering 0x8080_0000
+ *
+ *   mmpt = MODE(3=Smmpt64)<<60 | PPN(0x80400)   (PPN[2:0] must be 0)
+ */
+
+#include "smmpt-common.S"
+
+       .option norvc
+
+       .text
+       .global _start
+_start:
+       /* Install the M-mode trap handler */
+       lla     t0, mtrap
+       csrw    mtvec, t0
+       csrw    medeleg, zero
+
+       /* PMP entry 0: NAPOT covering the whole space, RWX. */
+       li      t0, -1
+       csrw    pmpaddr0, t0
+       li      t0, 0x1f
+       csrw    pmpcfg0, t0
+
+       /* Build the MPT tables (M-mode stores bypass the MPT). */
+       /* L4[0] = non-leaf -> L3 (PPN 0x80410); root is 32 KiB aligned */
+       li      t0, 0x80400000
+       li      t1, 0x20104001
+       sd      t1, 0(t0)
+       /* L3[0] = non-leaf -> L2 (PPN 0x80420) */
+       li      t0, 0x80410000
+       li      t1, 0x20108001
+       sd      t1, 0(t0)
+       /* L2[0] = non-leaf -> L1 (PPN 0x80430) */
+       li      t0, 0x80420000
+       li      t1, 0x2010C001
+       sd      t1, 0(t0)
+       /* L1[64] = non-leaf -> L0 (PPN 0x80440) */
+       li      t0, 0x80430000
+       li      t1, 0x20110001
+       sd      t1, 0x200(t0)           /* 64 * 8 = 0x200 */
+
+       li      t0, 0x80440000
+       /* L0[80] = non-NAPOT leaf carrying all XWR encodings (pi0..pi7) */
+       li      t1, LEAF_ALL_XWR
+       sd      t1, 0x280(t0)           /* 80 * 8 = 0x280 */
+       /* L0[81] = 0: invalid entry (V=0) */
+       sd      x0, 0x288(t0)           /* 81 * 8 = 0x288 */
+       /* L0[82] = leaf with reserved bit 3 set */
+       li      t1, 0x30B
+       sd      t1, 0x290(t0)           /* 82 * 8 = 0x290 */
+       /* L0[96] = NAPOT leaf: V|L|N | XWR=RW | G=4 */
+       li      t1, 0x4307
+       sd      t1, 0x300(t0)           /* 96 * 8 = 0x300 */
+       /* L0[128] = NAPOT leaf with reserved G=5 */
+       li      t1, 0x5307
+       sd      t1, 0x400(t0)           /* 128 * 8 = 0x400 */
+
+       /* Program mmpt: MODE=3 (Smmpt64), PPN = 0x80400 */
+       li      t0, 0x3000000000080400
+       csrw    0x382, t0               /* CSR_MMPT */
+
+       /* mfence.pa must not fault in M-mode */
+       TEST_MFENCE_PA 1
+
+       /* Run the shared permission and structural checks */
+       RUN_LEAF_CHECKS
+
+       /* All tests passed */
+       li      a0, 0
+       j       _exit
+
+       SMMPT_HARNESS
-- 
2.43.0


Reply via email to