From 8f881393bed1a9d10bb6593f3bdac92130effe9d Mon Sep 17 00:00:00 2001 From: Piyush Patle Date: Sat, 10 Oct 2026 10:29:53 +0530 Subject: [PATCH 1/4] risc-v: restore vstart after vector configuration 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. --- .../applications/test/SConscript | 3 + .../applications/test/rvv_vstart_probe_gcc.S | 46 +++++++ .../applications/test/rvv_vstart_tc.c | 115 ++++++++++++++++++ libcpu/risc-v/vector/rvv-1.0/rvv_context.h | 6 +- 4 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 bsp/qemu-virt64-riscv/applications/test/rvv_vstart_probe_gcc.S create mode 100644 bsp/qemu-virt64-riscv/applications/test/rvv_vstart_tc.c diff --git a/bsp/qemu-virt64-riscv/applications/test/SConscript b/bsp/qemu-virt64-riscv/applications/test/SConscript index 2597249cbd92..33a4cd49fdca 100644 --- a/bsp/qemu-virt64-riscv/applications/test/SConscript +++ b/bsp/qemu-virt64-riscv/applications/test/SConscript @@ -4,6 +4,9 @@ cwd = GetCurrentDir() src = Glob('*.c') + Glob('*.cpp') CPPPATH = [cwd] +if GetDepend('ENABLE_VECTOR') and (GetDepend('RT_USING_UTEST') or GetDepend('FINSH_USING_MSH')): + src += ['rvv_vstart_probe_gcc.S'] + group = DefineGroup('Testcase', src, depend = [''], CPPPATH = CPPPATH) list = os.listdir(cwd) diff --git a/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_probe_gcc.S b/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_probe_gcc.S new file mode 100644 index 000000000000..1868a8504b09 --- /dev/null +++ b/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_probe_gcc.S @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-10-10 Piyush Patle Add RVV restore regression probe + */ + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif +#define REGBYTES 8 +#define STORE sd +#define LOAD ld + +#include +#include "vector_encoding.h" +#include "rvv_context.h" + + .text + .align 2 + .option push + .option arch, +v + + /* a0: expected frame, a1: observed frame, a2: caller's vector frame. */ + .globl rvv_vstart_probe + .type rvv_vstart_probe, @function +rvv_vstart_probe: + /* Keep interrupts masked until the caller's complete state is restored. */ + csrrc a3, sstatus, 2 + li t0, SSTATUS_VS + csrs sstatus, t0 + SAVE_VECTOR a2 + + RESTORE_VECTOR a0 + /* SAVE_VECTOR records vstart before issuing any vector instruction. */ + SAVE_VECTOR a1 + + RESTORE_VECTOR a2 + csrw sstatus, a3 + ret + .size rvv_vstart_probe, . - rvv_vstart_probe + + .option pop diff --git a/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_tc.c b/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_tc.c new file mode 100644 index 000000000000..3ae1d2d5f43d --- /dev/null +++ b/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_tc.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2026-10-10 Piyush Patle Test zero and nonzero RVV restart indices + */ + +#include + +/* Run rvv_vstart_test in msh, or testcases.libcpu.rvv_vstart with UTest. */ +#if defined(ENABLE_VECTOR) && (defined(RT_USING_UTEST) || defined(FINSH_USING_MSH)) +#include "rvv_context.h" + +/* RV64 vector frames contain four control words followed by v0 through v31. */ +#define VECTOR_CONTROL_WORDS 4 +#define VECTOR_GUARD 0x5a5a5a5aUL + +struct vector_test_frame +{ + rt_ubase_t before[2]; + rt_ubase_t image[CTX_VECTOR_REG_NR]; + rt_ubase_t after[2]; +}; + +static struct vector_test_frame expected; +static struct vector_test_frame observed; +static struct vector_test_frame saved; + +void rvv_vstart_probe(const rt_ubase_t *input, rt_ubase_t *output, rt_ubase_t *backup); + +static void frame_init(struct vector_test_frame *frame) +{ + rt_memset(frame, 0, sizeof(*frame)); + frame->before[0] = frame->before[1] = VECTOR_GUARD; + frame->after[0] = frame->after[1] = VECTOR_GUARD; +} + +static rt_bool_t frame_guards_valid(const struct vector_test_frame *frame) +{ + return frame->before[0] == VECTOR_GUARD && frame->before[1] == VECTOR_GUARD && + frame->after[0] == VECTOR_GUARD && frame->after[1] == VECTOR_GUARD; +} + +static int rvv_vstart_test(void) +{ + rt_ubase_t vlenb; + rt_ubase_t starts[3]; + rt_uint8_t *payload = (rt_uint8_t *)&expected.image[VECTOR_CONTROL_WORDS]; + rt_size_t payload_size = sizeof(expected.image) - VECTOR_CONTROL_WORDS * sizeof(rt_ubase_t); + rt_size_t i; + rt_size_t j; + + __asm__ volatile("csrr %0, vlenb" : "=r"(vlenb)); + if (payload_size != 32 * vlenb) + { + rt_kprintf("RVV test: configured frame does not match vlenb=%lu\n", vlenb); + return -RT_ERROR; + } + + frame_init(&expected); + for (i = 0; i < payload_size; i++) + { + payload[i] = (rt_uint8_t)(i * 37 + i / vlenb + 0x5a); + } + + starts[0] = 0; + starts[1] = 1; + starts[2] = vlenb - 1; + + for (i = 0; i < sizeof(starts) / sizeof(starts[0]); i++) + { + for (j = 0; j < 3; j++) + { + expected.image[0] = starts[i]; + expected.image[1] = 0; /* e8, m1, tail/mask undisturbed */ + expected.image[2] = vlenb; + expected.image[3] = j * 3; /* Exercise vxrm and vxsat through vcsr. */ + frame_init(&observed); + frame_init(&saved); + + rvv_vstart_probe(expected.image, observed.image, saved.image); + + if (!frame_guards_valid(&expected) || !frame_guards_valid(&observed) || + !frame_guards_valid(&saved) || + rt_memcmp(expected.image, observed.image, sizeof(expected.image)) != 0) + { + rt_kprintf("RVV restore failed: vstart expected=%lu observed=%lu\n", + starts[i], observed.image[0]); + return -RT_ERROR; + } + } + } + + rt_kprintf("RVV restore passed: vlenb=%lu, 9 control/register checks\n", vlenb); + return RT_EOK; +} + +#ifdef FINSH_USING_MSH +MSH_CMD_EXPORT(rvv_vstart_test, Test RVV restart index and complete frame restoration); +#endif + +#ifdef RT_USING_UTEST +#include + +static void testcase(void) +{ + uassert_int_equal(rvv_vstart_test(), RT_EOK); +} + +UTEST_TC_EXPORT(testcase, "testcases.libcpu.rvv_vstart", RT_NULL, RT_NULL, 10); +#endif +#endif diff --git a/libcpu/risc-v/vector/rvv-1.0/rvv_context.h b/libcpu/risc-v/vector/rvv-1.0/rvv_context.h index 4466b3aeff1d..e6e876ae52e0 100644 --- a/libcpu/risc-v/vector/rvv-1.0/rvv_context.h +++ b/libcpu/risc-v/vector/rvv-1.0/rvv_context.h @@ -97,14 +97,16 @@ mv t1, t0 - LOAD t0, VEC_FRAME_VSTART(t1) - csrw vstart, t0 LOAD t0, VEC_FRAME_VCSR(t1) csrw vcsr, t0 LOAD t0, VEC_FRAME_VTYPE(t1) LOAD t3, VEC_FRAME_VL(t1) VEC_CONFIG_SET_VL_VTYPE(t3, t0) + + /* vsetvl resets vstart, so restore the restart index last. */ + LOAD t0, VEC_FRAME_VSTART(t1) + csrw vstart, t0 .endm #endif From 36afba28233037335c2fc5b40d64a190801bdd16 Mon Sep 17 00:00:00 2001 From: Piyush Patle Date: Sun, 11 Oct 2026 14:42:04 +0530 Subject: [PATCH 2/4] [risc-v][vector] Restore vstart after vector configuration 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. --- .../applications/test/SConscript | 2 +- .../applications/test/rvv_vstart_probe_gcc.S | 2 +- .../applications/test/rvv_vstart_tc.c | 54 +++++++++++-------- libcpu/risc-v/vector/rvv-1.0/rvv_context.h | 10 ++-- 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/bsp/qemu-virt64-riscv/applications/test/SConscript b/bsp/qemu-virt64-riscv/applications/test/SConscript index 33a4cd49fdca..3d1a78352465 100644 --- a/bsp/qemu-virt64-riscv/applications/test/SConscript +++ b/bsp/qemu-virt64-riscv/applications/test/SConscript @@ -4,7 +4,7 @@ cwd = GetCurrentDir() src = Glob('*.c') + Glob('*.cpp') CPPPATH = [cwd] -if GetDepend('ENABLE_VECTOR') and (GetDepend('RT_USING_UTEST') or GetDepend('FINSH_USING_MSH')): +if GetDepend('ENABLE_VECTOR') and GetDepend('RT_USING_HEAP') and (GetDepend('RT_USING_UTEST') or GetDepend('FINSH_USING_MSH')): src += ['rvv_vstart_probe_gcc.S'] group = DefineGroup('Testcase', src, depend = [''], CPPPATH = CPPPATH) diff --git a/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_probe_gcc.S b/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_probe_gcc.S index 1868a8504b09..e02cbaf393d4 100644 --- a/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_probe_gcc.S +++ b/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_probe_gcc.S @@ -29,7 +29,7 @@ .type rvv_vstart_probe, @function rvv_vstart_probe: /* Keep interrupts masked until the caller's complete state is restored. */ - csrrc a3, sstatus, 2 + csrrci a3, sstatus, 2 li t0, SSTATUS_VS csrs sstatus, t0 SAVE_VECTOR a2 diff --git a/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_tc.c b/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_tc.c index 3ae1d2d5f43d..69d007933206 100644 --- a/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_tc.c +++ b/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_tc.c @@ -11,7 +11,7 @@ #include /* Run rvv_vstart_test in msh, or testcases.libcpu.rvv_vstart with UTest. */ -#if defined(ENABLE_VECTOR) && (defined(RT_USING_UTEST) || defined(FINSH_USING_MSH)) +#if defined(ENABLE_VECTOR) && defined(RT_USING_HEAP) && (defined(RT_USING_UTEST) || defined(FINSH_USING_MSH)) #include "rvv_context.h" /* RV64 vector frames contain four control words followed by v0 through v31. */ @@ -25,10 +25,6 @@ struct vector_test_frame rt_ubase_t after[2]; }; -static struct vector_test_frame expected; -static struct vector_test_frame observed; -static struct vector_test_frame saved; - void rvv_vstart_probe(const rt_ubase_t *input, rt_ubase_t *output, rt_ubase_t *backup); static void frame_init(struct vector_test_frame *frame) @@ -48,8 +44,12 @@ static int rvv_vstart_test(void) { rt_ubase_t vlenb; rt_ubase_t starts[3]; - rt_uint8_t *payload = (rt_uint8_t *)&expected.image[VECTOR_CONTROL_WORDS]; - rt_size_t payload_size = sizeof(expected.image) - VECTOR_CONTROL_WORDS * sizeof(rt_ubase_t); + struct vector_test_frame *frames; + struct vector_test_frame *expected; + struct vector_test_frame *observed; + struct vector_test_frame *saved; + rt_uint8_t *payload; + rt_size_t payload_size = sizeof(expected->image) - VECTOR_CONTROL_WORDS * sizeof(rt_ubase_t); rt_size_t i; rt_size_t j; @@ -60,7 +60,17 @@ static int rvv_vstart_test(void) return -RT_ERROR; } - frame_init(&expected); + /* Each invocation owns its frames, including the caller-state backup. */ + frames = rt_malloc(3 * sizeof(*frames)); + if (frames == RT_NULL) + { + return -RT_ENOMEM; + } + expected = &frames[0]; + observed = &frames[1]; + saved = &frames[2]; + payload = (rt_uint8_t *)&expected->image[VECTOR_CONTROL_WORDS]; + frame_init(expected); for (i = 0; i < payload_size; i++) { payload[i] = (rt_uint8_t)(i * 37 + i / vlenb + 0x5a); @@ -74,26 +84,28 @@ static int rvv_vstart_test(void) { for (j = 0; j < 3; j++) { - expected.image[0] = starts[i]; - expected.image[1] = 0; /* e8, m1, tail/mask undisturbed */ - expected.image[2] = vlenb; - expected.image[3] = j * 3; /* Exercise vxrm and vxsat through vcsr. */ - frame_init(&observed); - frame_init(&saved); - - rvv_vstart_probe(expected.image, observed.image, saved.image); - - if (!frame_guards_valid(&expected) || !frame_guards_valid(&observed) || - !frame_guards_valid(&saved) || - rt_memcmp(expected.image, observed.image, sizeof(expected.image)) != 0) + expected->image[0] = starts[i]; + expected->image[1] = 0; /* e8, m1, tail/mask undisturbed */ + expected->image[2] = vlenb; + expected->image[3] = j * 3; /* Exercise vxrm and vxsat through vcsr. */ + frame_init(observed); + frame_init(saved); + + rvv_vstart_probe(expected->image, observed->image, saved->image); + + if (!frame_guards_valid(expected) || !frame_guards_valid(observed) || + !frame_guards_valid(saved) || + rt_memcmp(expected->image, observed->image, sizeof(expected->image)) != 0) { rt_kprintf("RVV restore failed: vstart expected=%lu observed=%lu\n", - starts[i], observed.image[0]); + starts[i], observed->image[0]); + rt_free(frames); return -RT_ERROR; } } } + rt_free(frames); rt_kprintf("RVV restore passed: vlenb=%lu, 9 control/register checks\n", vlenb); return RT_EOK; } diff --git a/libcpu/risc-v/vector/rvv-1.0/rvv_context.h b/libcpu/risc-v/vector/rvv-1.0/rvv_context.h index e6e876ae52e0..f5ec4d4ae8d3 100644 --- a/libcpu/risc-v/vector/rvv-1.0/rvv_context.h +++ b/libcpu/risc-v/vector/rvv-1.0/rvv_context.h @@ -12,17 +12,20 @@ #define __RVV_CONTEXT_1_0_H__ #if defined(ARCH_VECTOR_VLEN_128) - #define CTX_VECTOR_REGS 64 +#define CTX_VECTOR_REGS 64 #elif defined(ARCH_VECTOR_VLEN_256) - #define CTX_VECTOR_REGS 128 +#define CTX_VECTOR_REGS 128 #else #error "No supported VLEN" #endif /* VLEN */ -#define CTX_VECTOR_REG_NR (CTX_VECTOR_REGS + 4) +#define CTX_VECTOR_REG_NR (CTX_VECTOR_REGS + 4) #ifdef __ASSEMBLY__ +/* The following macros contain assembler, not C. */ +/* clang-format off */ + /** * ================================== * VECTOR EXTENSION @@ -109,6 +112,7 @@ csrw vstart, t0 .endm +/* clang-format on */ #endif #endif /* __RVV_CONTEXT_H__ */ From 8f376ff2638d543450c9b046125b42d88fc4c9bc Mon Sep 17 00:00:00 2001 From: Piyush Patle Date: Mon, 12 Oct 2026 15:56:14 +0530 Subject: [PATCH 3/4] [risc-v][utest] Integrate RVV restore regression and CI variants 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. --- .../.ci/attachconfig/ci.attachconfig.yml | 20 +++++++++++++++++++ bsp/qemu-virt64-riscv/SConstruct | 3 +++ .../applications/test/SConscript | 3 --- .../applications/utest/SConscript | 10 ++++++++++ .../{test => utest}/rvv_vstart_probe_gcc.S | 0 .../{test => utest}/rvv_vstart_tc.c | 10 ++-------- 6 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 bsp/qemu-virt64-riscv/.ci/attachconfig/ci.attachconfig.yml create mode 100644 bsp/qemu-virt64-riscv/applications/utest/SConscript rename bsp/qemu-virt64-riscv/applications/{test => utest}/rvv_vstart_probe_gcc.S (100%) rename bsp/qemu-virt64-riscv/applications/{test => utest}/rvv_vstart_tc.c (91%) diff --git a/bsp/qemu-virt64-riscv/.ci/attachconfig/ci.attachconfig.yml b/bsp/qemu-virt64-riscv/.ci/attachconfig/ci.attachconfig.yml new file mode 100644 index 000000000000..9385b3498fa6 --- /dev/null +++ b/bsp/qemu-virt64-riscv/.ci/attachconfig/ci.attachconfig.yml @@ -0,0 +1,20 @@ +utest.rvv.vlen128: + scons_arg: + - '--strict' + kconfig: + - CONFIG_ENABLE_VECTOR=y + - CONFIG_RT_USING_HEAP=y + - CONFIG_RT_USING_UTEST=y + - CONFIG_ARCH_VECTOR_VLEN_128=y + - CONFIG_ARCH_VECTOR_VLEN_256=n + - CONFIG_RT_USING_SMP=n +utest.rvv.vlen256: + scons_arg: + - '--strict' + kconfig: + - CONFIG_ENABLE_VECTOR=y + - CONFIG_RT_USING_HEAP=y + - CONFIG_RT_USING_UTEST=y + - CONFIG_ARCH_VECTOR_VLEN_128=n + - CONFIG_ARCH_VECTOR_VLEN_256=y + - CONFIG_RT_USING_SMP=n diff --git a/bsp/qemu-virt64-riscv/SConstruct b/bsp/qemu-virt64-riscv/SConstruct index ae0e3375e111..06d2a468df75 100644 --- a/bsp/qemu-virt64-riscv/SConstruct +++ b/bsp/qemu-virt64-riscv/SConstruct @@ -27,6 +27,9 @@ rtconfig.ARCH='risc-v' # prepare building environment objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False) +if GetDepend('ENABLE_VECTOR'): + env['ASFLAGS'] = str(env['ASFLAGS']).replace('-march=rv64imafdc ', '-march=rv64imafdcv ') + stack_size = 4096 if GetDepend('RT_USING_SMART'): diff --git a/bsp/qemu-virt64-riscv/applications/test/SConscript b/bsp/qemu-virt64-riscv/applications/test/SConscript index 3d1a78352465..2597249cbd92 100644 --- a/bsp/qemu-virt64-riscv/applications/test/SConscript +++ b/bsp/qemu-virt64-riscv/applications/test/SConscript @@ -4,9 +4,6 @@ cwd = GetCurrentDir() src = Glob('*.c') + Glob('*.cpp') CPPPATH = [cwd] -if GetDepend('ENABLE_VECTOR') and GetDepend('RT_USING_HEAP') and (GetDepend('RT_USING_UTEST') or GetDepend('FINSH_USING_MSH')): - src += ['rvv_vstart_probe_gcc.S'] - group = DefineGroup('Testcase', src, depend = [''], CPPPATH = CPPPATH) list = os.listdir(cwd) diff --git a/bsp/qemu-virt64-riscv/applications/utest/SConscript b/bsp/qemu-virt64-riscv/applications/utest/SConscript new file mode 100644 index 000000000000..8e56d71ed7bc --- /dev/null +++ b/bsp/qemu-virt64-riscv/applications/utest/SConscript @@ -0,0 +1,10 @@ +from building import * + +cwd = GetCurrentDir() +src = ['rvv_vstart_tc.c', 'rvv_vstart_probe_gcc.S'] + +group = DefineGroup('RVV utestcases', src, + depend = ['RT_USING_UTEST', 'ENABLE_VECTOR', 'RT_USING_HEAP'], + CPPPATH = [cwd]) + +Return('group') diff --git a/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_probe_gcc.S b/bsp/qemu-virt64-riscv/applications/utest/rvv_vstart_probe_gcc.S similarity index 100% rename from bsp/qemu-virt64-riscv/applications/test/rvv_vstart_probe_gcc.S rename to bsp/qemu-virt64-riscv/applications/utest/rvv_vstart_probe_gcc.S diff --git a/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_tc.c b/bsp/qemu-virt64-riscv/applications/utest/rvv_vstart_tc.c similarity index 91% rename from bsp/qemu-virt64-riscv/applications/test/rvv_vstart_tc.c rename to bsp/qemu-virt64-riscv/applications/utest/rvv_vstart_tc.c index 69d007933206..13776447184e 100644 --- a/bsp/qemu-virt64-riscv/applications/test/rvv_vstart_tc.c +++ b/bsp/qemu-virt64-riscv/applications/utest/rvv_vstart_tc.c @@ -10,8 +10,8 @@ #include -/* Run rvv_vstart_test in msh, or testcases.libcpu.rvv_vstart with UTest. */ -#if defined(ENABLE_VECTOR) && defined(RT_USING_HEAP) && (defined(RT_USING_UTEST) || defined(FINSH_USING_MSH)) +/* Run with: utest_run testcases.libcpu.rvv_vstart */ +#if defined(ENABLE_VECTOR) && defined(RT_USING_HEAP) && defined(RT_USING_UTEST) #include "rvv_context.h" /* RV64 vector frames contain four control words followed by v0 through v31. */ @@ -110,11 +110,6 @@ static int rvv_vstart_test(void) return RT_EOK; } -#ifdef FINSH_USING_MSH -MSH_CMD_EXPORT(rvv_vstart_test, Test RVV restart index and complete frame restoration); -#endif - -#ifdef RT_USING_UTEST #include static void testcase(void) @@ -124,4 +119,3 @@ static void testcase(void) UTEST_TC_EXPORT(testcase, "testcases.libcpu.rvv_vstart", RT_NULL, RT_NULL, 10); #endif -#endif From 73e4f97532be21d2227c9fc903a153c649a50098 Mon Sep 17 00:00:00 2001 From: Piyush Patle Date: Mon, 12 Oct 2026 16:05:03 +0530 Subject: [PATCH 4/4] [risc-v][utest] Fix legacy vector testcase build 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. --- .../applications/test/test_vector/SConscript | 7 ++- .../test/test_vector/test_vector.c | 4 +- .../test/test_vector/vector_context_gcc.S | 43 +++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 bsp/qemu-virt64-riscv/applications/test/test_vector/vector_context_gcc.S diff --git a/bsp/qemu-virt64-riscv/applications/test/test_vector/SConscript b/bsp/qemu-virt64-riscv/applications/test/test_vector/SConscript index 0827b048b281..0a287adadb21 100644 --- a/bsp/qemu-virt64-riscv/applications/test/test_vector/SConscript +++ b/bsp/qemu-virt64-riscv/applications/test/test_vector/SConscript @@ -3,7 +3,12 @@ from building import * cwd = GetCurrentDir() src = Glob('*.c') + Glob('*.cpp') CPPPATH = [cwd] +LOCAL_CCFLAGS = '' -group = DefineGroup('Vector', src, depend = [''], CPPPATH = CPPPATH) +if GetDepend(['RT_USING_UTEST', 'ENABLE_VECTOR']): + src += ['vector_context_gcc.S'] + LOCAL_CCFLAGS = ' -march=rv64gcv' + +group = DefineGroup('Vector', src, depend = [''], CPPPATH = CPPPATH, LOCAL_CCFLAGS = LOCAL_CCFLAGS) Return('group') diff --git a/bsp/qemu-virt64-riscv/applications/test/test_vector/test_vector.c b/bsp/qemu-virt64-riscv/applications/test/test_vector/test_vector.c index 50aae8024803..b84e1c42b302 100644 --- a/bsp/qemu-virt64-riscv/applications/test/test_vector/test_vector.c +++ b/bsp/qemu-virt64-riscv/applications/test/test_vector/test_vector.c @@ -55,8 +55,8 @@ static void test_feature(void) * not modified by each other * ============================================================== */ -#define TEST_THREAD 2 -#define VECTOR_CTX_BYTES (CTX_VECTOR_REG_NR * REGBYTES) +#define TEST_THREAD 2 +#define VECTOR_CTX_BYTES (CTX_VECTOR_REG_NR * sizeof(rt_ubase_t)) void *ctx_vector[TEST_THREAD * 2]; static rt_sem_t sem; diff --git a/bsp/qemu-virt64-riscv/applications/test/test_vector/vector_context_gcc.S b/bsp/qemu-virt64-riscv/applications/test/test_vector/vector_context_gcc.S new file mode 100644 index 000000000000..42e60f323df1 --- /dev/null +++ b/bsp/qemu-virt64-riscv/applications/test/test_vector/vector_context_gcc.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2006-2026, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif +#define REGBYTES 8 +#define STORE sd +#define LOAD ld + +#include +#include "vector_encoding.h" +#include "rvv_context.h" + + .text + .align 2 + + /* Test-only helpers; SAVE_VECTOR must not change the caller's controls. */ + .globl rt_hw_vector_ctx_save + .type rt_hw_vector_ctx_save, @function +rt_hw_vector_ctx_save: + csrrci a3, sstatus, 2 + li t0, SSTATUS_VS + csrs sstatus, t0 + SAVE_VECTOR a0 + RESTORE_VECTOR a0 + csrw sstatus, a3 + ret + .size rt_hw_vector_ctx_save, . - rt_hw_vector_ctx_save + + .globl rt_hw_vector_ctx_restore + .type rt_hw_vector_ctx_restore, @function +rt_hw_vector_ctx_restore: + csrrci a3, sstatus, 2 + li t0, SSTATUS_VS + csrs sstatus, t0 + RESTORE_VECTOR a0 + csrw sstatus, a3 + ret + .size rt_hw_vector_ctx_restore, . - rt_hw_vector_ctx_restore