Add SMMPT system-test coverage for Smmpt34, the RV32-only memory protection scheme (2-level MPT with 4-byte entries).
Smmpt34 requires a 32-bit CPU, but qemu-system-riscv64 can run a 32-bit CPU (-cpu rv32), so the test lives in tests/tcg/riscv64 alongside the RV64 Smmpt tests and shares the same harness (smmpt-common.S). It only differs in the table geometry: 4-byte MPTEs, two radix levels, a 10-bit level-0 index and the RV32 mmpt CSR layout (MODE in bits[31:30]). It exercises the same permission and structural checks as the RV64 tests (all XWR encodings for load and store, V=0 and reserved-bit leaves, and NAPOT leaves with a valid and a reserved G field), using the same access addresses. It is built for RV32 and run on qemu-system-riscv64 with -cpu rv32. Signed-off-by: LIU Zhiwei <[email protected]> --- tests/tcg/riscv64/test-smmpt34.S | 97 ++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tests/tcg/riscv64/test-smmpt34.S diff --git a/tests/tcg/riscv64/test-smmpt34.S b/tests/tcg/riscv64/test-smmpt34.S new file mode 100644 index 0000000000..92c8320999 --- /dev/null +++ b/tests/tcg/riscv64/test-smmpt34.S @@ -0,0 +1,97 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Test for the Smmpt34 (Supervisor Memory Protection Table) extension, + * per SMMTT specification v0.4.9. Smmpt34 is the RV32-only scheme. + * + * Although Smmpt34 requires a 32-bit CPU, the program is run on + * qemu-system-riscv64 with a 32-bit CPU (-cpu rv32), which lives in the + * same target as the RV64 Smmpt tests. It is therefore kept here in + * tests/tcg/riscv64 alongside the other Smmpt tests and shares the same + * harness (smmpt-common.S). Build it for RV32 and run it as: + * + * $CC -march=rv32ima_zicsr -mabi=ilp32 -I tests/tcg/riscv64 \ + * tests/tcg/riscv64/test-smmpt34.S -Wa,--noexecstack -c -o smmpt34.o + * $LD -m elf32lriscv -T tests/tcg/riscv64/semihost.ld smmpt34.o -o smmpt34 + * qemu-system-riscv64 -cpu rv32,x-smmpt=true -M virt -display none \ + * -semihosting -device loader,file=smmpt34 + * + * Smmpt34 uses a 2-level MPT with 4-byte entries (8 pages per leaf, + * pi = SPA[14:12]). The supervisor physical address is partitioned as + * pn[1] = SPA[33:25] (9-bit root index), pn[0] = SPA[24:15] (10-bit level-0 + * index) and range offset SPA[14:0]. For the RAM addresses used here + * (0x8xxx_xxxx, < 4 GiB) pn[1] resolves to 64. See smmpt-common.S for the + * MPRV trick, the shared address layout and the exit-code convention. + * + * This test reuses the same shared harness and the same access addresses as + * the RV64 tests; only the table geometry (4-byte entries, 2 levels, 10-bit + * level-0 index) and the RV32 mmpt layout differ. + * + * MPT layout (Smmpt34, 2 levels, 4-byte entries): + * + * L1 (root) @ 0x8040_0000 : entry[64] -> non-leaf, PPN(L0)=0x80410 + * L0 @ 0x8041_0000 : + * entry[160] -> non-NAPOT leaf (LEAF_ALL_XWR) covering 0x8050_0000+ + * entry[162] -> V=0 (invalid) covering 0x8051_0000 + * entry[164] -> leaf with a reserved bit set covering 0x8052_0000 + * entry[192] -> NAPOT leaf, G=6, XWR=RW covering 0x8060_0000 + * entry[256] -> NAPOT leaf, reserved G=0 covering 0x8080_0000 + * + * mmpt = MODE(1=Smmpt34)<<30 | 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). */ + /* L1[64] = non-leaf -> L0 (PPN 0x80410): (0x80410 << 10) | V */ + li t0, 0x80400000 + li t1, 0x20104001 + sw t1, 0x100(t0) /* 64 * 4 = 0x100 */ + + li t0, 0x80410000 + /* L0[160] = non-NAPOT leaf carrying all XWR encodings (pi0..pi7) */ + li t1, LEAF_ALL_XWR + sw t1, 0x280(t0) /* 160 * 4 = 0x280 */ + /* L0[162] = 0: invalid entry (V=0) */ + sw x0, 0x288(t0) /* 162 * 4 = 0x288 */ + /* L0[164] = leaf with reserved bit 3 set (V|L|rsv|XWR[pi0]=RW) */ + li t1, 0x30B + sw t1, 0x290(t0) /* 164 * 4 = 0x290 */ + /* L0[192] = NAPOT leaf: V|L|N | XWR=RW(0x300) | G=6(0x6000) */ + li t1, 0x6307 + sw t1, 0x300(t0) /* 192 * 4 = 0x300 */ + /* L0[256] = NAPOT leaf with reserved G=0: V|L|N | XWR=RW | G=0 */ + li t1, 0x307 + sw t1, 0x400(t0) /* 256 * 4 = 0x400 */ + + /* Program mmpt: MODE=1 (Smmpt34) at bits[31:30], PPN = 0x80400 */ + li t0, 0x40080400 + 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
