Skip to content

[risc-v][vector] Restore vstart after vector configuration - #11861

Open
PiyushPatle26 wants to merge 4 commits into
RT-Thread:masterfrom
PiyushPatle26:fix/riscv-rvv-vstart
Open

PiyushPatle26 wants to merge 4 commits into
RT-Thread:masterfrom
PiyushPatle26:fix/riscv-rvv-vstart

Conversation

@PiyushPatle26

@PiyushPatle26 PiyushPatle26 commented Oct 10, 2026 •

Copy link
Copy Markdown

拉取/合并请求描述:(PR description)

为什么提交这份PR (why to submit this PR)

RESTORE_VECTOR restores vstart before vsetvl, which resets the saved restart index to zero. Restore it after the final vector configuration instruction.

你的解决方案是什么 (what is your solution)

Move the vstart restore to the end of RESTORE_VECTOR, without changing the frame layout. Add a QEMU virt64 regression using the actual save/restore macros to check zero and nonzero vstart, vl, vtype, vcsr, all vector registers, and frame guards.

The regression and its probe live in applications/utest/, with conditional SCons integration and CI attachconfig variants for both VLENs. Each invocation owns its heap-backed frames, including its caller-state backup, so msh and UTest calls do not share mutable buffers. The test requires heap support. The probe uses explicit csrrci; assembler macro bodies are protected from C formatting.

请提供验证的bsp和config (provide the config and bsp)

  • BSP: bsp/qemu-virt64-riscv
  • .config: CONFIG_ENABLE_VECTOR=y, CONFIG_RT_USING_HEAP=y, CONFIG_FINSH_USING_MSH=y, SMP disabled, CONFIG_RT_USING_UTEST=y. Test CONFIG_ARCH_VECTOR_VLEN_128=y and CONFIG_ARCH_VECTOR_VLEN_256=y separately; run utest_run testcases.libcpu.rvv_vstart.
  • Toolchain: GCC 13.2.0 with CI Newlib 4.1.0 headers/RV64 lp64 libraries; QEMU 8.2.2. Validation-only compiler/library settings are described in the reproduction reply and are not included in this patch.
  • Validation: the revised regression fails with the original restore macro and passes with the fixed macro in the full BSP at both VLENs. All four strict builds pass. A fifth, vector-disabled build boots with v=false; the test is excluded. Concurrent msh/UTest execution and SMP have not been runtime-tested.
  • Reproduction commands and QEMU output: [risc-v][vector] Restore vstart after vector configuration #11861 (comment)
  • action: Previous vector-disabled build passed. Build for revised commit passed. These manual workflows compile the default configuration; vector-enabled runtime evidence is listed separately above.

当前拉取/合并请求的状态 Intent for your PR

必须选择一项 Choose one (Mandatory):

  • 本拉取/合并请求是一个草稿版本 This PR is for a code-review and is intended to get feedback
  • 本拉取/合并请求是一个成熟版本 This PR is mature, and ready to be integrated into the repo

代码质量 Code Quality:

我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:

  • 已经仔细查看过代码改动的对比 Already check the difference between PR and old code
  • 代码风格正确,包括缩进空格,命名及其他风格 Style guide is adhered to, including spacing, naming and other styles
  • 没有垃圾代码,代码尽量精简,不包含#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up
  • 所有变更均有原因及合理的,并且不会影响到其他软件组件代码或BSP All modifications are justified and not affect other components or BSP
  • 对难懂代码均提供对应的注释 I've commented appropriately where code is tricky
  • 代码是高质量的 Code in this PR is of high quality
  • 已经使用clang-format 源码格式化工具确保格式符合RT-Thread代码规范 This PR has been formatted with clang-format and complies with RT-Thread code specification
  • 如果是新增bsp, 已经添加ci检查到.github/ALL_BSP_COMPILE.json 详细请参考链接BSP自查

Latest validation: full Vector + heap + UTest builds and the focused UTest regression pass at both VLENs. The legacy testcase received a separate compilation fix; its runtime flow was not changed or executed.

RESTORE_VECTOR writes vstart before vsetvl, which resets the saved restart index to zero. Restore vstart after the final vector configuration instruction.

Add a QEMU virt64 regression using the actual save/restore macros. Check zero and nonzero vstart, vl, vtype, vcsr, all vector registers, and frame guards.

Validation: the original macro fails for nonzero vstart at VLEN=128 and VLEN=256. The fix passes the isolated probe and the RT-Thread shell regression at both VLENs. Strict BSP builds pass with vector support enabled and disabled; the disabled image boots with QEMU vector support off.
@CLAassistant

