Add a bare-metal test for vector fault-only-first loads whose first-element probe crosses a page boundary. The test covers a body access that crosses the boundary after the first element, and a first element that itself straddles the boundary, checking that both cases report a full vl and vstart of 0 rather than faulting on a mapped page.
Signed-off-by: Max Chou <[email protected]> --- tests/tcg/riscv64/Makefile.softmmu-target | 9 ++- tests/tcg/riscv64/test-rvv-ldst-ff-page.S | 83 +++++++++++++++++++++++ 2 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 tests/tcg/riscv64/test-rvv-ldst-ff-page.S diff --git a/tests/tcg/riscv64/Makefile.softmmu-target b/tests/tcg/riscv64/Makefile.softmmu-target index 9e0e0490753..93c4e58e0c2 100644 --- a/tests/tcg/riscv64/Makefile.softmmu-target +++ b/tests/tcg/riscv64/Makefile.softmmu-target @@ -86,14 +86,16 @@ run-test-vle32ff: test-vle32ff test-vle32ff: CFLAGS += -march=rv64gcv RVV_LDST_MARCH = -march=rv64gcv -RVV_LDST_TESTS = test-rvv-ldst-ff-pmp test-rvv-ldst-us-pmp +RVV_LDST_TESTS = test-rvv-ldst-ff-pmp test-rvv-ldst-us-pmp \ + test-rvv-ldst-ff-page CLEANFILES += $(RVV_LDST_TESTS) $(RVV_LDST_TESTS): %: %.S rvv-ldst.inc $(LINK_SCRIPT) $(CC) $(CFLAGS) $(RVV_LDST_MARCH) $< -Wa,--noexecstack -c -o [email protected] $(LD) $(LDFLAGS) [email protected] -o $@ -EXTRA_RUNS += run-test-rvv-ldst-ff-pmp run-test-rvv-ldst-us-pmp +EXTRA_RUNS += run-test-rvv-ldst-ff-pmp run-test-rvv-ldst-us-pmp \ + run-test-rvv-ldst-ff-page run-test-rvv-ldst-ff-pmp: test-rvv-ldst-ff-pmp $(call run-test, $<, $(QEMU) -cpu rv64$(comma)v=true$(comma)vlen=128$(comma)elen=64$(comma)vext_spec=v1.0$(comma)rvv_ta_all_1s=true$(comma)rvv_ma_all_1s=true $(QEMU_OPTS)$<) @@ -101,5 +103,8 @@ run-test-rvv-ldst-ff-pmp: test-rvv-ldst-ff-pmp run-test-rvv-ldst-us-pmp: test-rvv-ldst-us-pmp $(call run-test, $<, $(QEMU) -cpu rv64$(comma)v=true$(comma)vlen=128$(comma)elen=64$(comma)vext_spec=v1.0$(comma)rvv_ta_all_1s=true$(comma)rvv_ma_all_1s=true $(QEMU_OPTS)$<) +run-test-rvv-ldst-ff-page: test-rvv-ldst-ff-page + $(call run-test, $<, $(QEMU) -cpu rv64$(comma)v=true$(comma)vlen=128$(comma)elen=64$(comma)vext_spec=v1.0 $(QEMU_OPTS)$<) + # We don't currently support the multiarch system tests undefine MULTIARCH_TESTS diff --git a/tests/tcg/riscv64/test-rvv-ldst-ff-page.S b/tests/tcg/riscv64/test-rvv-ldst-ff-page.S new file mode 100644 index 00000000000..63b1e0ac8a8 --- /dev/null +++ b/tests/tcg/riscv64/test-rvv-ldst-ff-page.S @@ -0,0 +1,83 @@ +/* + * RISC-V vector fault-only-first probe page-crossing tests + * + * A first-element probe validates the mapping only for the bytes that + * the first (fault-only) element itself touches, then lets the + * remaining elements of the vector body fault normally. An + * implementation that instead probes the whole multi-element access + * range as one host operation aborts as soon as that range crosses a + * page boundary, even though every page involved is in fact mapped. + * + * Case 1 crosses the page boundary only in the vector body, after the + * first element. Case 2 crosses it inside the first element itself, + * so the first-element probe must span both pages it touches. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + #include "rvv-ldst.inc" + + .text + .global _start +_start: + RVV_ENABLE + lla t0, trap_handler + csrw mtvec, t0 + + /* + * Case 1: the body crosses the page boundary; the first element does not. + */ + CASE 1 + li t0, 3 + vsetvli t1, t0, e8, m1, tu, mu + lla a0, cross_segment + vlseg2e8ff.v v2, (a0) + csrr t0, vl + ASSERT_EQ t0, 3 + csrr t0, vstart + ASSERT_EQ t0, 0 + lla a0, output + vsseg2e8.v v2, (a0) + lbu t0, 5(a0) + ASSERT_EQ t0, 0x66 + + /* + * Case 2: the first segment element itself straddles the page boundary. + */ + CASE 2 + li t0, 3 + vsetvli t1, t0, e8, m1, tu, mu + lla a0, straddle_segment + vlseg2e8ff.v v2, (a0) + csrr t0, vl + ASSERT_EQ t0, 3 + csrr t0, vstart + ASSERT_EQ t0, 0 + lla a0, output + vsseg2e8.v v2, (a0) + lbu t0, 5(a0) + ASSERT_EQ t0, 0xf6 + li a0, 0 +exit: + SEMI_EXIT + FAIL + + /* + * No trap is expected: a spurious fault from the page-crossing probe + * is the very thing under test. Report the case number rather than + * vectoring to the reset value of mtvec and hanging until the + * harness timeout. + */ + .balign 4 +trap_handler: + j fail + + .data + .balign 16 +semiargs: .space 16 + .balign 4096 + .space 4094 +cross_segment: .byte 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 +output: .space 6 + .balign 4096 + .space 4095 +straddle_segment: .byte 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6 -- 2.43.0
