All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chao Liu <chao.liu@processmission.com>
To: Max Chou <max.chou@sifive.com>
Cc: qemu-devel@nongnu.org, qemu-riscv@nongnu.org,
	 richard.henderson@linaro.org,
	Palmer Dabbelt <palmer@dabbelt.com>,
	 Alistair Francis <alistair.francis@wdc.com>,
	Weiwei Li <liwei1518@gmail.com>,
	 Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>,
	Liu Zhiwei <zhiwei_liu@linux.alibaba.com>
Subject: Re: [PATCH 3/6] tests/tcg/riscv64: Add vector masked fault-only-first PMP test
Date: Fri, 11 Sep 2026 13:49:23 +0800	[thread overview]
Message-ID: <aqOSwMCX5UsGJA79@MacBook-Pro-4.local> (raw)
In-Reply-To: <20260909084154.223529-4-max.chou@sifive.com>

Hi Max,

On Wed, Sep 09, 2026 at 04:41:50PM +0800, Max Chou wrote:
> Add a bare-metal test for masked vector fault-only-first loads across
> locked NA4 PMP regions inside one page. The test covers masked-off
> elements, a faulting active element 0, and later active faults that
> shorten vl.
> 
> Signed-off-by: Max Chou <max.chou@sifive.com>
> ---
>  tests/tcg/riscv64/Makefile.softmmu-target |  13 ++
>  tests/tcg/riscv64/rvv-ldst.inc            |  91 ++++++++
>  tests/tcg/riscv64/test-rvv-ldst-ff-pmp.S  | 259 ++++++++++++++++++++++
>  3 files changed, 363 insertions(+)
>  create mode 100644 tests/tcg/riscv64/rvv-ldst.inc
>  create mode 100644 tests/tcg/riscv64/test-rvv-ldst-ff-pmp.S
> 
> diff --git a/tests/tcg/riscv64/Makefile.softmmu-target b/tests/tcg/riscv64/Makefile.softmmu-target
> index f2c75abd57a..0fdf242f735 100644
> --- a/tests/tcg/riscv64/Makefile.softmmu-target
> +++ b/tests/tcg/riscv64/Makefile.softmmu-target
> @@ -85,5 +85,18 @@ run-test-vle32ff: test-vle32ff
>  	$(call run-test, $<, $(QEMU) -cpu rv64$(comma)v=true $(QEMU_OPTS)$<)
>  test-vle32ff: CFLAGS += -march=rv64gcv
>  
> +RVV_LDST_MARCH = -march=rv64gcv
> +RVV_LDST_TESTS = test-rvv-ldst-ff-pmp
> +CLEANFILES += $(RVV_LDST_TESTS)
> +
> +$(RVV_LDST_TESTS): %: %.S rvv-ldst.inc $(LINK_SCRIPT)
> +	$(CC) $(CFLAGS) $(RVV_LDST_MARCH) $< -Wa,--noexecstack -c -o $@.o
> +	$(LD) $(LDFLAGS) $@.o -o $@
> +
> +EXTRA_RUNS += run-test-rvv-ldst-ff-pmp
> +
> +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)$<)
> +
Just a heads-up, TCG tests are moving to Meson build, so this needs to be
based on:

https://lore.kernel.org/qemu-devel/20260818192309.22169-1-pierrick.bouvier@oss.qualcomm.com/

Thanks,
Chao