CLAassistant commented Oct 10, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@github-actions

Copy link
Copy Markdown

👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread!

为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。
To ensure your code complies with RT-Thread's coding style, please run the code formatting workflow by following the steps below (If the formatting of CI fails to run).


🛠 操作步骤 | Steps

  1. 前往 Actions 页面 | Go to the Actions page
    点击进入工作流 → | Click to open workflow →

  2. 点击 Run workflow | Click Run workflow

  • Use workflow from 保持默认分支(通常为 master)
    Keep the default branch (usually master) in Use workflow from
  • 在 branch 输入框填写 PR 分支 fix/riscv-rvv-vstart
    Enter PR branch fix/riscv-rvv-vstart in the branch field
  • 设置需排除的文件/目录(目录请以"/"结尾)
    Set files/directories to exclude (directories should end with "/")
  1. 等待工作流完成 | Wait for the workflow to complete
    格式化后的代码将作为独立提交推送至你的分支。
    The formatting changes will be pushed to your branch as a separate commit.

完成后,提交将自动更新至 fix/riscv-rvv-vstart 分支,关联的 Pull Request 也会同步更新。
Once completed, commits will be pushed to the fix/riscv-rvv-vstart branch automatically, and the related Pull Request will be updated.

如有问题欢迎联系我们,再次感谢您的贡献!💐
If you have any questions, feel free to reach out. Thanks again for your contribution!

@github-actions github-actions Bot added BSP Arch: RISC-V BSP related with risc-v libcpu labels Oct 10, 2026
@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

📌 Code Review Assignment

🏷️ Tag: libcpu_riscv

Reviewers: @Yaochenger

Changed Files (Click to expand)
  • libcpu/risc-v/vector/rvv-1.0/rvv_context.h

📊 Current Review Status (Last Updated: 2026-10-12 18:35 CST)


📝 Review Instructions

  1. 维护者可以通过单击此处来刷新审查状态: 🔄 刷新状态
    Maintainers can refresh the review status by clicking here: 🔄 Refresh Status

  2. 确认审核通过后评论 LGTM/lgtm
    Comment LGTM/lgtm after confirming approval

  3. PR合并前需至少一位维护者确认
    PR must be confirmed by at least one maintainer before merging

ℹ️ 刷新CI状态操作需要具备仓库写入权限。
ℹ️ Refresh CI status operation requires repository Write permission.

@PiyushPatle26

Copy link
Copy Markdown
Author

@Rbb666 @Yaochenger can you guys review the PR

@Rbb666
Rbb666 requested a balanced review from Copilot October 11, 2026 07:48
@Rbb666

Rbb666 commented Oct 11, 2026

Copy link
Copy Markdown
Member

@GuEe-GUI 大佬帮忙看看?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The assembly probe uses an invalid immediate operand with csrrc, preventing vector-enabled builds.

2 open findings
What changed in this PR

Corrects RVV context restoration so nonzero vstart survives vsetvl, with QEMU virt64 regression coverage. / 修复 RVV 上下文恢复顺序并添加回归测试。

Changes:

  • Restore vstart after vector configuration.
  • Add complete vector-frame and guard validation.
  • Conditionally build the assembly probe.
File Description
libcpu/​risc-v/​vector/​rvv-1.0/​rvv_context.h Reorders vstart restoration.
bsp/​qemu-virt64-riscv/​applications/​test/​SConscript Adds conditional probe compilation.
bsp/​qemu-virt64-riscv/​applications/​test/​rvv_vstart_tc.c Adds RVV regression tests.
bsp/​qemu-virt64-riscv/​applications/​test/​rvv_vstart_probe_gcc.S Exercises save/restore macros.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

.type rvv_vstart_probe, @function
rvv_vstart_probe:
/* Keep interrupts masked until the caller's complete state is restored. */
csrrc a3, sstatus, 2
LOAD t3, VEC_FRAME_VL(t1)
VEC_CONFIG_SET_VL_VTYPE(t3, t0)

/* vsetvl resets vstart, so restore the restart index last. */
@Rbb666

Rbb666 commented Oct 11, 2026

Copy link
Copy Markdown
Member

The title is suggested to be changed to: [risc-v][vector] Restore vstart after vector configuration.

@Rbb666

Rbb666 commented Oct 11, 2026

Copy link
Copy Markdown
Member

Reviewed commit 8f881393bed1a9d10bb6593f3bdac92130effe9d.

English: Moving the vstart restore after the final vsetvl is correct: vector configuration instructions reset vstart to zero. I recommend addressing the test concurrency issue below and supplementing the validation evidence before merging.

中文:将 vstart 放到最后一个 vsetvl 之后恢复是正确的,因为向量配置指令会将 vstart 清零。建议在合并前处理以下测试并发问题,并补充验证证据。

  1. [P2][Test concurrency / 测试并发] Serialize access to the shared frames / 对共享测试帧进行串行保护

    Location / 位置:rvv_vstart_tc.c:28–30.

    English: expected, observed, and saved are shared static buffers, while the test exposes both msh and UTest entry points. A background invocation such as utest_run -thread testcases.libcpu.rvv_vstart 1000 can overlap with rvv_vstart_test. The calls can overwrite each other's test frames. On SMP, they can also overwrite the caller-state backup in saved, causing RESTORE_VECTOR to restore another invocation's vector state. Disabling local interrupts inside the probe does not serialize access across CPUs or protect initialization and comparison outside the probe. Please protect the entire test with a mutex or use independent buffers for each invocation.

    中文:expected、observed 和 saved 是共享静态缓冲区,但测试同时提供 msh 和 UTest 入口。后台执行 utest_run -thread testcases.libcpu.rvv_vstart 1000 时,再执行 rvv_vstart_test,两次调用可能重叠并互相覆盖测试帧。在 SMP 上,还可能覆盖 saved 中保存的调用者状态,使 RESTORE_VECTOR 恢复另一调用的向量状态。探针内关闭本核中断不能串行保护跨核访问,也未保护探针外的初始化和比较。建议用互斥锁保护整个测试,或为每次调用使用独立缓冲区。

  2. [Validation / 验证] The linked CI does not exercise the enabled vector path / 已提供的 CI 未覆盖开启向量的路径

    English: The linked successful build shows # CONFIG_ENABLE_VECTOR is not set. It validates the disabled configuration but does not assemble the new probe or run this regression. Please attach reproducible vector-enabled build and QEMU output for both VLEN=128 and VLEN=256, including the toolchain version and QEMU command.

    中文:已提供的成功构建日志显示 # CONFIG_ENABLE_VECTOR is not set。它验证了关闭向量的配置,但未汇编新增探针,也未运行该回归测试。请补充 VLEN=128 和 VLEN=256 两种开启向量配置的构建及 QEMU 输出,并注明工具链版本和 QEMU 命令,便于复现。

  3. [Assembly clarification / 汇编说明] The immediate form of csrrc is accepted by GNU assembler / GNU 汇编器支持 csrrc 的立即数别名

    English: The existing review comment that csrrc a3, sstatus, 2 necessarily fails to assemble is not supported by GNU assembler's opcode table, which explicitly maps the immediate form of csrrc to CSRRCI. Writing csrrci a3, sstatus, 2 would make the intent clearer, but the current spelling is not a GNU assembly compilation defect.

    中文:已有评论认为 csrrc a3, sstatus, 2 必然无法汇编,但 GNU 汇编器的指令表明确将 csrrc 的立即数形式映射到 CSRRCI。改写为 csrrci a3, sstatus, 2 可以提高可读性,但当前写法并不是 GNU 汇编器下的编译缺陷。

  4. [Minor][PR title and commit subject / PR 标题及提交信息] Use the repository prefix format / 使用仓库要求的前缀格式

    English: Please update both the title and the single commit subject to [risc-v][vector] Restore vstart after vector configuration, following the repository's [module][subsystem] convention.

    中文:请按仓库的 [模块][子系统] 约定,将 PR 标题及唯一提交的信息改为 [risc-v][vector] Restore vstart after vector configuration。

  5. [CI formatting / CI 格式检查] Handle the assembly macro region appropriately / 对汇编宏区域进行适当处理

    English: The format check fails on the assembly macro region of rvv_context.h, including unchanged lines. Please resolve how that region is handled by clang-format; applying C formatting to the assembler macro bodies needs care.

    中文:格式检查在 rvv_context.h 的汇编宏区域失败,包括未修改的旧代码。需要处理 clang-format 对该区域的检查方式,谨慎对待汇编宏体的 C 格式化。

English: This review is based on source inspection, caller-path checks, specifications, and CI logs. I have not independently rerun the QEMU regression.

中文:本次审核基于源码、调用路径、规范和 CI 日志,未独立复跑 QEMU 回归测试。

@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

MemBrowse Memory Report

stm32f407-rt-spark

  • RAM1: .stack +4 B (+0.1%, 5,476 B / 131,072 B, total: 4% used)

stm32l475-atk-pandora-llvm