>  # We don't currently support the multiarch system tests
>  undefine MULTIARCH_TESTS
> diff --git a/tests/tcg/riscv64/rvv-ldst.inc b/tests/tcg/riscv64/rvv-ldst.inc
> new file mode 100644
> index 00000000000..061f330abef
> --- /dev/null
> +++ b/tests/tcg/riscv64/rvv-ldst.inc
> @@ -0,0 +1,91 @@
> +/*
> + * Common support for bare-metal RVV load/store regressions
> + *
> + * Register contract: these macros use t0, t1, t5 and t6 as scratch and
> + * keep the current case number in s11.  ASSERT_EQ and CHECK_VELEM hold
> + * their expected value in t6 across a branch, so a trap handler that can
> + * run in between must leave t6 alone; use t5 and s5 for that instead.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +    .option    norelax
> +    .option    norvc
> +
> +    .macro          RVV_ENABLE
> +    li              t0, 0x6600
> +    csrs            mstatus, t0
> +    csrw            vcsr, zero
> +    .endm
> +
> +    .macro          ASSERT_EQ actual, expected
> +    li              t6, \expected
> +    bne             \actual, t6, fail
> +    .endm
> +
> +    .macro          CASE number
> +    li              s11, \number
> +    .endm
> +
> +    .macro          SEMI_EXIT
> +    lla             a1, semiargs
> +    li              t0, 0x20026
> +    sd              t0, 0(a1)
> +    sd              a0, 8(a1)
> +    li              a0, 0x20
> +    .balign         16
> +    slli            zero, zero, 0x1f
> +    ebreak
> +    srai            zero, zero, 0x7
> +    j    .
> +    .endm
> +
> +    .macro          FAIL
> +fail:
> +    mv              a0, s11
> +    bnez            a0, 1f
> +    li              a0, 1
> +1:
> +    j               exit
> +    .endm
> +
> +    /* Pre-fill selected registers with a sentinel neither data nor 1s. */
> +    .macro          PREFILL vd=, vl=4, sew=e32, value=0x05050505
> +    vsetivli        zero, \vl, \sew, m1, ta, ma
> +    li              t0, \value
> +    .ifb            \vd
> +    vmv.v.x         v2, t0
> +    vmv.v.x         v3, t0
> +    .else
> +    vmv.v.x         \vd, t0
> +    .endif
> +    .endm
> +
> +    /* Set the low mask bits of v0 to \val. */
> +    .macro          SET_MASK val
> +    vsetivli        zero, 1, e8, m1, ta, ma
> +    li              t0, \val
> +    vmv.s.x         v0, t0
> +    .endm
> +
> +    /* Assert element \idx of \vsrc (e32) equals \expected. */
> +    .macro          CHECK_VELEM vsrc, idx, expected
> +    vsetivli        zero, 4, e32, m1, ta, ma
> +    vslidedown.vi   v8, \vsrc, \idx
> +    vmv.x.s         t0, v8
> +    li              t6, \expected
> +    bne             t0, t6, fail
> +    .endm
> +
> +    /* Assert that no trap has been taken since the last check. */
> +    .macro          CHECK_NO_TRAP
> +    bne             s2, s4, fail
> +    .endm
> +
> +    /* Assert that exactly one expected trap has been taken. */
> +    .macro          CHECK_TRAP
> +    addi            s4, s4, 1
> +    bne             s2, s4, fail
> +    li              s0, 0
> +    li              s1, 0
> +    .endm
> diff --git a/tests/tcg/riscv64/test-rvv-ldst-ff-pmp.S b/tests/tcg/riscv64/test-rvv-ldst-ff-pmp.S
> new file mode 100644
> index 00000000000..80b48965625
> --- /dev/null
> +++ b/tests/tcg/riscv64/test-rvv-ldst-ff-pmp.S
> @@ -0,0 +1,259 @@
> +/*
> + * RISC-V vector masked fault-only-first with PMP tests
> + *
> + * PMP permissions may change at NA4 (4-byte) granularity inside one
> + * target page, matching one e32 element exactly. A masked-off body
> + * element performs no memory access, so a read-denied PMP region under
> + * a masked-off element must not fault.
> + *
> + * Runs with rvv_ta_all_1s=true and rvv_ma_all_1s=true so that with a
> + * "ta, ma" vtype every masked-off and tail element must read back as
> + * all-1s, distinct from the 0x05050505 sentinel and the loaded data.
> + *
> + * PMP layout (locked entries, lowest number wins; everything outside
> + * the test page is unmatched and so fully accessible from M-mode):
> + *   pmp0: NA4   buf_a+4,   L, ---   deny element 1 of buf_a
> + *   pmp1: NA4   buf_b+0,   L, ---   deny element 0 of buf_b
> + *   pmp2: NA4   buf_c+8,   L, ---   deny element 2 of buf_c
> + *   pmp3: NAPOT test page, L, R     lower-priority page allow
> + *
> + * 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
> +
> +    /*
> +     * Trap handler protocol:
> +     *   s0: expected mcause (0: no trap expected)
> +     *   s1: expected mtval (-1 accepts any value)
> +     *   s2: traps taken
> +     *   s3: vstart seen at last trap
> +     *   s4: traps expected
> +     *   s5: mtval seen at last trap
> +     */
> +    li      s0, 0
> +    li      s1, 0
> +    li      s2, 0
> +    li      s3, -1
> +    li      s4, 0
> +
> +    /* Program the locked PMP entries; single locking cfg write last. */
> +    lla     t0, buf_a + 4
> +    srli    t0, t0, 2
> +    csrw    pmpaddr0, t0
> +    lla     t0, buf_b
> +    srli    t0, t0, 2
> +    csrw    pmpaddr1, t0
> +    lla     t0, buf_c + 8
> +    srli    t0, t0, 2
> +    csrw    pmpaddr2, t0
> +    lla     t0, pmp_page
> +    srli    t0, t0, 2
> +    ori     t0, t0, 0x1ff
> +    csrw    pmpaddr3, t0
> +    li      t0, 0x99909090
> +    csrw    pmpcfg0, t0
> +
> +    /*
> +     * Case 1: sanity: the NA4 deny is in effect for a scalar load.
> +     */
> +    CASE    1
> +    li              s0, 5
> +    li              s1, -1
> +    lla             t1, buf_a
> +    lw              t0, 4(t1)
> +    CHECK_TRAP
> +
> +    /*
> +     * Case 2: denied bytes lie only under masked-off element 1: no trap.
> +     * QEMU retains vl at 3 for this successful access.
> +     */
> +    CASE    2
> +    PREFILL
> +    SET_MASK        0b101
> +    vsetivli        zero, 3, e32, m1, ta, ma
> +    lla             a0, buf_a
> +    vle32ff.v       v2, (a0), v0.t
> +    CHECK_NO_TRAP
> +    csrr            t0, vl
> +    ASSERT_EQ       t0, 3
> +    csrr            t0, vstart
> +    bnez            t0, fail
> +    CHECK_VELEM     v2, 0, 0x00aa0000
> +    CHECK_VELEM     v2, 1, -1
> +    CHECK_VELEM     v2, 2, 0x00aa0002
> +    CHECK_VELEM     v2, 3, -1
> +
> +    /*
> +     * Case 3: active element 0 denied: trap, vstart 0.
> +     */
> +    CASE    3
> +    PREFILL
> +    li              s0, 5
> +    li              s1, -1
> +    vsetivli        zero, 3, e32, m1, ta, ma
> +    lla             a0, buf_b
> +    vle32ff.v       v2, (a0)
> +    CHECK_TRAP
> +    bnez            s3, fail
> +
> +    /*
> +     * Case 4: masked-off element 0 over denied bytes: no trap.
> +     * retains vl at 3 and loads elements 1 and 2.
> +     */
> +    CASE    4
> +    PREFILL
> +    SET_MASK        0b110
> +    vsetivli        zero, 3, e32, m1, ta, ma
> +    lla             a0, buf_b
> +    vle32ff.v       v2, (a0), v0.t
> +    CHECK_NO_TRAP
> +    csrr            t0, vl
> +    ASSERT_EQ       t0, 3
> +    CHECK_VELEM     v2, 0, -1
> +    CHECK_VELEM     v2, 1, 0x00bb0001
> +    CHECK_VELEM     v2, 2, 0x00bb0002
> +    CHECK_VELEM     v2, 3, -1
> +
> +    /*
> +     * Case 5: active element 2 denied, unmasked: no trap, vl 2.
> +     */
> +    CASE    5
> +    PREFILL
> +    vsetivli        zero, 3, e32, m1, ta, ma
> +    lla             a0, buf_c
> +    vle32ff.v       v2, (a0)
> +    CHECK_NO_TRAP
> +    csrr            t0, vl
> +    ASSERT_EQ       t0, 2
> +    CHECK_VELEM     v2, 0, 0x00cc0000
> +    CHECK_VELEM     v2, 1, 0x00cc0001
> +    CHECK_VELEM     v2, 2, -1
> +    CHECK_VELEM     v2, 3, -1
> +
> +    /*
> +     * Case 6: masked-off element 0, active element 2 denied: vl 2.
> +     */
> +    CASE    6
> +    PREFILL
> +    SET_MASK        0b110
> +    vsetivli        zero, 3, e32, m1, ta, ma
> +    lla             a0, buf_c
> +    vle32ff.v       v2, (a0), v0.t
> +    CHECK_NO_TRAP
> +    csrr            t0, vl
> +    ASSERT_EQ       t0, 2
> +    CHECK_VELEM     v2, 0, -1
> +    CHECK_VELEM     v2, 1, 0x00cc0001
> +    CHECK_VELEM     v2, 2, -1
> +    CHECK_VELEM     v2, 3, -1
> +
> +    /*
> +     * Case 7: nf=2 segments, masked-off segment 0 covers the denied bytes at
> +     * buf_b: no trap. retains vl at 3 and loads segments 1 and 2.
> +     */
> +    CASE    7
> +    PREFILL
> +    SET_MASK        0b110
> +    vsetivli        zero, 3, e32, m1, ta, ma
> +    lla             a0, buf_b
> +    vlseg2e32ff.v   v2, (a0), v0.t
> +    CHECK_NO_TRAP
> +    csrr            t0, vl
> +    ASSERT_EQ       t0, 3
> +    CHECK_VELEM     v2, 0, -1
> +    CHECK_VELEM     v3, 0, -1
> +    CHECK_VELEM     v2, 1, 0x00bb0002
> +    CHECK_VELEM     v3, 1, 0x00bb0003
> +    CHECK_VELEM     v2, 2, 0x00bb0004
> +    CHECK_VELEM     v3, 2, 0x00bb0005
> +    CHECK_VELEM     v2, 3, -1
> +    CHECK_VELEM     v3, 3, -1
> +
> +    /*
> +     * Case 8: nf=2 segments, unmasked, field 0 of segment 1 denied
> +     * at buf_c+8: no trap, vl truncates to 1, segment 0 loaded.
> +     */
> +    CASE    8
> +    PREFILL
> +    vsetivli        zero, 3, e32, m1, ta, ma
> +    lla             a0, buf_c
> +    vlseg2e32ff.v   v2, (a0)
> +    CHECK_NO_TRAP
> +    csrr            t0, vl
> +    ASSERT_EQ       t0, 1
> +    CHECK_VELEM     v2, 0, 0x00cc0000
> +    CHECK_VELEM     v3, 0, 0x00cc0001
> +    CHECK_VELEM     v2, 1, -1
> +    CHECK_VELEM     v3, 1, -1
> +    CHECK_VELEM     v2, 2, -1
> +    CHECK_VELEM     v3, 2, -1
> +    CHECK_VELEM     v2, 3, -1
> +    CHECK_VELEM     v3, 3, -1
> +
> +    /*
> +     * Case 9: the denied masked-off element is the last element of the
> +     * accessed range, so a range probe cannot miss it as an interior
> +     * region: no trap. retains vl at 2.
> +     */
> +    CASE    9
> +    PREFILL
> +    SET_MASK        0b01
> +    vsetivli        zero, 2, e32, m1, ta, ma
> +    lla             a0, buf_a
> +    vle32ff.v       v2, (a0), v0.t
> +    CHECK_NO_TRAP
> +    csrr            t0, vl
> +    ASSERT_EQ       t0, 2
> +    CHECK_VELEM     v2, 0, 0x00aa0000
> +    CHECK_VELEM     v2, 1, -1
> +    CHECK_VELEM     v2, 2, -1
> +    CHECK_VELEM     v2, 3, -1
> +
> +    li    a0, 0
> +exit:
> +    SEMI_EXIT
> +    FAIL
> +
> +    .balign    4
> +trap_handler:
> +    csrr   t5, mcause
> +    bne    t5, s0, fail
> +    csrr   s5, mtval
> +    li     t5, -1
> +    beq    s1, t5, 1f
> +    bne    s5, s1, fail
> +1:
> +    csrr    s3, vstart
> +    addi    s2, s2, 1
> +    csrw    vstart, zero
> +    csrr    t5, mepc
> +    addi    t5, t5, 4
> +    csrw    mepc, t5
> +    mret
> +
> +    .data
> +    .balign    16
> +semiargs: .space 16
> +
> +    /* One dedicated page; the locked NAPOT entry grants R only. */
> +    .balign    4096
> +pmp_page:
> +buf_a:
> +    .word    0x00aa0000, 0x00aa0001, 0x00aa0002, 0x00aa0003
> +    .word    0x00aa0004, 0x00aa0005
> +    .skip    40
> +buf_b:
> +    .word    0x00bb0000, 0x00bb0001, 0x00bb0002, 0x00bb0003
> +    .word    0x00bb0004, 0x00bb0005
> +    .skip    40
> +buf_c:
> +    .word    0x00cc0000, 0x00cc0001, 0x00cc0002, 0x00cc0003
> +    .word    0x00cc0004, 0x00cc0005
> +    .skip    3944
> -- 
> 2.43.0
> 


  reply	other threads:[~2026-09-11  5:49 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-09  8:41 [PATCH 0/6] tests/tcg/riscv64: Add system mode rvv ld/st tests Max Chou
2026-09-09  8:41 ` [PATCH 1/6] target/riscv: Match PMP entries lying inside the checked range Max Chou
2026-09-09  8:41 ` [PATCH 2/6] target/riscv: rvv: Probe unit-stride accesses by the first element Max Chou
2026-09-09  8:41 ` [PATCH 3/6] tests/tcg/riscv64: Add vector masked fault-only-first PMP test Max Chou
2026-09-11  5:49   ` Chao Liu [this message]
2026-09-09  8:41 ` [PATCH 4/6] tests/tcg/riscv64: Add vector unit-stride " Max Chou
2026-09-09  8:41 ` [PATCH 5/6] tests/tcg/riscv64: Add vector fault-only-first page probe test Max Chou
2026-09-09  8:41 ` [PATCH 6/6] tests/tcg/riscv64: Add vector segment PMP region spanning test Max Chou

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aqOSwMCX5UsGJA79@MacBook-Pro-4.local \
    --to=chao.liu@processmission.com \
    --cc=alistair.francis@wdc.com \
    --cc=daniel.barboza@oss.qualcomm.com \
    --cc=liwei1518@gmail.com \
    --cc=max.chou@sifive.com \
    --cc=palmer@dabbelt.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-riscv@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=zhiwei_liu@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.