@PiyushPatle26 PiyushPatle26 changed the title risc-v: restore vstart after vector configuration [risc-v][vector] Restore vstart after vector configuration Oct 11, 2026
Address review feedback on the restore regression. Give each invocation its own heap-backed frames and release them on both success and comparison failure. Require heap support for the test.

Use the explicit csrrci instruction and protect assembler macro bodies from C formatting. Keep normal preprocessor declarations formatted.

Reproduced the nonzero-vstart failure with the original macro and verified the revised test in the full QEMU BSP at VLEN=128 and VLEN=256. The extension-disabled strict build and boot also pass. clang-format checks pass with versions 18 and 23.
@PiyushPatle26

PiyushPatle26 commented Oct 11, 2026 •

Copy link
Copy Markdown
Author

Thanks @Rbb666 for the review. I pushed the corrections in 36afba2823.

  • Each invocation now allocates its own three frames, including the caller-state backup. The test frees them on success and comparison failure and reports allocation failure. Its build guard now requires RT_USING_HEAP. There are no shared mutable test frames.
  • The probe uses explicit csrrci a3, sstatus, 2. This clarifies the intent; the original GNU assembler alias was not a compilation defect.
  • The assembler macro region is marked clang-format off/on. The C/preprocessor portion remains formatted. The repository formatter check passes locally with clang-format 23.1.3, and the two changed C/header files also pass version 18.
  • The PR title and follow-up commit use [risc-v][vector] Restore vstart after vector configuration. I retained the original published commit because the repository agent instructions prohibit history rewrites. The requested title can also be used for the eventual squash commit.

I reran the revised regression in the actual bsp/qemu-virt64-riscv image, not only the isolated probe:

Restore macro VLEN Strict BSP build RT-Thread shell result
Original upstream macro 128 Passed vstart expected=1 observed=0
Original upstream macro 256 Passed vstart expected=1 observed=0
Fixed macro 128 Passed vlenb=16, 9 control/register checks
Fixed macro 256 Passed vlenb=32, 9 control/register checks
Vector disabled N/A Passed Booted with v=false; test command and symbols absent

The original-macro runs used the revised test and probe, replacing only rvv_context.h in an isolated build copy with the header from 914dda7d0272c6ffedcdc590e423c93a54970caf.

Environment: GCC 13.2.0-11ubuntu1+12, QEMU 8.2.2, Newlib 4.1.0 headers and RV64 lp64 libraries from the RT-Thread CI toolchain archive. Single hart, SMP disabled, CONFIG_RT_USING_HEAP=y, CONFIG_FINSH_USING_MSH=y, CONFIG_ENABLE_VECTOR=y; VLEN=128 and 256 were selected separately. UTest was disabled in these runtime runs. I have not run concurrent msh/UTest invocations or SMP validation; the concurrency correction is independent storage per invocation, rather than a claim of SMP context-switch correctness.

Reproduction commands and temporary toolchain settings

The installed bare-metal GCC has no bundled libc. I used the following validation-only setup in an isolated checkout. These compiler/library changes are not part of the PR. This requires GCC 13.2, QEMU 8.2.2, Python, pip, curl, and tar already installed.

git clone --branch fix/riscv-rvv-vstart https://github.com/PiyushPatle26/rt-thread.git rvv-review
cd rvv-review
git checkout 36afba2823
export RVV_REPRO_ROOT="$PWD"
python3 -m pip install --target "$RVV_REPRO_ROOT/.validation/python" scons kconfiglib
export PYTHONPATH="$RVV_REPRO_ROOT/.validation/python"
export PKGS_DIR="$RVV_REPRO_ROOT/.validation/packages"
export RTT_EXEC_PATH=/usr/bin
mkdir -p "$PKGS_DIR" "$RVV_REPRO_ROOT/.validation/toolchain"
curl -fL https://github.com/RT-Thread/toolchains-ci/releases/download/v1.4/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz |
  tar -xz -C "$RVV_REPRO_ROOT/.validation/toolchain" --wildcards     '*/riscv64-unknown-elf/include/*' '*/riscv64-unknown-elf/lib/rv64imac/lp64/*'

python3 - <<'PYSETUP'
import os
from pathlib import Path
root = Path(os.environ['RVV_REPRO_ROOT'])
base = next((root / '.validation/toolchain').glob('*/riscv64-unknown-elf'))
p = root / 'bsp/qemu-virt64-riscv/rtconfig.py'
s = p.read_text().replace('-march=rv64imafdc', '-march=rv64imafdc_zicsr_zifencei')
s += f"\nCFLAGS += ' -isystem {base}/include'\nCXXFLAGS = CFLAGS\n"
s += f"LFLAGS += ' -L{base}/lib/rv64imac/lp64'\n"
s += "AFLAGS = AFLAGS.replace('rv64imafdc_zicsr_zifencei', 'rv64imafdcv_zicsr_zifencei')\n"
s += f"DEVICE += ' -isystem {base}/include'\n"
p.write_text(s)
PYSETUP

For each VLEN, edit .config using this helper, generate rtconfig.h, and build:

# Set RVV_VLEN=128 first, then repeat with 256.
export RVV_VLEN=128
python3 - <<'PYCONFIG'
import os
from pathlib import Path
p = Path('bsp/qemu-virt64-riscv/.config')
s = p.read_text().replace('# CONFIG_ENABLE_VECTOR is not set', 'CONFIG_ENABLE_VECTOR=y')
for n in (128, 256):
    key = f'CONFIG_ARCH_VECTOR_VLEN_{n}'
    enabled = os.environ['RVV_VLEN'] == str(n)
    s = s.replace(key + '=y', '# ' + key + ' is not set')
    if enabled:
        s = s.replace('# ' + key + ' is not set', key + '=y')
p.write_text(s)
PYCONFIG
python3 -m SCons --pyconfig-silent -C bsp/qemu-virt64-riscv
python3 -m SCons -j4 --strict -C bsp/qemu-virt64-riscv
qemu-system-riscv64 -machine virt   -cpu "rv64,v=true,vlen=$RVV_VLEN,vext_spec=v1.0"   -smp 1 -m 256M -nographic -kernel bsp/qemu-virt64-riscv/rtthread.bin

At the msh /> prompt, run rvv_vstart_test. To reproduce the defect with the same revised test, save the fixed header outside the source tree, replace it with git show 914dda7d0272c6ffedcdc590e423c93a54970caf:libcpu/risc-v/vector/rvv-1.0/rvv_context.h, rebuild, and rerun QEMU. Restore the fixed header afterward.

Captured shell output:

Original macro, VLEN=128 and VLEN=256:
msh />rvv_vstart_test
RVV restore failed: vstart expected=1 observed=0
rvv_vstart_test: command failed -255.

Fixed macro, VLEN=128:
msh />rvv_vstart_test
RVV restore passed: vlenb=16, 9 control/register checks

Fixed macro, VLEN=256:
msh />rvv_vstart_test
RVV restore passed: vlenb=32, 9 control/register checks

For the other CI failures, the Tools job ends with scons: command not found (log); the package test fails when pulling CMSIS device files because untracked files would be overwritten (log). Those failures occur in STM32/tooling paths outside this patch. I have left their configuration unchanged.

Also, could you please share guidance on the open scope and extension-use-policy questions in #11786? I would like to agree on the next FP correctness work before proposing lazy switching. The initial scope remains single-hart RISC-V.

Update: the fork BSP build for 36afba2823 passed. The new upstream workflows currently report action_required, including the format check. Could a maintainer please approve those workflow runs so the revised commit can be checked upstream?

@Rbb666 Rbb666 Oct 12, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is recommended to move the test and its assembly probe to a dedicated utest directory and enable conditional build integration. Add additional CI configuration to enable vector support, heap, and UTest for VLEN=128 and VLEN=256.

You can refer to the BSP of K230:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the guidance. I moved the regression and assembly probe to applications/utest/ with conditional build integration, and added CI configurations for VLEN=128 and 256.

Both vector-enabled builds and the new UTest regression pass locally. I also added a separate minimal commit fixing the legacy testcase’s compilation errors. Please review the updated commits.

Move the regression and assembly probe into a dedicated UTest directory. Build them only with Vector, heap, and UTest enabled, and use the UTest entry point.

Add strict CI attachconfig variants for VLEN=128 and VLEN=256. Enable V in assembler flags only for vector builds.

Both regression objects compile at both VLENs. The vector-disabled full UTest build passes. Vector-enabled full builds expose pre-existing failures in the legacy testcase, addressed separately.
Use sizeof(rt_ubase_t) for the vector frame size instead of the assembly-only REGBYTES macro. Provide test-only wrappers for the missing save/restore helpers, and enable vector instructions only for the legacy testcase compilation.

Keep the legacy testcase flow unchanged. Strict Vector + UTest builds pass at VLEN=128 and VLEN=256, and the new vstart regression passes through UTest at both VLENs. The vector-disabled full build passes with vector test symbols excluded. The legacy runtime testcase itself was not executed.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: RISC-V BSP related with risc-v BSP libcpu

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants