diff --git a/docs/coding/writing_tests.md b/docs/coding/writing_tests.md index 1e30cbf47..fc5a504c9 100644 --- a/docs/coding/writing_tests.md +++ b/docs/coding/writing_tests.md @@ -646,10 +646,19 @@ instead of assuming one tier: - **Probe via the framework layer**: `#include ` and call `arm64_require_sve_vl(test, min_bits, max_bits)` / - `arm64_require_sme_svl(...)` from `test_init`; a negative return - (EXIT_SKIP, -255 — the unified require contract) means the helper - already logged the skip — `return EXIT_SKIP` immediately (consume - with `< 0`, never `== -1` / `== EXIT_SKIP`). Do +<<<<<<< HEAD + `arm64_require_sme_svl(...)` from `test_init`; on skip the helper + already logged the reason and returns `EXIT_SKIP` (a negative value, + −255 — the unified require contract, never a bare −1: any other + negative would surface as a misleading "Unexpected OS error") — + `return EXIT_SKIP` immediately (consume with `< 0`, never `== -1` + / `== EXIT_SKIP`). Do +======= + `arm64_require_sme_svl(...)` from `test_init`; on skip the helper + returns `EXIT_SKIP` (a negative value, −255 — not a bare −1: any other + negative would surface as a misleading "Unexpected OS error") after + logging the reason — `return EXIT_SKIP` immediately. Do +>>>>>>> 52c2d755 (docs(coding): writing_tests.md all-VL 政策返回值措辞修正——EXIT_SKIP 而非 -1 (PR #288 检视 round 2)) not hand-write getauxval probes: `device_has_feature()` is short-circuited by compile-time `__ARM_FEATURE_*` macros in +sve/+sme TUs (docs/architecture.md). diff --git a/docs/research/progress-log.md b/docs/research/progress-log.md index 714cecc93..18624e915 100644 --- a/docs/research/progress-log.md +++ b/docs/research/progress-log.md @@ -714,14 +714,6 @@ M4 未尽项(假通过清单 ARM64 重推导、耗时尾部基线)在 v5 §1 - **验证模式**: 16-run 与 20-commit 实施均由隔离 subagent 执行; 每文件 TU 零告警+skip 干净(框架编译特性门)+终态全量构建零告警+zstd19 pass。 - **诚实边界**: verify.cpp 的 5200 向量 OpenSSL 重验需 SVE 硬件(本机 -<<<<<<< HEAD - 仅编译验证, commit 正文记录); hmac 容量守卫的 init 侧失败类别已由 - 20f73730 修正(compute_golden 经返回值传播, test_init 返回 - EXIT_FAILURE → 干净 Failed, 非 Skipped)——本条曾按旧形态记账, 评审 - 二轮勘误同步。 -- **承接**:P5(sleef/eigen×8)Eigen 侧已裁自 pin 回退(spike 证据: VLA - 语言级不可编译); sleef 半侧待 spike; P6 存量迁移(含本阶段 6 个 - 遗留手探文件)待做。 ## 2026-10-25(PR #280 检视处置 R2:rebase 契约统一 + asm 加固 + FNV 重锚) - **rebase 到 main(#277 已并入)**:11 条当前 head 意见中 6 条 @@ -783,19 +775,30 @@ M4 未尽项(假通过清单 ARM64 重推导、耗时尾部基线)在 v5 §1 完整 sdcshield 二进制(fork+96 线程+OpenSSL)不可入 gem5 SE 单进程 配置; 胶水依赖的算术不变式(lanes 换算 svl/4==svcntw()、[4,32]/ [2,16] 范围、漂移比较操作数)已由同源 harness 逐档执行。 -======= + 仅编译验证, commit 正文记录); hmac 容量守卫的 init 侧失败类别已由 + 20f73730 修正(compute_golden 经返回值传播, test_init 返回 + EXIT_FAILURE → 干净 Failed, 非 Skipped)——本条曾按旧形态记账, 评审 + 二轮勘误同步。 +- **承接**:P5(sleef/eigen×8)Eigen 侧已裁自 pin 回退(spike 证据: VLA + 语言级不可编译); sleef 半侧待 spike; P6 存量迁移(含本阶段 6 个 + 遗留手探文件)待做。 仅编译验证, commit 正文记录); hmac 容量守卫的 init 侧失败经 report_fail_msg 会表现为 Skipped("Unexpected OS error")而非干净 Failed——knob 钳制后不可达, 纯纵深防御, 记账。 - **承接**:P5(sleef/eigen×8)Eigen 侧已裁自 pin 回退(spike 证据: VLA <<<<<<< HEAD +- **承接**:P5(SLEEF/Eigen×8)Eigen 侧已裁自 pin 回退(spike 证据: VLA 语言级不可编译); sleef 半侧待 spike; P6 存量迁移(含本阶段 6 个 遗留手探文件)待做。 ->>>>>>> 853994d3 (docs(all-vl2): P4 收尾——README VL 政策段 all-VL 化 + progress-log 实证条目) +<<<<<<< HEAD ======= 语言级不可编译); P6 存量迁移(含本阶段 6 个遗留手探文件)待做。 +<<<<<<< HEAD ## 2026-10-24 · P5 sleef 半侧实证收口(PR #286 检视闭环) +======= +## 2026-10-24(all-VL Phase 2 P5:SLEEF/Eigen×8 按 spike 证据分流——真 VLA 迁移 + 自 pin 回退) +>>>>>>> 51679200 (docs(all-vl2): 检视精度两处——vl_bytes 来源注释 + progress-log 库名大小写) - **sleef_sve 真 VLA 迁移的 16-run 矩阵全绿**(merge blocker 解除): gem5-fi `sleef_vla_dual`(feat/sleef-vla-dual @ 6d740525),四档 @@ -854,3 +857,31 @@ M4 未尽项(假通过清单 ARM64 重推导、耗时尾部基线)在 v5 §1 (CpuNotSupported, 'test compiled with sve');zstd19 -t 2000 -n 1 pass; x86-64 非回归(纯 aarch64 段内改动)。 >>>>>>> 679c4610 (docs(progress): PR #286 检视 round 1 处置记录——k7pattern tag 32 位拆分 + sve_rot_vla_dual 16-run 实证) +======= + +## 2026-10-24(all-VL Phase 2 P6:存量迁移收官——142 文件框架层化 + 分支拓扑修复) + +- **迁移成果**(feat/p6-allvl = PR #288, 三批并行代理 + P2 回并, 29+1 commit): + 批 A(sve/case 51+kreg 11+vector2 5+fma 10)/批 B(mesh 18+arithmetic 16+ + mem 9+fma2 8)/批 C(arm64 13+eigen_bidiag 1+meson 收尾)——全部 + getauxval 手探 → arm64_require_sve_vl/sme_svl; 23 个 lanes 文件换算 + svl/8|svl/4+范围检查; 全仓活调用审计**仅剩 2 个设计保留**(fmmla/ + cross_precision 的 SVE2 HWCAP2 复合门, 测试自有语义)。批 A 净删 279 行。 +- **分支拓扑缺陷发现与修复**: P3 当初从 #277 切出漏掉 P2——P3→P4→P5→P6 + 整条栈缺 P2 的 fmopa_za 重构(批 C 在 P2 之前的旧文件上迁门控被 + 发现)。修复: P2 并入 P6(20a79b88), fmopa_za 取 P2 版本; 新合并顺序 + #277→#283→#284→#286→#280(任意时点)→#288。 +- **单位约定审计**(P6 Task 4, ac5b1e6b): 298 调用面统计(~200 纯门控/ + 97 换算/pin 全字节)——维持现行约定, 教训与防线入档 arm64_vl.h。 +- **429 预算中断**: 批 C 代理与 chain 重验代理被 API 预算超限终止; + 批 C 收尾由主 agent 补完(dc4b0121); gem5 补证改主 agent 后台自跑。 +- **先存缺陷掘出**(记账后续硬化单元, 不混入迁移批): 批 B 报告 7 类 + VL>512 越界(vsum[8] 家族/ai[8]/phase[8]/chunk[64]/fsu 跨行/ + movmskpspd VL>128 越界读——可移植范式先例 agu_stress_store_only_sve + .cpp:126); 批 A 报告 3 文件 init 取整无 run 守卫; stress 测试 + run 侧 assert 在 release(NDEBUG) 失效(P2 时发现)。 +- **验证**: 三批各自构建零告警+逐文件/逐 ID skip 核验+grep 归零; 合并 + 终态 477 测试构建零告警+zstd19 pass; 全仓审计如上。 +- **战役状态**: P0-P6 全部落地; PR 编队 #277→#283→#284→#286→#288 + (+计划文档 #279/#281/#282/#285/#287)等人工 merge 门。 +>>>>>>> a9c1f08c (docs(progress): all-VL Phase 2 P6 收官条目 + 战役状态总览) diff --git a/framework/device/cpu/arm64/arm64_vl.h b/framework/device/cpu/arm64/arm64_vl.h index 06c8daacb..ab539fc20 100644 --- a/framework/device/cpu/arm64/arm64_vl.h +++ b/framework/device/cpu/arm64/arm64_vl.h @@ -27,6 +27,16 @@ * kernel's clone-inheritance rule (new threads inherit the creator's VL) * still holds — the framework's thread structure is simply not "test_init * creates the workers". + * + * UNIT CONVENTION (P6 audit, 2026-10-24 — 298 call sites counted: ~200 + * pure gates, 97 lane conversions, all pin sites in bytes): the require + * helpers take the RANGE in BITS (matching how the spec and skip messages + * speak: "128..1024-bit") but RETURN BYTES (what buffers and lanes need); + * the pin helpers take and return BYTES. Lane conversions are therefore + * divisions: f64 lanes = svl/8, f32 lanes = svl/4 (the P2 Critical-1 + * lesson — dividing bytes by the wrong power of two compiles silently; + * every conversion site carries a unit comment plus a release-effective + * range check that catches drift). */ #include diff --git a/tests/cpu/arm64/meson.build b/tests/cpu/arm64/meson.build index c493d8025..63d926425 100644 --- a/tests/cpu/arm64/meson.build +++ b/tests/cpu/arm64/meson.build @@ -143,14 +143,21 @@ if host_machine.cpu_family() == 'aarch64' # such as this Kunpeng 920. Every test self-gates in test_init and # returns a clean EXIT_SKIP on SVE-less CPUs, so their SVE # codegen only ever executes on SVE-capable hardware. Built only on - # aarch64. (Gate split as of all-VL Phase 2: the P3 files gate via - # the framework layer — arm64_require_sve_vl: HWCAP_SVE capability + - # 128..1024-bit range in one call; the remaining legacy files still - # probe HWCAP_SVE by hand and migrate in P6.) + # aarch64. (Gate split as of all-VL Phase 2 P6: every SVE1 test in + # this library gates via the framework layer — arm64_require_sve_vl: + # HWCAP_SVE capability + 128..1024-bit range in one call. The only + # getauxval hand-probes left under tests/cpu/arm64/ are the SVE2 + # composite-gate files sve512_fmmla_arm/sve2_cross_precision_arm + # (tests_arm64_sve2 below): their SVE2|F32MM|F64MM / SVE2|SVEBF16 + # HWCAP2 conjunctions are the tests' own semantics and stay hand- + # probed by design, while their pure-SVE gate goes through the + # require helper.) # # NOTE: sve512_fma_arm.cpp is committed (ea879f68) but deliberately NOT - # wired into any sources list yet — wiring + all-VL validation is - # scheduled for all-VL Phase 2 P3 + # wired into any sources list yet — its source side was migrated to + # the all-VL form in P6 batch C (require + lanes + drift guard, commit + # d8e6f625), so wiring it in only needs the meson entry plus the + # all-VL validation run; the original wiring plan (P3) lapsed unclaimed # (docs/superpowers/specs/2026-10-23-sve-sme-all-vl2-design.md §6). arm64_sve_lib = static_library( 'tests_arm64_sve', diff --git a/tests/cpu/arm64/power_virus_dit_sve_arm.cpp b/tests/cpu/arm64/power_virus_dit_sve_arm.cpp index 8ab205713..78fb2e475 100644 --- a/tests/cpu/arm64/power_virus_dit_sve_arm.cpp +++ b/tests/cpu/arm64/power_virus_dit_sve_arm.cpp @@ -37,8 +37,11 @@ * enhancement, not a requirement — the NEON version ships the same * way). * - * test_init probes HWCAP_SVE and returns a clean EXIT_SKIP on SVE-less - * CPUs. Any runtime vector length (full 512-bit on 0xd22). Built in + * test_init gates via the framework layer (arm64_require_sve_vl: + * HWCAP_SVE capability + 128..1024-bit range in one call, all-VL + * Phase 2 P6) and returns a clean EXIT_SKIP on SVE-less CPUs. The run + * side reads the VL fresh (svcntd) and derives the golden from the + * same lanes, so no init/run VL state exists to drift. Built in * tests_arm64_sve. * @endparblock */ @@ -51,9 +54,8 @@ #include #ifdef __aarch64__ -#include -#include #include +#include #endif // Burst/stall sizes (matched duty cycle, power_virus_dit precedent). @@ -74,14 +76,14 @@ static constexpr double B1 = -0.8333333333333333; // 0xBFEAAAAAAAAAAAAA static int power_virus_dit_sve_arm_init(struct test *test) { - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "ARM64 SVE not available; power_virus_dit_sve_arm " - "requires SVE (full-width di/dt burst)"); + /* All-VL Phase 2 P6: capability + 128..1024-bit range check in one + framework-layer call, replacing the getauxval hand-probe. Gate + only: the run side re-reads svcntd() and sizes its buffers and + golden from the same lanes (no init/run VL state to drift). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - (void)test; + (void)svl; return EXIT_SUCCESS; } @@ -214,8 +216,8 @@ DECLARE_TEST(power_virus_dit_sve_arm, "svmla_f64_x burst chains with alternating high-Hamming " "operands and periodic stack-reload SVE loads (address " "generation inside the burst window), alternating with yield " - "stalls — the SVE-512 port of power_virus_dit, byte-exact vs " - "a per-lane scalar fma golden") + "stalls — the full-width SVE port of power_virus_dit, " + "byte-exact vs a per-lane scalar fma golden") .groups = DECLARE_TEST_GROUPS(&group_math), .test_init = power_virus_dit_sve_arm_init, .test_run = power_virus_dit_sve_arm_run, diff --git a/tests/cpu/arm64/sme_fmopa_stress_arm.cpp b/tests/cpu/arm64/sme_fmopa_stress_arm.cpp index 59a147d27..23705467c 100644 --- a/tests/cpu/arm64/sme_fmopa_stress_arm.cpp +++ b/tests/cpu/arm64/sme_fmopa_stress_arm.cpp @@ -28,12 +28,14 @@ * - all-core concurrency: 608 threads each in their own streaming * window (per-thread ZA, no sharing). * - * Gates: HWCAP2 SME bit, then a runtime rdsvl check bounding SVL to the - * supported 128..1024-bit range (n = SVL/4 f32 lanes per slice; the - * geometry was characterized at 512-bit on cn23154 and the parameterized - * asm verified at all four SVLs in gem5). Non-aarch64 hosts, non-clang - * compilers, and out-of-range SVLs skip with an honest reason. x86-64 - * untouched. + * Gates: the framework layer's arm64_require_sme_svl (HWCAP2_SME + * capability + 128..1024-bit SVL range in one call, all-VL Phase 2 + * P6), then the characterized-geometry guard (n = SVL/4 f32 lanes per + * slice within [4, kTileNMax]; the geometry was characterized at + * 512-bit on cn23154 and the parameterized asm verified at all four + * SVLs in gem5). Non-aarch64 hosts, non-clang compilers, and + * out-of-range SVLs skip with an honest reason; test_run re-checks the + * SVL and fails closed on drift. x86-64 untouched. * @endparblock */ @@ -56,12 +58,7 @@ #include #ifdef __aarch64__ -#include -#include -#endif -/* Kernel headers of the SME era define this; older ones (5.10) do not. */ -#ifndef HWCAP2_SME -#define HWCAP2_SME (1UL << 23) +#include #endif /* Full-SVL support (128..1024-bit): n = SVL/4 f32 lanes per slice is @@ -163,18 +160,16 @@ static int sme_fmopa_stress_arm_init(struct test *test) "built with clang on aarch64 (armv9-a+sve+sme+sme-f64f64)"); return EXIT_SKIP; #else - unsigned long hwcap2 = getauxval(AT_HWCAP2); - if ((hwcap2 & HWCAP2_SME) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "ARM64 SME not available; sme_fmopa_stress_arm exercises " - "the FMOPA matrix-accumulate datapath"); + /* All-VL Phase 2 P6: HWCAP2_SME capability + 128..1024-bit SVL range + * in one framework-layer call, replacing the getauxval hand-probe and + * the inline rdsvl (the helper reads rdsvl #1 internally — SME + * implies SVE, so it cannot SIGILL here). Returns the SVL in BYTES; + * the n = SVL/4 geometry and the [4, kTileNMax] stack-buffer guard + * below are the gem5-verified parameterized geometry and stay + * untouched. */ + const long svl_bytes = arm64_require_sme_svl(test, 128, 1024); + if (svl_bytes < 0) return EXIT_SKIP; - } - - /* RDVL Xd, #imm = VL_bytes * imm; #1 reads the streaming vector - * length in bytes. SME implies SVE, so rdsvl cannot SIGILL here. */ - long svl_bytes; - asm volatile("rdsvl %0, #1" : "=r"(svl_bytes)); const long n = svl_bytes / 4; if (n < 4 || n > kTileNMax) { log_skip(CpuNotSupportedSkipCategory, @@ -246,6 +241,16 @@ static int sme_fmopa_stress_arm_run(struct test *test, int cpu) * pin init's invariant (n within [4, kTileNMax]) before any buffer * math (PR #242 review, coderabbit). */ assert(n >= 4 && n <= kTileNMax); + /* All-VL policy #3: fail closed on init/run SVL drift — the shared + * golden is sized at init's n, and the assert above only pins the + * stored invariant (NDEBUG-sensitive); this check is + * release-effective and compares a fresh rdsvl read. */ + if (arm64_sme_svl_bytes() / 4 != n) { + log_error("sme_fmopa_stress_arm: SVL drifted between init (n=%ld) " + "and run (n=%ld)", n, arm64_sme_svl_bytes() / 4); + report_fail_msg("sme_fmopa_stress_arm: SME SVL drifted between " + "init and run"); + } const size_t count = static_cast(n) * n; const size_t bytes = count * sizeof(float); diff --git a/tests/cpu/arm64/sme_za_tileview_arm.cpp b/tests/cpu/arm64/sme_za_tileview_arm.cpp index 317eb87ed..577cb8bb8 100644 --- a/tests/cpu/arm64/sme_za_tileview_arm.cpp +++ b/tests/cpu/arm64/sme_za_tileview_arm.cpp @@ -32,9 +32,12 @@ * ZA stores, register-offset addressing) are spelled out so codegen * cannot drift from the measured recipe. * - * Gates: HWCAP2 SME bit, then a runtime rdsvl check pinning the - * characterized geometry (8 f64 per slice). Non-aarch64 hosts, non- - * clang compilers, and uncharacterized SVLs skip with an honest reason. + * Gates: the framework layer's arm64_require_sme_svl (HWCAP2_SME + * capability + 128..1024-bit SVL range in one call, all-VL Phase 2 + * P6), then the characterized-geometry guard (n = SVL/8 f64 per slice + * within [2, kTileNMax]). Non-aarch64 hosts, non-clang compilers, and + * uncharacterized SVLs skip with an honest reason. test_run re-checks + * the SVL and fails closed on drift. * @endparblock */ @@ -60,13 +63,7 @@ #include #ifdef __aarch64__ -#include -#include -#endif - -/* Kernel headers of the SME era define this; older ones (5.10) do not. */ -#ifndef HWCAP2_SME -#define HWCAP2_SME (1UL << 23) +#include #endif /* Full-SVL support (128..1024-bit): n = SVL/8 f64 per ZA slice is read @@ -197,18 +194,16 @@ static int sme_za_tileview_arm_init(struct test *test) "built with clang on aarch64 (armv9-a+sve+sme+sme-f64f64)"); return EXIT_SKIP; #else - unsigned long hwcap2 = getauxval(AT_HWCAP2); - if ((hwcap2 & HWCAP2_SME) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "ARM64 SME not available; sme_za_tileview_arm exercises " - "the ZA tile-view datapath"); + /* All-VL Phase 2 P6: HWCAP2_SME capability + 128..1024-bit SVL range + * in one framework-layer call, replacing the getauxval hand-probe and + * the inline rdsvl (the helper reads rdsvl #1 internally — SME + * implies SVE, so it cannot SIGILL here). Returns the SVL in BYTES; + * the n = SVL/8 geometry and the [2, kTileNMax] stack-buffer guard + * below are the P1-242/PR-#242-verified parameterized geometry and + * stay untouched. */ + const long svl_bytes = arm64_require_sme_svl(test, 128, 1024); + if (svl_bytes < 0) return EXIT_SKIP; - } - - /* RDVL Xd, #imm = VL_bytes * imm, so #1 reads the streaming vector - * length in bytes. SME implies SVE, so rdsvl cannot SIGILL here. */ - long svl_bytes; - asm volatile("rdsvl %0, #1" : "=r"(svl_bytes)); const long n = svl_bytes / 8; if (n < 2 || n > kTileNMax) { log_skip(CpuNotSupportedSkipCategory, @@ -302,6 +297,16 @@ static int sme_za_tileview_arm_run(struct test *test, int cpu) * so pin init's invariant (n within [2, kTileNMax]) before any buffer * math (PR #242 review, coderabbit). */ assert(n >= 2 && n <= kTileNMax); + /* All-VL policy #3: fail closed on init/run SVL drift — the shared + * goldens are sized at init's n, and the assert above only pins the + * stored invariant (NDEBUG-sensitive); this check is + * release-effective and compares a fresh rdsvl read. */ + if (arm64_sme_svl_bytes() / 8 != n) { + log_error("sme_za_tileview_arm: SVL drifted between init (n=%ld) " + "and run (n=%ld)", n, arm64_sme_svl_bytes() / 8); + report_fail_msg("sme_za_tileview_arm: SME SVL drifted between " + "init and run"); + } const size_t count = static_cast(n) * n; const size_t bytes = count * sizeof(double); diff --git a/tests/cpu/arm64/sve2_cross_precision_arm.cpp b/tests/cpu/arm64/sve2_cross_precision_arm.cpp index 49cc0331b..1b893c4d3 100644 --- a/tests/cpu/arm64/sve2_cross_precision_arm.cpp +++ b/tests/cpu/arm64/sve2_cross_precision_arm.cpp @@ -37,11 +37,18 @@ * bf16), so products and sums stay exact and the chain of 256 steps is * byte-exact comparable. Chains are dependent (accumulator feeds forward). * - * test_init probes HWCAP_SVE + HWCAP2 (SVE2, SVEBF16) and returns a clean - * EXIT_SKIP when absent; a one-step self-check compares golden vs hardware - * before the long chain so a golden bug never reports as SDC. Requires - * the tests_arm64_sve2 library (-march=armv9-a+sve2+bf16). Any runtime - * vector length accepted. ARM64-native. + * test_init gates in two layers (all-VL Phase 2 P6 split): the pure SVE + * capability + 128..1024-bit range check goes through the framework + * layer (arm64_require_sve_vl, one call), while the composite + * SVE2|SVEBF16 HWCAP2 bits stay a getauxval hand-probe — that + * conjunction is this test's own semantics (FEAT_SVE_bf16 widening + * pipelines), not something the generic require helper covers. Either + * layer returns a clean EXIT_SKIP when absent; test_run re-checks the + * VL and fails closed on drift. A one-step self-check compares golden + * vs hardware before the long chain so a golden bug never reports as + * SDC. Requires the tests_arm64_sve2 library (-march=armv9-a+sve2+bf16). + * Any runtime vector length in the supported range is accepted. + * ARM64-native. * @endparblock */ @@ -58,6 +65,7 @@ #include #include #include +#include #endif // Dependent chain length per iteration. @@ -188,14 +196,16 @@ static int sve2_cross_precision_arm_init(struct test *test) (void)test; return EXIT_SUCCESS; #else - unsigned long hwcap = getauxval(AT_HWCAP); - unsigned long hwcap2 = getauxval(AT_HWCAP2); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "ARM64 SVE not available; sve2_cross_precision_arm " - "requires SVE"); + /* All-VL Phase 2 P6 split gate: the pure SVE capability + 128..1024-bit + range check moves to the framework layer (arm64_require_sve_vl — + returns the VL in BYTES), while the composite SVE2|SVEBF16 HWCAP2 + conjunction stays a getauxval hand-probe: it is this test's own + semantic gate (FEAT_SVE_bf16), which the generic require helper + does not cover. */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } + unsigned long hwcap2 = getauxval(AT_HWCAP2); if ((hwcap2 & (HWCAP2_SVE2 | HWCAP2_SVEBF16)) != (HWCAP2_SVE2 | HWCAP2_SVEBF16)) { log_skip(CpuNotSupportedSkipCategory, @@ -209,7 +219,13 @@ static int sve2_cross_precision_arm_init(struct test *test) try { auto data = std::make_unique(); - data->vl_f32 = svcntw(); + data->vl_f32 = (size_t)svl / 4; /* f32 lanes = SVL bytes / 4 */ + if (data->vl_f32 < 4 || data->vl_f32 > 32) { + log_error("sve2_cross_precision_arm: f32 lanes %zu outside " + "[4,32] — unit drift (svl %ld bytes)", + data->vl_f32, svl); + return EXIT_FAILURE; + } const size_t lanes = data->vl_f32; const size_t srcs = 2 * lanes; // f16/bf16 source lanes @@ -252,6 +268,18 @@ static int sve2_cross_precision_arm_run(struct test *test, int cpu) return EXIT_SKIP; #else auto *d = static_cast(test->data); + + /* All-VL policy #3: fail closed on init/run VL drift (the goldens + are sized at init's lanes; a wider run-side VL would read past + them in the compare loops below). */ + if (svcntw() != d->vl_f32) { + log_error("sve2_cross_precision_arm: VL drifted between init " + "(%zu f32 lanes) and run (%u lanes)", d->vl_f32, + (unsigned)svcntw()); + report_fail_msg("sve2_cross_precision_arm: SVE VL drifted " + "between init and run"); + } + const size_t lanes = d->vl_f32; const size_t srcs = 2 * lanes; bool all_passed = true; diff --git a/tests/cpu/arm64/sve512_fcmla_arm.cpp b/tests/cpu/arm64/sve512_fcmla_arm.cpp index d01aa40d6..36c5d725f 100644 --- a/tests/cpu/arm64/sve512_fcmla_arm.cpp +++ b/tests/cpu/arm64/sve512_fcmla_arm.cpp @@ -46,8 +46,10 @@ * per rotation compares golden vs hardware before the chain runs — a * golden bug reports as a test bug, never as SDC. * - * test_init probes HWCAP_SVE and returns a clean EXIT_SKIP on SVE-less - * CPUs. Any runtime vector length. Built in tests_arm64_sve + * test_init gates via the framework layer (arm64_require_sve_vl: + * HWCAP_SVE capability + 128..1024-bit range in one call, all-VL + * Phase 2 P6) and returns a clean EXIT_SKIP on SVE-less CPUs; test_run + * re-checks the VL and fails closed on drift. Built in tests_arm64_sve * (armv8.2-a+sve — FCMLA is SVE1). * @endparblock */ @@ -61,9 +63,8 @@ #include #ifdef __aarch64__ -#include -#include #include +#include #endif static constexpr size_t CHAIN_STEPS = 512; @@ -165,17 +166,25 @@ static int sve512_fcmla_arm_init(struct test *test) (void)test; return EXIT_SUCCESS; #else - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "ARM64 SVE not available; sve512_fcmla_arm requires SVE " - "(complex FMA FCMLA is SVE1)"); + /* All-VL Phase 2 P6: capability + 128..1024-bit range check in one + framework-layer call, replacing the getauxval hand-probe (the + framework-level compiler_minimum_device gate already skips no-SVE + hosts before init; this keeps a test-specific skip reason if that + gate ordering ever changes). arm64_require_sve_vl returns the VL + in BYTES — f64 lanes = svl/8, range-checked below + (release-effective, NDEBUG-proof). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } try { auto data = std::make_unique(); - data->vl_d = svcntd(); + data->vl_d = (size_t)svl / 8; /* f64 lanes = SVL bytes / 8 */ + if (data->vl_d < 2 || data->vl_d > 16) { + log_error("sve512_fcmla_arm: f64 lanes %zu outside [2,16] " + "— unit drift (svl %ld bytes)", data->vl_d, svl); + return EXIT_FAILURE; + } const size_t pairs = data->vl_d / 2; // complex lane pairs // b/c operand streams: pair-major [pair*2 + {e,i}] @@ -219,6 +228,16 @@ static int sve512_fcmla_arm_run(struct test *test, int cpu) return EXIT_SKIP; #else auto *d = static_cast(test->data); + + /* All-VL policy #3: fail closed on init/run VL drift (init sized the + golden lanes at its VL). */ + if (svcntd() != d->vl_d) { + log_error("sve512_fcmla_arm: VL drifted between init (%zu lanes) " + "and run (%u lanes)", d->vl_d, (unsigned)svcntd()); + report_fail_msg("sve512_fcmla_arm: SVE VL drifted between init " + "and run"); + } + const size_t vl_d = d->vl_d; const size_t pairs = vl_d / 2; diff --git a/tests/cpu/arm64/sve512_fma_arm.cpp b/tests/cpu/arm64/sve512_fma_arm.cpp index 627e24308..12177697e 100644 --- a/tests/cpu/arm64/sve512_fma_arm.cpp +++ b/tests/cpu/arm64/sve512_fma_arm.cpp @@ -17,9 +17,11 @@ * This test is compiled WITHOUT -msve-vector-bits so the GCC sizeless * svfloat64_t / svfloat32_t types adopt the CPU runtime vector length — * the full 512-bit datapath on 0xd22 (and a proportional width on any - * other SVE CPU). test_init probes HWCAP_SVE via getauxval (no SVE - * instruction executes before the probe), returning a clean EXIT_SKIP on - * SVE-less CPUs (e.g. the Kunpeng 920 login node). + * other SVE CPU). test_init gates via the framework layer + * (arm64_require_sve_vl: HWCAP_SVE capability + 128..1024-bit range in + * one call, no SVE instruction executes before the gate, all-VL Phase 2 + * P6), returning a clean EXIT_SKIP on SVE-less CPUs (e.g. the Kunpeng + * 920 login node); test_run re-checks the VL and fails closed on drift. * * Four byte-exact-checked workloads run in every iteration: * @@ -60,9 +62,8 @@ #include #ifdef __aarch64__ -#include -#include #include +#include #endif // Serial FMA chain length per iteration. @@ -339,19 +340,29 @@ static int sve512_fma_arm_init(struct test *test) (void)test; return EXIT_SUCCESS; #else - // Probe SVE availability BEFORE executing any SVE instruction. - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "ARM64 SVE not available on this CPU; sve512_fma_arm " - "requires SVE (e.g. HiSilicon 0xd22, 512-bit VL)"); + /* All-VL Phase 2 P6: capability + 128..1024-bit range check in one + framework-layer call, replacing the getauxval hand-probe (no SVE + instruction executes before the gate). arm64_require_sve_vl + returns the VL in BYTES — f64 lanes = svl/8, f32 lanes = svl/4, + both range-checked below (release-effective, NDEBUG-proof). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } try { auto data = std::make_unique(); - data->vl_d = svcntd(); - data->vl_w = svcntw(); + data->vl_d = (size_t)svl / 8; /* f64 lanes = SVL bytes / 8 */ + data->vl_w = (size_t)svl / 4; /* f32 lanes = SVL bytes / 4 */ + if (data->vl_d < 2 || data->vl_d > 16) { + log_error("sve512_fma_arm: f64 lanes %zu outside [2,16] " + "— unit drift (svl %ld bytes)", data->vl_d, svl); + return EXIT_FAILURE; + } + if (data->vl_w < 4 || data->vl_w > 32) { + log_error("sve512_fma_arm: f32 lanes %zu outside [4,32] " + "— unit drift (svl %ld bytes)", data->vl_w, svl); + return EXIT_FAILURE; + } // Per-lane seed accumulators: finite in [1.0, 2.0). data->seeds_f64.resize(data->vl_d); @@ -444,6 +455,17 @@ static int sve512_fma_arm_run(struct test *test, int cpu) #else auto *d = static_cast(test->data); + /* All-VL policy #3: fail closed on init/run VL drift (the operand + streams and goldens are sized in init at its lanes). */ + if (svcntd() != d->vl_d || svcntw() != d->vl_w) { + log_error("sve512_fma_arm: VL drifted between init (f64 %zu, " + "f32 %zu lanes) and run (f64 %u, f32 %u lanes)", + d->vl_d, d->vl_w, (unsigned)svcntd(), + (unsigned)svcntw()); + report_fail_msg("sve512_fma_arm: SVE VL drifted between init " + "and run"); + } + // Goldens, recomputed each iteration (deterministic, same op order). std::vector gold64(d->vl_d); std::vector golds64(d->vl_d); @@ -539,9 +561,9 @@ static int sve512_fma_arm_cleanup(struct test *test) DECLARE_TEST(sve512_fma_arm, "SVE full-vector-length FMA SDC stress: f64/f32 FMLA dependency " "chains + special-value category chain + gather/scatter " - "round-trip at the CPU's runtime SVE vector length (512-bit on " - "HiSilicon 0xd22), byte-exact compared against deterministic " - "software references") + "round-trip at the CPU's runtime SVE vector length (all-VL " + "128..1024-bit via arm64_require_sve_vl), byte-exact compared " + "against deterministic software references") .groups = DECLARE_TEST_GROUPS(&group_math), .test_init = sve512_fma_arm_init, .test_run = sve512_fma_arm_run, diff --git a/tests/cpu/arm64/sve512_fmmla_arm.cpp b/tests/cpu/arm64/sve512_fmmla_arm.cpp index 53737245c..09684e72b 100644 --- a/tests/cpu/arm64/sve512_fmmla_arm.cpp +++ b/tests/cpu/arm64/sve512_fmmla_arm.cpp @@ -43,11 +43,17 @@ * with a clear message (golden-lane-mapping bug guard, so the test never * reports a false SDC on a healthy CPU). * - * test_init probes HWCAP_SVE + HWCAP2 (SVE2, F32MM, F64MM) via getauxval - * before any SVE instruction, returning a clean EXIT_SKIP when absent - * (e.g. this Kunpeng 920 dev host). Requires the tests_arm64_sve2 library - * (-march=armv9-a+sve2+f32mm+f64mm). Any runtime vector length is - * accepted (full 512-bit on 0xd22). + * test_init gates in two layers (all-VL Phase 2 P6 split): the pure SVE + * capability + 128..1024-bit range check goes through the framework + * layer (arm64_require_sve_vl, one call, no SVE instruction executes + * before the gate), while the composite SVE2|F32MM|F64MM HWCAP2 bits + * stay a getauxval hand-probe — that conjunction is this test's own + * semantics (FEAT_F32MM + FEAT_F64MM), not something the generic + * require helper covers. Either layer returns a clean EXIT_SKIP when + * absent (e.g. this Kunpeng 920 dev host). test_run re-checks the VL + * and fails closed on drift. Requires the tests_arm64_sve2 library + * (-march=armv9-a+sve2+f32mm+f64mm). Any runtime vector length in the + * supported range is accepted (full 512-bit on 0xd22). * @endparblock */ @@ -63,6 +69,7 @@ #include #include #include +#include #endif // Dependent FMMLA chain length per iteration. @@ -146,13 +153,16 @@ static int sve512_fmmla_arm_init(struct test *test) (void)test; return EXIT_SUCCESS; #else - unsigned long hwcap = getauxval(AT_HWCAP); - unsigned long hwcap2 = getauxval(AT_HWCAP2); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "ARM64 SVE not available; sve512_fmmla_arm requires SVE"); + /* All-VL Phase 2 P6 split gate: the pure SVE capability + 128..1024-bit + range check moves to the framework layer (arm64_require_sve_vl — + returns the VL in BYTES), while the composite SVE2|F32MM|F64MM + HWCAP2 conjunction stays a getauxval hand-probe: it is this test's + own semantic gate (FEAT_F32MM + FEAT_F64MM matrix-multiply + instructions), which the generic require helper does not cover. */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } + unsigned long hwcap2 = getauxval(AT_HWCAP2); if ((hwcap2 & (HWCAP2_SVE2 | HWCAP2_SVEF32MM | HWCAP2_SVEF64MM)) != (HWCAP2_SVE2 | HWCAP2_SVEF32MM | HWCAP2_SVEF64MM)) { log_skip(CpuNotSupportedSkipCategory, @@ -167,8 +177,13 @@ static int sve512_fmmla_arm_init(struct test *test) try { auto data = std::make_unique(); - const size_t vl_w = svcntw(); // f32 lanes - const size_t vl_d = svcntd(); // f64 lanes + const size_t vl_w = (size_t)svl / 4; /* f32 lanes = SVL bytes / 4 */ + const size_t vl_d = (size_t)svl / 8; /* f64 lanes = SVL bytes / 8 */ + if (vl_d < 2 || vl_d > 16 || vl_w < 4 || vl_w > 32) { + log_error("sve512_fmmla_arm: lanes outside [2,16]/[4,32] " + "— unit drift (svl %ld bytes)", svl); + return EXIT_FAILURE; + } data->vl_f32_rows = vl_w / 2; // f32 tile side data->vl_f64_rows = vl_d / 2; // f64 tile side @@ -223,6 +238,19 @@ static int sve512_fmmla_arm_run(struct test *test, int cpu) auto *d = static_cast(test->data); const size_t vl_d = svcntd(); const size_t vl_w = svcntw(); + + /* All-VL policy #3: fail closed on init/run VL drift (the goldens + are sized at init's lanes; a wider run-side VL would read past + them in the compare loops below). */ + if (vl_d != d->vl_f64_rows * 2 || vl_w != d->vl_f32_rows * 2) { + log_error("sve512_fmmla_arm: VL drifted between init (f64 tile " + "side %zu, f32 tile side %zu) and run (svcntd %u, " + "svcntw %u)", d->vl_f64_rows, d->vl_f32_rows, + (unsigned)vl_d, (unsigned)vl_w); + report_fail_msg("sve512_fmmla_arm: SVE VL drifted between init " + "and run"); + } + bool all_passed = true; // ---------- f64 tile ---------- diff --git a/tests/cpu/arm64/sve512_nt_reload_arm.cpp b/tests/cpu/arm64/sve512_nt_reload_arm.cpp index fef697e93..73b7bb923 100644 --- a/tests/cpu/arm64/sve512_nt_reload_arm.cpp +++ b/tests/cpu/arm64/sve512_nt_reload_arm.cpp @@ -42,10 +42,12 @@ * (sve512_stencil_axis_arm precedent — the NUMA3 signature corrupts * VA[55:48] while TCR.TBI0=1 silently ignores VA[63:56]). * - * test_init probes HWCAP_SVE via getauxval before any SVE instruction, - * returning a clean EXIT_SKIP on SVE-less CPUs. Any runtime vector length - * is accepted (full 512-bit on HiSilicon 0xd22). ARM64-native; built only - * on aarch64 (tests_arm64_sve library). + * test_init gates via the framework layer (arm64_require_sve_vl: + * HWCAP_SVE capability + 128..1024-bit range in one call, no SVE + * instruction executes before the gate, all-VL Phase 2 P6), returning a + * clean EXIT_SKIP on SVE-less CPUs; test_run re-checks the VL and fails + * closed on drift. ARM64-native; built only on aarch64 (tests_arm64_sve + * library). * @endparblock */ @@ -58,9 +60,8 @@ #include #ifdef __aarch64__ -#include -#include #include +#include #endif // Full-vector steps per outer iteration. @@ -216,18 +217,24 @@ static int sve512_nt_reload_arm_init(struct test *test) (void)test; return EXIT_SUCCESS; #else - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "ARM64 SVE not available on this CPU; " - "sve512_nt_reload_arm requires SVE (ld1rd/ldnt1d/stnt1d " - "are the NUMA3 VA-path fault trigger-instruction window)"); + /* All-VL Phase 2 P6: capability + 128..1024-bit range check in one + framework-layer call, replacing the getauxval hand-probe (no SVE + instruction executes before the gate). arm64_require_sve_vl + returns the VL in BYTES — f64 lanes = svl/8, range-checked below + (release-effective, NDEBUG-proof). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } try { auto data = std::make_unique(); - data->vl_d = svcntd(); + data->vl_d = (size_t)svl / 8; /* f64 lanes = SVL bytes / 8 */ + if (data->vl_d < 2 || data->vl_d > 16) { + log_error("sve512_nt_reload_arm: f64 lanes %zu outside " + "[2,16] — unit drift (svl %ld bytes)", + data->vl_d, svl); + return EXIT_FAILURE; + } if (BUF_ELEMS % data->vl_d != 0) { // BUF_ELEMS is 4096; any power-of-two lane count divides it. // A non-power-of-two VL would make step vectors overlap; skip @@ -300,6 +307,17 @@ static int sve512_nt_reload_arm_run(struct test *test, int cpu) return EXIT_SKIP; #else auto *d = static_cast(test->data); + + /* All-VL policy #3: fail closed on init/run VL drift (buf/out/golden + are sized in init at its VL). */ + if (svcntd() != d->vl_d) { + log_error("sve512_nt_reload_arm: VL drifted between init (%zu " + "lanes) and run (%u lanes)", d->vl_d, + (unsigned)svcntd()); + report_fail_msg("sve512_nt_reload_arm: SVE VL drifted between " + "init and run"); + } + const size_t vl = d->vl_d; // Stack slots — the reload sources (fault ingredient). diff --git a/tests/cpu/arm64/sve512_pred_ops_arm.cpp b/tests/cpu/arm64/sve512_pred_ops_arm.cpp index 3fda83c25..b29be9550 100644 --- a/tests/cpu/arm64/sve512_pred_ops_arm.cpp +++ b/tests/cpu/arm64/sve512_pred_ops_arm.cpp @@ -44,8 +44,10 @@ * datapath itself.) FMAXV tree reduction (order-independent, exactly * checkable) over the whilelt-masked prefix. * - * test_init probes HWCAP_SVE and returns a clean EXIT_SKIP on SVE-less - * CPUs. Any runtime vector length. Built in tests_arm64_sve. + * test_init gates via the framework layer (arm64_require_sve_vl: + * HWCAP_SVE capability + 128..1024-bit range in one call, all-VL + * Phase 2 P6) and returns a clean EXIT_SKIP on SVE-less CPUs; test_run + * re-checks the VL and fails closed on drift. Built in tests_arm64_sve. * @endparblock */ @@ -58,9 +60,8 @@ #include #ifdef __aarch64__ -#include -#include #include +#include #endif static constexpr size_t FADDA_STEPS = 256; @@ -82,17 +83,23 @@ static int sve512_pred_ops_arm_init(struct test *test) (void)test; return EXIT_SUCCESS; #else - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "ARM64 SVE not available; sve512_pred_ops_arm requires " - "SVE (predicate network is SVE-specific silicon)"); + /* All-VL Phase 2 P6: capability + 128..1024-bit range check in one + framework-layer call, replacing the getauxval hand-probe. + arm64_require_sve_vl returns the VL in BYTES — f64 lanes = + svl/8, range-checked below (release-effective, NDEBUG-proof). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } try { auto data = std::make_unique(); - data->vl_d = svcntd(); + data->vl_d = (size_t)svl / 8; /* f64 lanes = SVL bytes / 8 */ + if (data->vl_d < 2 || data->vl_d > 16) { + log_error("sve512_pred_ops_arm: f64 lanes %zu outside " + "[2,16] — unit drift (svl %ld bytes)", + data->vl_d, svl); + return EXIT_FAILURE; + } data->src.resize(data->vl_d); for (size_t j = 0; j < data->vl_d; ++j) data->src[j] = (double)(j % 4) - 1.5; // exact values @@ -117,6 +124,17 @@ static int sve512_pred_ops_arm_run(struct test *test, int cpu) return EXIT_SKIP; #else auto *d = static_cast(test->data); + + /* All-VL policy #3: fail closed on init/run VL drift (src and the + density-sweep buffers are sized in init at its VL). */ + if (svcntd() != d->vl_d) { + log_error("sve512_pred_ops_arm: VL drifted between init (%zu " + "lanes) and run (%u lanes)", d->vl_d, + (unsigned)svcntd()); + report_fail_msg("sve512_pred_ops_arm: SVE VL drifted between " + "init and run"); + } + const size_t vl = d->vl_d; const svbool_t all = svptrue_b64(); bool all_passed = true; diff --git a/tests/cpu/arm64/sve512_stencil_axis_arm.cpp b/tests/cpu/arm64/sve512_stencil_axis_arm.cpp index 50ea30e12..83313cb99 100644 --- a/tests/cpu/arm64/sve512_stencil_axis_arm.cpp +++ b/tests/cpu/arm64/sve512_stencil_axis_arm.cpp @@ -65,9 +65,11 @@ * dropped (the framework times tests itself). * * Full-VL support: bt = 2*svcntd() f64 lanes (128..1024-bit SVE), all - * layout offsets scale at runtime; out-of-range VLs return a clean - * EXIT_SKIP, non-SVE CPUs are skipped by the framework's - * compiler-feature gate. Built only on aarch64. + * layout offsets scale at runtime; test_init gates the SVE capability + * and the 128..1024-bit range via the framework layer + * (arm64_require_sve_vl, all-VL Phase 2 P6) and out-of-range tile + * widths return a clean EXIT_SKIP, non-SVE CPUs are skipped by the + * framework's compiler-feature gate. Built only on aarch64. * * RUNTIME-UNVERIFIABLE (512-bit SVE): developed on a host without SVE * (HWCAP_SVE clear); compile-verified and the skip path executed for @@ -87,9 +89,8 @@ #include #ifdef __aarch64__ -#include -#include #include +#include #endif using std::size_t; @@ -199,12 +200,19 @@ static double stencil_random_pm_one() static int sve512_stencil_axis_arm_init(struct test *test) { - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "ARM64 SVE not available; sve512_stencil_axis_arm requires SVE"); + /* All-VL Phase 2 P6: probe-only swap — the SVE capability gate moves + * to the framework layer (arm64_require_sve_vl: HWCAP_SVE + the + * 128..1024-bit range in one call), replacing the getauxval + * hand-probe. The bt = 2*svcntd() geometry below and its [4, + * kTileMax] stack-buffer guard are the P1-242-verified parameterized + * geometry and stay untouched; the run side re-checks 2*svcntd() + * against init's bt (release-effective drift guard, all-VL policy + * #3), and the run-side assert() additionally pins the kTileMax + * buffer bound. */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } + (void)svl; /* gate only: bt is read via svcntd() as before */ /* Full-VL support: bt = 2*svcntd() scales every layout offset below. * The 512-bit geometry was characterized on HiSilicon 0xd22; the @@ -267,6 +275,19 @@ static int sve512_stencil_axis_arm_run(struct test *test, int cpu) (void)cpu; auto *d = static_cast(test->data); + /* All-VL policy #3 (fail-closed): re-check the geometry fresh. The + * assert() further down only pins the stored invariant and is + * NDEBUG-sensitive (writing_tests.md: re-check the VL in test_run and + * report_fail on drift — never continue with stale geometry; the + * xlswave/gather_scatter siblings use the same release-effective + * form). */ + if (2 * svcntd() != d->bt) { + log_error("sve512_stencil_axis_arm: VL drifted between init (bt=%zu) " + "and run (bt=%zu)", d->bt, (size_t)(2 * svcntd())); + report_fail_msg("sve512_stencil_axis_arm: SVE VL drifted between " + "init and run"); + } + // Stack-local coefficient table (the svdup_f64 / ld1rd source), as in // the original main(). 0.125 is exactly representable. double coeff[RADIUS + 1] = {}; diff --git a/tests/cpu/arm64/sve_fpcr_cartesian_arm.cpp b/tests/cpu/arm64/sve_fpcr_cartesian_arm.cpp index 6f330303b..4ee4bcb44 100644 --- a/tests/cpu/arm64/sve_fpcr_cartesian_arm.cpp +++ b/tests/cpu/arm64/sve_fpcr_cartesian_arm.cpp @@ -15,8 +15,13 @@ * golden with FZ flush mirrored in software. mrs/msr only between * configurations. FPCR saved/restored/verified. * - * test_init probes HWCAP_SVE and returns a clean EXIT_SKIP on SVE-less - * CPUs (e.g. this Kunpeng 920 dev host). Any runtime vector length. + * test_init gates via the framework layer (arm64_require_sve_vl: + * HWCAP_SVE capability + 128..1024-bit range in one call, all-VL + * Phase 2 P6) and returns a clean EXIT_SKIP on SVE-less CPUs (e.g. + * this Kunpeng 920 dev host). The run side reads the VL fresh (svcntw) + * and sizes its operand buffers from the same lanes, and re-checks it + * against the init-time value recorded in test->data — a drifted VL + * fails closed instead of running ungated geometry (all-VL policy #3). * Built in tests_arm64_sve. * @endparblock */ @@ -30,9 +35,8 @@ #include #ifdef __aarch64__ -#include -#include #include +#include #endif static const uint32_t SPECIAL_F32[] = { @@ -82,6 +86,12 @@ static const int ROUND_FE[4] = { FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO }; static const char *ROUND_NAME[4] = { "RNE", "RP", "RM", "RZ" }; +/* init 期记录的 VL (f32 lanes): run 侧漂移比对用 (all-VL policy #3, + * stencil_axis/xlswave sibling 同款 fail-closed 形态)。 */ +struct SveFpcrCartesianData { + size_t vl_w; +}; + static uint32_t golden_fma_f32(uint32_t ua, uint32_t ub, uint32_t uc, int r, int fz) { @@ -111,13 +121,18 @@ static int sve_fpcr_cartesian_arm_init(struct test *test) (void)test; return EXIT_SUCCESS; #else - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "ARM64 SVE not available; sve_fpcr_cartesian_arm " - "requires SVE (SVE-side rounding network)"); + /* All-VL Phase 2 P6: capability + 128..1024-bit range check in one + framework-layer call, replacing the getauxval hand-probe. The + init-time VL (f32 lanes) is recorded in test->data; the run side + re-reads svcntw(), sizes its buffers from the same lanes, and + fails closed on drift from the recorded value (all-VL policy #3). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } + auto *fpcr_data = static_cast( + malloc(sizeof(SveFpcrCartesianData))); + fpcr_data->vl_w = (size_t)svl / sizeof(float); + test->data = fpcr_data; return EXIT_SUCCESS; #endif } @@ -132,7 +147,17 @@ static int sve_fpcr_cartesian_arm_run(struct test *test, int cpu) "sve_fpcr_cartesian_arm"); return EXIT_SKIP; #else + auto *data = static_cast(test->data); const size_t vl_w = svcntw(); + /* All-VL policy #3 (fail-closed): a VL that drifted between init + * and run was never range-gated — refuse to run it on stale + * geometry (stencil_axis/xlswave sibling form). */ + if (vl_w != data->vl_w) { + log_error("sve_fpcr_cartesian_arm: VL drifted between init " + "(%zu lanes) and run (%zu lanes)", data->vl_w, vl_w); + report_fail_msg("sve_fpcr_cartesian_arm: SVE VL drifted " + "between init and run"); + } const uint64_t orig_fpcr = rd_fpcr(); const svbool_t all = svptrue_b32(); bool all_passed = true; @@ -153,25 +178,27 @@ static int sve_fpcr_cartesian_arm_run(struct test *test, int cpu) wr_fpcr(fpcr); // tie liveness on the SVE datapath: fma(1,1,2^-24) is a real - // single-rounding tie — 1.0 + 2^-24 rounds per mode. + // single-rounding tie — 1.0 + 2^-24 rounds per mode. Operands + // and result live in the vl_w-sized a/b/c/hw vectors (lane 0 = + // tie operands, lanes 1+ whatever the previous hot iteration + // left — never compared): the pre-all-VL form used 2-element + // stack arrays against a full-width svld1/svst1, an OOB + // read/write at every VL >= 128-bit (svcntw() >= 4 lanes). { - float ta[2] = { 1.0f, 0.0f }; - float tb[2] = { 1.0f, 0.0f }; - float tc[2] = { 0x1p-24f, 0.0f }; - svfloat32_t va = svld1_f32(all, ta); - svfloat32_t vb = svld1_f32(all, tb); - svfloat32_t vc = svld1_f32(all, tc); + a[0] = 1.0f; b[0] = 1.0f; c[0] = 0x1p-24f; + svfloat32_t va = svld1_f32(all, a.data()); + svfloat32_t vb = svld1_f32(all, b.data()); + svfloat32_t vc = svld1_f32(all, c.data()); svfloat32_t vd = svmla_f32_x(all, vc, va, vb); - float res[2] = { 0.0f, 0.0f }; - svst1_f32(all, res, vd); + svst1_f32(all, hw.data(), vd); // 1+2^-24 is an exact tie between 1.0 and 1.000002: // RNE->1.0, RP->1.000002 (toward +inf), RM->1.0, RZ->1.0. float expect2 = (r == 1) ? 0x1.000002p+0f : 0x1p+0f; - if (res[0] != expect2) { + if (hw[0] != expect2) { log_warning("sve_fpcr_cartesian: mode %s fz=%d " "liveness FAILED: fma(1,1,2^-24)=%a " "(want %a)", ROUND_NAME[r], fz, - (double)res[0], (double)expect2); + (double)hw[0], (double)expect2); wr_fpcr(orig_fpcr); report_fail_msg("sve_fpcr_cartesian_arm: SVE " "rounding mode did not take effect"); @@ -265,7 +292,8 @@ static int sve_fpcr_cartesian_arm_run(struct test *test, int cpu) static int sve_fpcr_cartesian_arm_cleanup(struct test *test) { - (void)test; + free(static_cast(test->data)); + test->data = nullptr; return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/arithmetic/acl_gemm_sve.cpp b/tests/cpu/sve/arithmetic/acl_gemm_sve.cpp index ddf93abc5..499889f95 100644 --- a/tests/cpu/sve/arithmetic/acl_gemm_sve.cpp +++ b/tests/cpu/sve/arithmetic/acl_gemm_sve.cpp @@ -29,11 +29,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif /* GEMM 维度 n (M=N=K) 运行时可配置, 统一优先级链: @@ -66,12 +62,13 @@ static void naive_gemm(const float *A, const float *B, float *C, int n) static int acl_gemm_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for acl_gemm_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *d = new acl_gemm_sve_data; diff --git a/tests/cpu/sve/arithmetic/adcx_adox_interleaved_arm_sve.cpp b/tests/cpu/sve/arithmetic/adcx_adox_interleaved_arm_sve.cpp index c1c1eab51..ec2595260 100644 --- a/tests/cpu/sve/arithmetic/adcx_adox_interleaved_arm_sve.cpp +++ b/tests/cpu/sve/arithmetic/adcx_adox_interleaved_arm_sve.cpp @@ -23,11 +23,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif namespace { /* ODR: per-TU TestData (66-file same-name hazard) */ @@ -123,12 +119,13 @@ static size_t adcx_adox_interleaved_arm_sve_count(struct test *test) static int adcx_adox_interleaved_arm_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for adcx_adox_interleaved_arm_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = new TestData; if (!data) return EXIT_FAILURE; diff --git a/tests/cpu/sve/arithmetic/adcx_adox_interleaved_sve.cpp b/tests/cpu/sve/arithmetic/adcx_adox_interleaved_sve.cpp index 4d1124bef..d92a3da67 100644 --- a/tests/cpu/sve/arithmetic/adcx_adox_interleaved_sve.cpp +++ b/tests/cpu/sve/arithmetic/adcx_adox_interleaved_sve.cpp @@ -23,11 +23,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif namespace { /* ODR: per-TU TestData (66-file same-name hazard) */ @@ -123,12 +119,13 @@ static size_t adcx_adox_interleaved_sve_count(struct test *test) static int adcx_adox_interleaved_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for adcx_adox_interleaved_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = new TestData; if (!data) return EXIT_FAILURE; diff --git a/tests/cpu/sve/arithmetic/adcx_arm_sve.cpp b/tests/cpu/sve/arithmetic/adcx_arm_sve.cpp index 5809022d8..9530842a2 100644 --- a/tests/cpu/sve/arithmetic/adcx_arm_sve.cpp +++ b/tests/cpu/sve/arithmetic/adcx_arm_sve.cpp @@ -22,11 +22,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif namespace { /* ODR: per-TU TestData (66-file same-name hazard) */ @@ -121,12 +117,13 @@ static size_t adcx_arm_sve_count(struct test *test) static int adcx_arm_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for adcx_arm_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = new TestData; if (!data) return EXIT_FAILURE; diff --git a/tests/cpu/sve/arithmetic/adcx_sve.cpp b/tests/cpu/sve/arithmetic/adcx_sve.cpp index 81bbcf368..c27cbde3e 100644 --- a/tests/cpu/sve/arithmetic/adcx_sve.cpp +++ b/tests/cpu/sve/arithmetic/adcx_sve.cpp @@ -22,11 +22,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif namespace { /* ODR: per-TU TestData (66-file same-name hazard) */ @@ -122,12 +118,13 @@ static size_t adcx_sve_count(struct test *test) static int adcx_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for adcx_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = new TestData; if (!data) return EXIT_FAILURE; diff --git a/tests/cpu/sve/arithmetic/adcxlong_arm_sve.cpp b/tests/cpu/sve/arithmetic/adcxlong_arm_sve.cpp index 8dd5eacc4..6b0fe0df3 100644 --- a/tests/cpu/sve/arithmetic/adcxlong_arm_sve.cpp +++ b/tests/cpu/sve/arithmetic/adcxlong_arm_sve.cpp @@ -22,11 +22,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif namespace { /* ODR: per-TU TestData (66-file same-name hazard) */ @@ -122,12 +118,13 @@ static size_t adcxlong_arm_sve_count(struct test *test) static int adcxlong_arm_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for adcxlong_arm_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = new TestData; if (!data) return EXIT_FAILURE; diff --git a/tests/cpu/sve/arithmetic/adcxlong_sve.cpp b/tests/cpu/sve/arithmetic/adcxlong_sve.cpp index b8f2f10ce..22b032c30 100644 --- a/tests/cpu/sve/arithmetic/adcxlong_sve.cpp +++ b/tests/cpu/sve/arithmetic/adcxlong_sve.cpp @@ -22,11 +22,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif namespace { /* ODR: per-TU TestData (66-file same-name hazard) */ @@ -122,12 +118,13 @@ static size_t adcxlong_sve_count(struct test *test) static int adcxlong_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for adcxlong_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = new TestData; if (!data) return EXIT_FAILURE; diff --git a/tests/cpu/sve/arithmetic/adox_arm_sve.cpp b/tests/cpu/sve/arithmetic/adox_arm_sve.cpp index 0406d0b11..acc66a779 100644 --- a/tests/cpu/sve/arithmetic/adox_arm_sve.cpp +++ b/tests/cpu/sve/arithmetic/adox_arm_sve.cpp @@ -22,11 +22,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif namespace { /* ODR: per-TU TestData (66-file same-name hazard) */ @@ -122,12 +118,13 @@ static size_t adox_arm_sve_count(struct test *test) static int adox_arm_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for adox_arm_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = new TestData; if (!data) return EXIT_FAILURE; diff --git a/tests/cpu/sve/arithmetic/adox_sve.cpp b/tests/cpu/sve/arithmetic/adox_sve.cpp index ed3dc8a1e..674da7922 100644 --- a/tests/cpu/sve/arithmetic/adox_sve.cpp +++ b/tests/cpu/sve/arithmetic/adox_sve.cpp @@ -22,11 +22,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif namespace { /* ODR: per-TU TestData (66-file same-name hazard) */ @@ -121,12 +117,13 @@ static size_t adox_sve_count(struct test *test) static int adox_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for adox_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = new TestData; if (!data) return EXIT_FAILURE; diff --git a/tests/cpu/sve/arithmetic/bigint_mulx_sve.cpp b/tests/cpu/sve/arithmetic/bigint_mulx_sve.cpp index 802c072cb..51af83712 100644 --- a/tests/cpu/sve/arithmetic/bigint_mulx_sve.cpp +++ b/tests/cpu/sve/arithmetic/bigint_mulx_sve.cpp @@ -23,11 +23,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr int NUM_WORDS = 8; // 512 位 = 8 × 64 位 @@ -94,12 +90,13 @@ static void sw_bigint_mul512(const uint64_t *a, const uint64_t *b, uint64_t *out static int bigint_mulx_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for bigint_mulx_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = new TestData; diff --git a/tests/cpu/sve/arithmetic/crt_builtins_sve.cpp b/tests/cpu/sve/arithmetic/crt_builtins_sve.cpp index 55b76d53a..cbaee63a8 100644 --- a/tests/cpu/sve/arithmetic/crt_builtins_sve.cpp +++ b/tests/cpu/sve/arithmetic/crt_builtins_sve.cpp @@ -29,11 +29,7 @@ #include "sdc_stress_config.h" #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif /* compiler-rt soft-float builtins: IEEE-754 implemented in integer ALU. @@ -81,12 +77,13 @@ static size_t crt_builtins_sve_count(struct test *test) static int crt_builtins_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for crt_builtins_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif crt_data *data = new crt_data; const size_t CRT_N = crt_builtins_sve_count(test); diff --git a/tests/cpu/sve/arithmetic/fisttp_sve.cpp b/tests/cpu/sve/arithmetic/fisttp_sve.cpp index b0e881966..ade11634f 100644 --- a/tests/cpu/sve/arithmetic/fisttp_sve.cpp +++ b/tests/cpu/sve/arithmetic/fisttp_sve.cpp @@ -26,11 +26,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif /* 元素数 NUM_ELEMENTS(1024) — 运行时可配置, 统一优先级链: @@ -72,12 +68,13 @@ static inline int32_t truncate_to_int(float val) { static int fisttp_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fisttp_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *d = new (std::nothrow) FisttpSveData; diff --git a/tests/cpu/sve/arithmetic/gmp_bigadd_sve.cpp b/tests/cpu/sve/arithmetic/gmp_bigadd_sve.cpp index 8da57c4f7..864ba32a8 100644 --- a/tests/cpu/sve/arithmetic/gmp_bigadd_sve.cpp +++ b/tests/cpu/sve/arithmetic/gmp_bigadd_sve.cpp @@ -25,11 +25,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr size_t GMP_SVE_LIMBS = 256; /* 2048-bit operands */ @@ -73,12 +69,13 @@ static size_t gmp_bigadd_sve_limbs(struct test *test) static int gmp_bigadd_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for gmp_bigadd_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *d = new GmpBigaddSveData; const size_t LIMBS = gmp_bigadd_sve_limbs(test); diff --git a/tests/cpu/sve/arithmetic/gmp_bignum_sve.cpp b/tests/cpu/sve/arithmetic/gmp_bignum_sve.cpp index 8edaf71c8..e9e6da22b 100644 --- a/tests/cpu/sve/arithmetic/gmp_bignum_sve.cpp +++ b/tests/cpu/sve/arithmetic/gmp_bignum_sve.cpp @@ -23,11 +23,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr int NUM_WORDS = 8; // 512 位 = 8 × 64 位 @@ -94,12 +90,13 @@ static void sw_bigint_mul512(const uint64_t *a, const uint64_t *b, uint64_t *out static int gmp_bignum_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for gmp_bignum_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = new TestData; diff --git a/tests/cpu/sve/arithmetic/iex_operand_combo_sve.cpp b/tests/cpu/sve/arithmetic/iex_operand_combo_sve.cpp index 41e1d3aa9..b3f763a78 100644 --- a/tests/cpu/sve/arithmetic/iex_operand_combo_sve.cpp +++ b/tests/cpu/sve/arithmetic/iex_operand_combo_sve.cpp @@ -32,11 +32,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr size_t COMBO_STEPS = 1024; // serial ALU steps per chain @@ -252,12 +248,13 @@ static uint64_t flag_chain_run_sub(const IexComboSveData *d, uint64_t seed) static int iex_operand_combo_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for iex_operand_combo_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif const size_t STEPS = iex_operand_combo_sve_steps(test); try { diff --git a/tests/cpu/sve/arithmetic/operand_space_sve.cpp b/tests/cpu/sve/arithmetic/operand_space_sve.cpp index c89c2d8ca..6756f01cc 100644 --- a/tests/cpu/sve/arithmetic/operand_space_sve.cpp +++ b/tests/cpu/sve/arithmetic/operand_space_sve.cpp @@ -30,11 +30,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr size_t NUM_WORDS = 4; @@ -160,12 +156,13 @@ static inline uint64_t slf_probe(const uint64_t *src, uint64_t *buf, size_t n) static int operand_space_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for operand_space_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif const size_t NUM_P = operand_space_sve_num_pairs(test); try { diff --git a/tests/cpu/sve/case/mite_sve.cpp b/tests/cpu/sve/case/mite_sve.cpp index c84550392..e216891d6 100644 --- a/tests/cpu/sve/case/mite_sve.cpp +++ b/tests/cpu/sve/case/mite_sve.cpp @@ -19,11 +19,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MITE_SVE_ITERATIONS 1024 @@ -83,12 +79,11 @@ static inline uint32_t process_value_ref(uint32_t w0_val) static int mite_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mite_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (MiteSveData *)malloc(sizeof(MiteSveData)); data->count = mite_sve_count(test); diff --git a/tests/cpu/sve/case/movbe_dump_golden_sve.cpp b/tests/cpu/sve/case/movbe_dump_golden_sve.cpp index a59c43293..dbdbf2594 100644 --- a/tests/cpu/sve/case/movbe_dump_golden_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_golden_sve.cpp @@ -49,11 +49,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MOVBE_DUMP_GOLDEN_SVE_BUFFER_SIZE (1 << 14) @@ -66,12 +62,11 @@ struct MovbeDumpGoldenSveData { static int movbe_dump_golden_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_golden_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MovbeDumpGoldenSveData))); data->input = static_cast(aligned_alloc_safe(64, MOVBE_DUMP_GOLDEN_SVE_BUFFER_SIZE * sizeof(uint32_t))); diff --git a/tests/cpu/sve/case/movbe_dump_probe_a_sve.cpp b/tests/cpu/sve/case/movbe_dump_probe_a_sve.cpp index eb0009215..0eda20009 100644 --- a/tests/cpu/sve/case/movbe_dump_probe_a_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_probe_a_sve.cpp @@ -22,11 +22,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -39,12 +41,11 @@ struct movbe_dump_probe_a_sve_data { static int movbe_dump_probe_a_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_probe_a_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_dump_probe_a_sve_data *)malloc(sizeof(movbe_dump_probe_a_sve_data)); data->input = (uint32_t *)aligned_alloc_safe(64, MOVBE_BUFFER_SIZE * sizeof(uint32_t)); @@ -68,11 +69,14 @@ static int movbe_dump_probe_a_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); TEST_LOOP(test, 1 << 13) { @@ -81,18 +85,18 @@ static int movbe_dump_probe_a_sve_run(struct test *test, int cpu) svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)(n * 4)); /* 载入 n 个 32-bit 元素 (向量) → 字节级重排 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, data->input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); /* PROBE A: no store —— 还原链寄存器直连 (无堆 store/reload 副作用, * 对齐原版 no-store 探针; swapped 缓冲区不触碰) */ svuint8_t vrestored = svtbl_u8(vswapped, vidx); - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值; ONLY on failure: dump input/golden/actual/xor + 字节分解 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/movbe_dump_probe_b_sve.cpp b/tests/cpu/sve/case/movbe_dump_probe_b_sve.cpp index 77d285c41..45fafd097 100644 --- a/tests/cpu/sve/case/movbe_dump_probe_b_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_probe_b_sve.cpp @@ -22,11 +22,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -39,12 +41,11 @@ struct movbe_dump_probe_b_sve_data { static int movbe_dump_probe_b_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_probe_b_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_dump_probe_b_sve_data *)malloc(sizeof(movbe_dump_probe_b_sve_data)); data->input = (uint32_t *)aligned_alloc_safe(64, MOVBE_BUFFER_SIZE * sizeof(uint32_t)); @@ -68,11 +69,14 @@ static int movbe_dump_probe_b_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); TEST_LOOP(test, 1 << 13) { @@ -81,7 +85,7 @@ static int movbe_dump_probe_b_sve_run(struct test *test, int cpu) svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)(n * 4)); /* 载入 n 个 32-bit 元素 (向量) → 字节级重排 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, data->input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); @@ -96,11 +100,11 @@ static int movbe_dump_probe_b_sve_run(struct test *test, int cpu) /* 再交换一次还原 (同一索引表, svtbl 可逆) */ svuint8_t vrestored = svtbl_u8(svld1_u8(pg, (const uint8_t *)(data->swapped + base)), vidx); - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值; ONLY on failure: dump input/golden/actual/xor + 字节分解 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/movbe_dump_probe_c_sve.cpp b/tests/cpu/sve/case/movbe_dump_probe_c_sve.cpp index 73e95d834..d49e710d2 100644 --- a/tests/cpu/sve/case/movbe_dump_probe_c_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_probe_c_sve.cpp @@ -24,11 +24,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -41,12 +43,11 @@ struct movbe_dump_probe_c_sve_data { static int movbe_dump_probe_c_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_probe_c_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_dump_probe_c_sve_data *)malloc(sizeof(movbe_dump_probe_c_sve_data)); data->input = (uint32_t *)aligned_alloc_safe(64, MOVBE_BUFFER_SIZE * sizeof(uint32_t)); @@ -70,11 +71,14 @@ static int movbe_dump_probe_c_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); /* 每线程私有副本 (SLF 探针, 消除多写者竞争) */ @@ -90,7 +94,7 @@ static int movbe_dump_probe_c_sve_run(struct test *test, int cpu) svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)(n * 4)); /* 载入 n 个 32-bit 元素 (向量) → 字节级重排 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, priv_input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); @@ -106,11 +110,11 @@ static int movbe_dump_probe_c_sve_run(struct test *test, int cpu) /* 再交换一次还原 (同一索引表, svtbl 可逆) */ svuint8_t vrestored = svtbl_u8(reloaded, vidx); - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值; ONLY on failure: dump input/golden/actual/xor + 字节分解 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/movbe_dump_probe_d_sve.cpp b/tests/cpu/sve/case/movbe_dump_probe_d_sve.cpp index 9a0f05edf..987ae047e 100644 --- a/tests/cpu/sve/case/movbe_dump_probe_d_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_probe_d_sve.cpp @@ -22,11 +22,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -39,12 +41,11 @@ struct movbe_dump_probe_d_sve_data { static int movbe_dump_probe_d_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_probe_d_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_dump_probe_d_sve_data *)malloc(sizeof(movbe_dump_probe_d_sve_data)); data->input = (uint32_t *)aligned_alloc_safe(64, MOVBE_BUFFER_SIZE * sizeof(uint32_t)); @@ -68,11 +69,14 @@ static int movbe_dump_probe_d_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); TEST_LOOP(test, 1 << 13) { @@ -81,7 +85,7 @@ static int movbe_dump_probe_d_sve_run(struct test *test, int cpu) svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)(n * 4)); /* 载入 n 个 32-bit 元素 (向量) → 字节级重排 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, data->input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); @@ -96,11 +100,11 @@ static int movbe_dump_probe_d_sve_run(struct test *test, int cpu) /* 再交换一次还原 (同一索引表, svtbl 可逆) */ svuint8_t vrestored = svtbl_u8(svld1_u8(pg, (const uint8_t *)(data->swapped + base)), vidx); - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值; ONLY on failure: dump input/golden/actual/xor + 字节分解 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/movbe_dump_probe_e_sve.cpp b/tests/cpu/sve/case/movbe_dump_probe_e_sve.cpp index da442d030..bf806760c 100644 --- a/tests/cpu/sve/case/movbe_dump_probe_e_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_probe_e_sve.cpp @@ -26,11 +26,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -43,12 +45,11 @@ struct movbe_dump_probe_e_sve_data { static int movbe_dump_probe_e_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_probe_e_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_dump_probe_e_sve_data *)malloc(sizeof(movbe_dump_probe_e_sve_data)); data->input = (uint32_t *)aligned_alloc_safe(64, MOVBE_BUFFER_SIZE * sizeof(uint32_t)); @@ -76,11 +77,14 @@ static int movbe_dump_probe_e_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); TEST_LOOP(test, 1 << 13) { @@ -89,7 +93,7 @@ static int movbe_dump_probe_e_sve_run(struct test *test, int cpu) svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)(n * 4)); /* 载入 n 个 32-bit 元素 (向量) → 字节级重排 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, data->input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); @@ -101,11 +105,11 @@ static int movbe_dump_probe_e_sve_run(struct test *test, int cpu) /* 再交换一次还原 (同一索引表, svtbl 可逆) */ svuint8_t vrestored = svtbl_u8(reloaded, vidx); - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值; ONLY on failure: dump input/golden/actual/xor + 字节分解 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/movbe_dump_probe_f_sve.cpp b/tests/cpu/sve/case/movbe_dump_probe_f_sve.cpp index 06dd42bad..14b40438e 100644 --- a/tests/cpu/sve/case/movbe_dump_probe_f_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_probe_f_sve.cpp @@ -23,11 +23,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -40,12 +42,11 @@ struct movbe_dump_probe_f_sve_data { static int movbe_dump_probe_f_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_probe_f_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_dump_probe_f_sve_data *)malloc(sizeof(movbe_dump_probe_f_sve_data)); data->input = (uint32_t *)aligned_alloc_safe(64, MOVBE_BUFFER_SIZE * sizeof(uint32_t)); @@ -75,11 +76,14 @@ static int movbe_dump_probe_f_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); TEST_LOOP(test, 1 << 13) { @@ -88,7 +92,7 @@ static int movbe_dump_probe_f_sve_run(struct test *test, int cpu) svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)(n * 4)); /* 载入 n 个 32-bit 元素 (向量) → 字节级重排 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, data->input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); @@ -108,11 +112,11 @@ static int movbe_dump_probe_f_sve_run(struct test *test, int cpu) /* 再交换一次还原 (同一索引表, svtbl 可逆) */ svuint8_t vrestored = svtbl_u8(vswapped, vidx); /* 寄存器直连: 原版 bswap 作用于寄存器值, 这些 probe 被测的是 store 侧效应 */ - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值; ONLY on failure: dump input/golden/actual/xor + 字节分解 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/movbe_dump_probe_g1_sve.cpp b/tests/cpu/sve/case/movbe_dump_probe_g1_sve.cpp index 508017ce1..cb63cd525 100644 --- a/tests/cpu/sve/case/movbe_dump_probe_g1_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_probe_g1_sve.cpp @@ -24,11 +24,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -41,12 +43,11 @@ struct movbe_dump_probe_g1_sve_data { static int movbe_dump_probe_g1_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_probe_g1_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_dump_probe_g1_sve_data *)malloc(sizeof(movbe_dump_probe_g1_sve_data)); data->input = (uint32_t *)aligned_alloc_safe(64, MOVBE_BUFFER_SIZE * sizeof(uint32_t)); @@ -77,11 +78,14 @@ static int movbe_dump_probe_g1_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); TEST_LOOP(test, 1 << 13) { @@ -90,7 +94,7 @@ static int movbe_dump_probe_g1_sve_run(struct test *test, int cpu) svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)(n * 4)); /* 载入 n 个 32-bit 元素 (向量) → 字节级重排 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, data->input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); @@ -107,11 +111,11 @@ static int movbe_dump_probe_g1_sve_run(struct test *test, int cpu) /* 再交换一次还原 (同一索引表, svtbl 可逆) */ svuint8_t vrestored = svtbl_u8(vswapped, vidx); /* 寄存器直连: 原版 bswap 作用于寄存器值, 这些 probe 被测的是 store 侧效应 */ - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值; ONLY on failure: dump input/golden/actual/xor + 字节分解 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/movbe_dump_probe_g2_sve.cpp b/tests/cpu/sve/case/movbe_dump_probe_g2_sve.cpp index 4d1ce7316..4dc9433db 100644 --- a/tests/cpu/sve/case/movbe_dump_probe_g2_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_probe_g2_sve.cpp @@ -23,11 +23,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -40,12 +42,11 @@ struct movbe_dump_probe_g2_sve_data { static int movbe_dump_probe_g2_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_probe_g2_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_dump_probe_g2_sve_data *)malloc(sizeof(movbe_dump_probe_g2_sve_data)); data->input = (uint32_t *)aligned_alloc_safe(64, MOVBE_BUFFER_SIZE * sizeof(uint32_t)); @@ -75,11 +76,14 @@ static int movbe_dump_probe_g2_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); TEST_LOOP(test, 1 << 13) { @@ -88,7 +92,7 @@ static int movbe_dump_probe_g2_sve_run(struct test *test, int cpu) svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)(n * 4)); /* 载入 n 个 32-bit 元素 (向量) → 字节级重排 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, data->input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); @@ -102,11 +106,11 @@ static int movbe_dump_probe_g2_sve_run(struct test *test, int cpu) /* 再交换一次还原 (同一索引表, svtbl 可逆) */ svuint8_t vrestored = svtbl_u8(vswapped, vidx); /* 寄存器直连: 原版 bswap 作用于寄存器值, 这些 probe 被测的是 store 侧效应 */ - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值; ONLY on failure: dump input/golden/actual/xor + 字节分解 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/movbe_dump_probe_h_sve.cpp b/tests/cpu/sve/case/movbe_dump_probe_h_sve.cpp index c69b1225d..3348308c2 100644 --- a/tests/cpu/sve/case/movbe_dump_probe_h_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_probe_h_sve.cpp @@ -24,11 +24,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -41,12 +43,11 @@ struct movbe_dump_probe_h_sve_data { static int movbe_dump_probe_h_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_probe_h_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_dump_probe_h_sve_data *)malloc(sizeof(movbe_dump_probe_h_sve_data)); data->input = (uint32_t *)aligned_alloc_safe(64, MOVBE_BUFFER_SIZE * sizeof(uint32_t)); @@ -70,11 +71,14 @@ static int movbe_dump_probe_h_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); TEST_LOOP(test, 1 << 13) { @@ -83,7 +87,7 @@ static int movbe_dump_probe_h_sve_run(struct test *test, int cpu) svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)(n * 4)); /* 载入 n 个 32-bit 元素 (向量) → 字节级重排 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, data->input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); @@ -102,11 +106,11 @@ static int movbe_dump_probe_h_sve_run(struct test *test, int cpu) /* 再交换一次还原 (同一索引表, svtbl 可逆) */ svuint8_t vrestored = svtbl_u8(vswapped, vidx); /* 寄存器直连: 原版 bswap 作用于寄存器值, 这些 probe 被测的是 store 侧效应 */ - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值; ONLY on failure: dump input/golden/actual/xor + 字节分解 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/movbe_dump_probe_x_sve.cpp b/tests/cpu/sve/case/movbe_dump_probe_x_sve.cpp index 883e18d62..72df1993b 100644 --- a/tests/cpu/sve/case/movbe_dump_probe_x_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_probe_x_sve.cpp @@ -22,11 +22,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -39,12 +41,11 @@ struct movbe_dump_probe_x_sve_data { static int movbe_dump_probe_x_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_probe_x_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_dump_probe_x_sve_data *)malloc(sizeof(movbe_dump_probe_x_sve_data)); data->input = (uint32_t *)aligned_alloc_safe(64, MOVBE_BUFFER_SIZE * sizeof(uint32_t)); @@ -68,11 +69,14 @@ static int movbe_dump_probe_x_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); TEST_LOOP(test, 1 << 13) { @@ -81,7 +85,7 @@ static int movbe_dump_probe_x_sve_run(struct test *test, int cpu) svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)(n * 4)); /* 载入 n 个 32-bit 元素 (向量) → 字节级重排 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, data->input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); @@ -96,11 +100,11 @@ static int movbe_dump_probe_x_sve_run(struct test *test, int cpu) /* 再交换一次还原 (同一索引表, svtbl 可逆) */ svuint8_t vrestored = svtbl_u8(svld1_u8(pg, (const uint8_t *)(data->swapped + base)), vidx); - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值; ONLY on failure: dump input/golden/actual/xor + 字节分解 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/movbe_dump_probe_xn_sve.cpp b/tests/cpu/sve/case/movbe_dump_probe_xn_sve.cpp index 383395525..aeefcf903 100644 --- a/tests/cpu/sve/case/movbe_dump_probe_xn_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_probe_xn_sve.cpp @@ -24,11 +24,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -41,12 +43,11 @@ struct movbe_dump_probe_xn_sve_data { static int movbe_dump_probe_xn_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_probe_xn_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_dump_probe_xn_sve_data *)malloc(sizeof(movbe_dump_probe_xn_sve_data)); data->input = (uint32_t *)aligned_alloc_safe(64, MOVBE_BUFFER_SIZE * sizeof(uint32_t)); @@ -70,11 +71,14 @@ static int movbe_dump_probe_xn_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); TEST_LOOP(test, 1 << 13) { @@ -83,7 +87,7 @@ static int movbe_dump_probe_xn_sve_run(struct test *test, int cpu) svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)(n * 4)); /* 载入 n 个 32-bit 元素 (向量) → 字节级重排 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, data->input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); @@ -102,11 +106,11 @@ static int movbe_dump_probe_xn_sve_run(struct test *test, int cpu) /* 再交换一次还原 (同一索引表, svtbl 可逆) */ svuint8_t vrestored = svtbl_u8(svld1_u8(pg, (const uint8_t *)(data->swapped + base)), vidx); - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值; ONLY on failure: dump input/golden/actual/xor + 字节分解 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/movbe_dump_sve.cpp b/tests/cpu/sve/case/movbe_dump_sve.cpp index 2dc352ea8..e0a293c51 100644 --- a/tests/cpu/sve/case/movbe_dump_sve.cpp +++ b/tests/cpu/sve/case/movbe_dump_sve.cpp @@ -21,11 +21,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -38,12 +40,11 @@ struct movbe_dump_sve_data { static int movbe_dump_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_dump_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_dump_sve_data *)malloc(sizeof(movbe_dump_sve_data)); data->input = (uint32_t *)aligned_alloc_safe(64, MOVBE_BUFFER_SIZE * sizeof(uint32_t)); @@ -67,11 +68,14 @@ static int movbe_dump_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); TEST_LOOP(test, 1 << 13) { @@ -80,7 +84,7 @@ static int movbe_dump_sve_run(struct test *test, int cpu) svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)(n * 4)); /* 载入 n 个 32-bit 元素 (向量) → 字节级重排 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, data->input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); @@ -92,11 +96,11 @@ static int movbe_dump_sve_run(struct test *test, int cpu) /* 再交换一次还原 (同一索引表, svtbl 可逆) */ svuint8_t vrestored = svtbl_u8(reloaded, vidx); - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值; ONLY on failure: dump input/golden/actual/xor + 字节分解 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/movbe_l1d_vs_l2_sve.cpp b/tests/cpu/sve/case/movbe_l1d_vs_l2_sve.cpp index 4f9ad01f0..45b3d9699 100644 --- a/tests/cpu/sve/case/movbe_l1d_vs_l2_sve.cpp +++ b/tests/cpu/sve/case/movbe_l1d_vs_l2_sve.cpp @@ -71,11 +71,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MOVBE_L1D_SVE_BUFFER_SIZE (1 << 14) @@ -120,12 +116,11 @@ struct MovbeL1dL2SveData { static int movbe_l1d_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_l1d_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MovbeL1dL2SveData))); data->count = movbe_l1d_sve_count(test); diff --git a/tests/cpu/sve/case/movbe_slf_sweep_sve.cpp b/tests/cpu/sve/case/movbe_slf_sweep_sve.cpp index b3e1ba76d..f74fd1c4a 100644 --- a/tests/cpu/sve/case/movbe_slf_sweep_sve.cpp +++ b/tests/cpu/sve/case/movbe_slf_sweep_sve.cpp @@ -39,11 +39,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif /* 64KB 扫描缓冲 (16384 u32, 按 u32 填充; 运行时按字节扫描 — 与元素宽度解耦)。 @@ -203,12 +199,11 @@ static void slf_sweep_selfcheck(int width) static int movbe_slf_sweep_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_slf_sweep_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_slf_sweep_sve_data *)malloc(sizeof(movbe_slf_sweep_sve_data)); data->buffer_bytes = movbe_slf_sweep_sve_buffer_bytes(test); diff --git a/tests/cpu/sve/case/movbe_sve.cpp b/tests/cpu/sve/case/movbe_sve.cpp index 60e6177c8..01bd4ce46 100644 --- a/tests/cpu/sve/case/movbe_sve.cpp +++ b/tests/cpu/sve/case/movbe_sve.cpp @@ -22,11 +22,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_dump_golden 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MOVBE_BUFFER_SIZE (1 << 14) @@ -70,12 +72,11 @@ struct movbe_sve_data { static int movbe_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movbe_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movbe_sve_data *)malloc(sizeof(movbe_sve_data)); data->count = movbe_sve_count(test); @@ -112,11 +113,14 @@ static int movbe_sve_run(struct test *test, int cpu) static const uint8_t idx4[4] = {3, 2, 1, 0}; const int lanes = svcntw(); - uint8_t vidx_bytes[64]; - for (int i = 0; i < lanes && i < 16; ++i) + /* 索引按运行时 VL 定容: svcntw()*4 = svcntb() ≤ 256 = 架构最大 VL + * (movbe_dump_golden/slf_sweep VL-portable 范式); 原 64 字节 cap 在 + * lanes>16 时使尾部 lane 索引为垃圾 → 确定性误报 + 失败路径栈越界 */ + uint8_t vidx_bytes[SVE_MAX_VECTOR_BYTES]; + for (int i = 0; i < lanes; ++i) for (int b = 0; b < 4; ++b) vidx_bytes[i * 4 + b] = (uint8_t)(i * 4 + idx4[b]); - svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)(lanes < 16 ? lanes * 4 : 64)); + svbool_t pg_batch = svwhilelt_b8((uint64_t)0, (uint64_t)lanes * 4); svuint8_t vidx = svld1_u8(pg_batch, vidx_bytes); TEST_LOOP(test, 1 << 13) { @@ -126,7 +130,7 @@ static int movbe_sve_run(struct test *test, int cpu) /* 直接堆访存 (无栈中转): 修复版 —— 原版被测路径是 * 堆 store(swapped) 后紧跟堆 reload, 栈中转会改变被测微操作序列 */ - uint8_t in_bytes[64]; + uint8_t in_bytes[SVE_MAX_VECTOR_BYTES]; memcpy(in_bytes, data->input + base, n * 4); svuint8_t vswapped = svtbl_u8(svld1_u8(pg, in_bytes), vidx); @@ -138,11 +142,11 @@ static int movbe_sve_run(struct test *test, int cpu) /* 再交换一次还原 (同一索引表, svtbl 可逆) */ svuint8_t vrestored = svtbl_u8(reloaded, vidx); - uint8_t out_bytes[64]; + uint8_t out_bytes[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, out_bytes, vrestored); /* 校验: 还原值 == 输入值 */ - uint32_t restored[16]; + uint32_t restored[SVE_MAX_VECTOR_BYTES / 4]; memcpy(restored, out_bytes, n * 4); for (int i = 0; i < n; ++i) { if (restored[i] != data->input[base + i]) { diff --git a/tests/cpu/sve/case/mrn_flags_sve.cpp b/tests/cpu/sve/case/mrn_flags_sve.cpp index 5c699eae6..617c1cb26 100644 --- a/tests/cpu/sve/case/mrn_flags_sve.cpp +++ b/tests/cpu/sve/case/mrn_flags_sve.cpp @@ -19,11 +19,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_FLAGS_SVE_COUNT 1024 @@ -67,12 +63,11 @@ struct MrnFlagsSveData { static int mrn_flags_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_flags_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnFlagsSveData))); data->count = mrn_flags_sve_count(test); diff --git a/tests/cpu/sve/case/mrn_nuke_2src_alu_sve.cpp b/tests/cpu/sve/case/mrn_nuke_2src_alu_sve.cpp index 70875950d..002a46150 100644 --- a/tests/cpu/sve/case/mrn_nuke_2src_alu_sve.cpp +++ b/tests/cpu/sve/case/mrn_nuke_2src_alu_sve.cpp @@ -32,11 +32,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_NUKE_2SRC_ALU_SVE_COUNT 1024 @@ -81,12 +77,11 @@ struct MrnNuke2srcAluSveData { static int mrn_nuke_2src_alu_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_nuke_2src_alu_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnNuke2srcAluSveData))); data->count = mrn_nuke_2src_alu_sve_count(test); diff --git a/tests/cpu/sve/case/mrn_nuke_3src_alu_sve.cpp b/tests/cpu/sve/case/mrn_nuke_3src_alu_sve.cpp index 7ede5ab31..0f7eb2cc3 100644 --- a/tests/cpu/sve/case/mrn_nuke_3src_alu_sve.cpp +++ b/tests/cpu/sve/case/mrn_nuke_3src_alu_sve.cpp @@ -31,11 +31,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_NUKE_3SRC_ALU_SVE_COUNT 1024 @@ -81,12 +77,11 @@ struct MrnNuke3srcAluSveData { static int mrn_nuke_3src_alu_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_nuke_3src_alu_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnNuke3srcAluSveData))); data->count = mrn_nuke_3src_alu_sve_count(test); diff --git a/tests/cpu/sve/case/mrn_nuke_4src_alu_sve.cpp b/tests/cpu/sve/case/mrn_nuke_4src_alu_sve.cpp index 400e13c1e..953aeffdb 100644 --- a/tests/cpu/sve/case/mrn_nuke_4src_alu_sve.cpp +++ b/tests/cpu/sve/case/mrn_nuke_4src_alu_sve.cpp @@ -29,11 +29,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_NUKE_4SRC_ALU_SVE_COUNT 1024 @@ -80,12 +76,11 @@ struct MrnNuke4srcAluSveData { static int mrn_nuke_4src_alu_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_nuke_4src_alu_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnNuke4srcAluSveData))); data->count = mrn_nuke_4src_alu_sve_count(test); diff --git a/tests/cpu/sve/case/mrn_nuke_dense_sve.cpp b/tests/cpu/sve/case/mrn_nuke_dense_sve.cpp index 6c354fc04..1381abe07 100644 --- a/tests/cpu/sve/case/mrn_nuke_dense_sve.cpp +++ b/tests/cpu/sve/case/mrn_nuke_dense_sve.cpp @@ -24,11 +24,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_NUKE_DENSE_SVE_COUNT 16384 /* 16x the 1024-element family default */ @@ -71,12 +67,11 @@ struct MrnNukeDenseSveData { static int mrn_nuke_dense_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_nuke_dense_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnNukeDenseSveData))); data->count = mrn_nuke_dense_sve_count(test); diff --git a/tests/cpu/sve/case/mrn_nuke_sve.cpp b/tests/cpu/sve/case/mrn_nuke_sve.cpp index 58d64fa2f..855f43a95 100644 --- a/tests/cpu/sve/case/mrn_nuke_sve.cpp +++ b/tests/cpu/sve/case/mrn_nuke_sve.cpp @@ -19,11 +19,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_NUKE_SVE_COUNT 1024 @@ -66,12 +62,11 @@ struct MrnNukeSveData { static int mrn_nuke_sve_init(struct test *test) {{ #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) {{ - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_nuke_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - }} #endif auto *data = static_cast(malloc(sizeof(MrnNukeSveData))); data->count = mrn_nuke_sve_count(test); diff --git a/tests/cpu/sve/case/mrn_pairs_2src_alu_sve.cpp b/tests/cpu/sve/case/mrn_pairs_2src_alu_sve.cpp index fa53bd775..36dc26f87 100644 --- a/tests/cpu/sve/case/mrn_pairs_2src_alu_sve.cpp +++ b/tests/cpu/sve/case/mrn_pairs_2src_alu_sve.cpp @@ -31,11 +31,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_PAIRS_2SRC_ALU_SVE_COUNT 1024 @@ -80,12 +76,11 @@ struct MrnPairs2srcAluSveData { static int mrn_pairs_2src_alu_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_pairs_2src_alu_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnPairs2srcAluSveData))); data->count = mrn_pairs_2src_alu_sve_count(test); diff --git a/tests/cpu/sve/case/mrn_pairs_sve.cpp b/tests/cpu/sve/case/mrn_pairs_sve.cpp index 62bca5989..e504bad61 100644 --- a/tests/cpu/sve/case/mrn_pairs_sve.cpp +++ b/tests/cpu/sve/case/mrn_pairs_sve.cpp @@ -19,11 +19,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_PAIRS_SVE_COUNT 1024 @@ -66,12 +62,11 @@ struct MrnPairsSveData { static int mrn_pairs_sve_init(struct test *test) {{ #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) {{ - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_pairs_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - }} #endif auto *data = static_cast(malloc(sizeof(MrnPairsSveData))); data->count = mrn_pairs_sve_count(test); diff --git a/tests/cpu/sve/case/mrn_reloaded_2src_alu_sve.cpp b/tests/cpu/sve/case/mrn_reloaded_2src_alu_sve.cpp index 5b9b38c68..36a42d1ed 100644 --- a/tests/cpu/sve/case/mrn_reloaded_2src_alu_sve.cpp +++ b/tests/cpu/sve/case/mrn_reloaded_2src_alu_sve.cpp @@ -32,11 +32,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_RELOADED_2SRC_ALU_SVE_COUNT 1024 @@ -81,12 +77,11 @@ struct MrnReloaded2srcAluSveData { static int mrn_reloaded_2src_alu_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_reloaded_2src_alu_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnReloaded2srcAluSveData))); data->count = mrn_reloaded_2src_alu_sve_count(test); diff --git a/tests/cpu/sve/case/mrn_reloaded_sve.cpp b/tests/cpu/sve/case/mrn_reloaded_sve.cpp index bbfd6b784..9298b819c 100644 --- a/tests/cpu/sve/case/mrn_reloaded_sve.cpp +++ b/tests/cpu/sve/case/mrn_reloaded_sve.cpp @@ -19,11 +19,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_slf_sweep 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MRN_RELOADED_SVE_COUNT 256 @@ -69,12 +71,11 @@ struct MrnReloadedSveData { static int mrn_reloaded_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_reloaded_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnReloadedSveData))); data->count = mrn_reloaded_sve_count(test); @@ -104,7 +105,10 @@ static int mrn_reloaded_sve_run(struct test *test, int cpu) int n = (data->count - base < (size_t)svcntb()) ? (int)(data->count - base) : svcntb(); svbool_t pg = svwhilelt_b8((uint64_t)0, (uint64_t)n); svst1_u8(pg, temp8 + base, svld1_u8(pg, data->src8 + base)); - uint8_t got[64]; + /* spill 缓冲按架构最大 VL 定容: svcntb() 最多 256 lane, + * 原 got[64] 在 VL>512-bit 时被 svst1 全宽越界写 (movbe 家族 + * SVE_MAX_VECTOR_BYTES 范式, all-VL Phase 2 P6 收口)。 */ + uint8_t got[SVE_MAX_VECTOR_BYTES]; svst1_u8(pg, got, svld1_u8(pg, temp8 + base)); for (int i = 0; i < n; ++i) if (got[i] != data->src8[base + i]) @@ -118,7 +122,7 @@ static int mrn_reloaded_sve_run(struct test *test, int cpu) int n = (data->count - base < (size_t)svcntw()) ? (int)(data->count - base) : svcntw(); svbool_t pg = svwhilelt_b32((uint64_t)0, (uint64_t)n); svst1_u32(pg, temp32 + base, svld1_u32(pg, data->src32 + base)); - uint32_t got[16]; + uint32_t got[SVE_MAX_VECTOR_BYTES / 4]; svst1_u32(pg, got, svld1_u32(pg, temp32 + base)); for (int i = 0; i < n; ++i) if (got[i] != data->src32[base + i]) @@ -132,7 +136,7 @@ static int mrn_reloaded_sve_run(struct test *test, int cpu) int n = (data->count - base < (size_t)svcntd()) ? (int)(data->count - base) : svcntd(); svbool_t pg = svwhilelt_b64((uint64_t)0, (uint64_t)n); svst1_u64(pg, temp64 + base, svld1_u64(pg, data->src64 + base)); - uint64_t got[8]; + uint64_t got[SVE_MAX_VECTOR_BYTES / 8]; svst1_u64(pg, got, svld1_u64(pg, temp64 + base)); for (int i = 0; i < n; ++i) if (got[i] != data->src64[base + i]) diff --git a/tests/cpu/sve/case/mrn_rmw_diff_footprint_sve.cpp b/tests/cpu/sve/case/mrn_rmw_diff_footprint_sve.cpp index daa23623a..c92208cc2 100644 --- a/tests/cpu/sve/case/mrn_rmw_diff_footprint_sve.cpp +++ b/tests/cpu/sve/case/mrn_rmw_diff_footprint_sve.cpp @@ -43,11 +43,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_RMW_DIFF_64K_SVE_COUNT 8192 /* 64 KB == L1D (thrash edge) */ @@ -127,12 +123,11 @@ static int mrn_rmw_diff_fp_sve_init_common(struct test *test, int count) static int mrn_rmw_diff_64k_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_rmw_diff_64k_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return mrn_rmw_diff_fp_sve_init_common(test, (int)mrn_rmw_diff_fp_base_count(test)); } @@ -140,12 +135,11 @@ static int mrn_rmw_diff_64k_sve_init(struct test *test) static int mrn_rmw_diff_1m_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_rmw_diff_1m_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif /* 1MB 实例 = base*16: ×16 的 L1D-边缘-vs-L2 比率是实验本体 */ return mrn_rmw_diff_fp_sve_init_common( diff --git a/tests/cpu/sve/case/mrn_rmw_dump_sve.cpp b/tests/cpu/sve/case/mrn_rmw_dump_sve.cpp index e814e5369..a5ee9cb70 100644 --- a/tests/cpu/sve/case/mrn_rmw_dump_sve.cpp +++ b/tests/cpu/sve/case/mrn_rmw_dump_sve.cpp @@ -17,11 +17,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_slf_sweep 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MRN_RMW_SVE_COUNT 1024 @@ -66,12 +68,11 @@ struct MrnRmwSveData { static int mrn_rmw_dump_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_rmw_dump_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnRmwSveData))); data->count = mrn_rmw_dump_sve_count(test); @@ -115,8 +116,11 @@ static int mrn_rmw_dump_sve_run(struct test *test, int cpu) svuint64_t r_sub = svsub_u64_x(pg, va, vb); svuint64_t r_eor = sveor_u64_x(pg, va, vb); svuint64_t r_and = svand_u64_x(pg, va, vb); - /* 相位谓词: lane k → (base+k)%4 */ - uint64_t phase[8]; + /* 相位谓词: lane k → (base+k)%4 (phase 缓冲按架构最大 VL + * 定容: svcntd() 最多 32 lane, 原 phase[8] 在 VL>512-bit 时 + * 被 svld1_u64 全宽越界读 + 填充循环越界写, mrn_rmw/ + * nuke_2src_alu 同款 SVE_MAX_VECTOR_BYTES 范式) */ + uint64_t phase[SVE_MAX_VECTOR_BYTES / 8]; for (int k = 0; k < n; ++k) phase[k] = (base + k) % 4; svuint64_t vphase = svld1_u64(pg, phase); svuint64_t res = svsel_u64(svcmpeq_n_u64(pg, vphase, 0), r_add, diff --git a/tests/cpu/sve/case/mrn_rmw_fwd_vs_diff_sve.cpp b/tests/cpu/sve/case/mrn_rmw_fwd_vs_diff_sve.cpp index cb0f88b45..fbd2a69cf 100644 --- a/tests/cpu/sve/case/mrn_rmw_fwd_vs_diff_sve.cpp +++ b/tests/cpu/sve/case/mrn_rmw_fwd_vs_diff_sve.cpp @@ -55,11 +55,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_RMW_DIFF_SVE_COUNT 1024 @@ -106,12 +102,11 @@ struct MrnRmwDiffSveData { static int mrn_rmw_diff_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_rmw_diff_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnRmwDiffSveData))); data->count = mrn_rmw_diff_sve_count(test); diff --git a/tests/cpu/sve/case/mrn_rmw_fwd_vs_l1d_sve.cpp b/tests/cpu/sve/case/mrn_rmw_fwd_vs_l1d_sve.cpp index 59f4a9b24..f3359f601 100644 --- a/tests/cpu/sve/case/mrn_rmw_fwd_vs_l1d_sve.cpp +++ b/tests/cpu/sve/case/mrn_rmw_fwd_vs_l1d_sve.cpp @@ -56,11 +56,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_RMW_FWD_SVE_COUNT 1024 @@ -107,12 +103,11 @@ struct MrnRmwFwdL1dSveData { static int mrn_rmw_fwd_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_rmw_fwd_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnRmwFwdL1dSveData))); data->count = mrn_rmw_fwd_sve_count(test); diff --git a/tests/cpu/sve/case/mrn_rmw_sve.cpp b/tests/cpu/sve/case/mrn_rmw_sve.cpp index dc5a4b155..086fdf14a 100644 --- a/tests/cpu/sve/case/mrn_rmw_sve.cpp +++ b/tests/cpu/sve/case/mrn_rmw_sve.cpp @@ -18,11 +18,13 @@ #if defined(__aarch64__) #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) +#ifndef SVE_MAX_VECTOR_BYTES +/* GCC 12 的 arm_sve.h 不提供该 ACLE 宏 (movbe_slf_sweep 同款自定义): + * SVE 架构最大 VL 2048bit = 256 字节 */ +#define SVE_MAX_VECTOR_BYTES 256 #endif +#include #endif #define MRN_RMW_SVE_COUNT 1024 @@ -67,12 +69,11 @@ struct MrnRmwSveData { static int mrn_rmw_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_rmw_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnRmwSveData))); data->count = mrn_rmw_sve_count(test); @@ -116,8 +117,11 @@ static int mrn_rmw_sve_run(struct test *test, int cpu) svuint64_t r_sub = svsub_u64_x(pg, va, vb); svuint64_t r_eor = sveor_u64_x(pg, va, vb); svuint64_t r_and = svand_u64_x(pg, va, vb); - /* 相位谓词: lane k → (base+k)%4 */ - uint64_t phase[8]; + /* 相位谓词: lane k → (base+k)%4 (phase 缓冲按架构最大 VL + * 定容: svcntd() 最多 32 lane, 原 phase[8] 在 VL>512-bit 时 + * 被 svld1_u64 全宽越界读 + 填充循环越界写, mrn_rmw_dump/ + * nuke_2src_alu 同款 SVE_MAX_VECTOR_BYTES 范式) */ + uint64_t phase[SVE_MAX_VECTOR_BYTES / 8]; for (int k = 0; k < n; ++k) phase[k] = (base + k) % 4; svuint64_t vphase = svld1_u64(pg, phase); svuint64_t res = svsel_u64(svcmpeq_n_u64(pg, vphase, 0), r_add, diff --git a/tests/cpu/sve/case/mrn_rmw_timing_probe_sve.cpp b/tests/cpu/sve/case/mrn_rmw_timing_probe_sve.cpp index 38daf2f8d..30557dffc 100644 --- a/tests/cpu/sve/case/mrn_rmw_timing_probe_sve.cpp +++ b/tests/cpu/sve/case/mrn_rmw_timing_probe_sve.cpp @@ -53,11 +53,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MRN_RMW_NOP_SVE_COUNT 1024 @@ -104,12 +100,11 @@ struct MrnRmwNopSveData { static int mrn_rmw_nop_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mrn_rmw_nop_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MrnRmwNopSveData))); data->count = mrn_rmw_nop_sve_count(test); diff --git a/tests/cpu/sve/case/neon_rot_2src_sve.cpp b/tests/cpu/sve/case/neon_rot_2src_sve.cpp index d4ea2ca71..68e2600cf 100644 --- a/tests/cpu/sve/case/neon_rot_2src_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_2src_sve.cpp @@ -21,11 +21,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_2SRC_SVE_COUNT 1024 /* uint64 elements per buffer */ @@ -67,15 +63,21 @@ static size_t neon_rot_2src_sve_count(struct test *test) static int neon_rot_2src_sve_init(struct test *test) { size_t count = NEON_ROT_2SRC_SVE_COUNT; #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_2src_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } count = neon_rot_2src_sve_count(test); /* asm ldr z/str z 全向量访问: count 向下取整到 svcntd() 的整倍数 (倍数约束保留) */ - const size_t lanes = (size_t)svcntd(); + const size_t lanes = (size_t)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + /* arm64_vl.h unit convention: release-effective range check catches + * a wrong-divisor drift (e.g. svl/4 here would compile silently). */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %zu outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t rem = count - count / lanes * lanes; /* % 表达式触发 GCC SVE ICE, 改用除法组合 */ if (rem != 0) { const size_t rounded = count - rem; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_ldr4_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_ldr4_sve.cpp index b1c05e716..989178703 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_ldr4_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_ldr4_sve.cpp @@ -28,11 +28,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_LDR4_SVE_SLOTS 1024 @@ -75,14 +71,18 @@ static size_t neon_rot_ldr_at_top_ldr4_sve_slots(struct test *test) static int neon_rot_ldr_at_top_ldr4_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_ldr4_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_ldr4_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_mla_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_mla_sve.cpp index a57ebe8c6..8fa9ffcd2 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_mla_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_mla_sve.cpp @@ -34,11 +34,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_MLA_SVE_SLOTS 1024 @@ -80,14 +76,18 @@ static size_t neon_rot_ldr_at_top_mla_sve_slots(struct test *test) static int neon_rot_ldr_at_top_mla_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_mla_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntw(); + const int lanes = (int)(svl / 4); /* f32 lanes = SVL bytes / 4 */ + if (lanes < 4 || lanes > 32) { + log_error("%s: f32 lanes %d outside [4,32] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_mla_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_offdiag_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_offdiag_sve.cpp index 13223c4fe..e5b890240 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_offdiag_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_offdiag_sve.cpp @@ -28,11 +28,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_OFFDIAG_SVE_SLOTS 1024 @@ -73,14 +69,18 @@ static size_t neon_rot_ldr_at_top_offdiag_sve_slots(struct test *test) static int neon_rot_ldr_at_top_offdiag_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_offdiag_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_offdiag_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_dualcmp_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_dualcmp_sve.cpp index 5e4a473df..09d311f78 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_dualcmp_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_dualcmp_sve.cpp @@ -35,11 +35,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_ROWMAJOR_DUALCMP_SVE_SLOTS 1024 @@ -110,14 +106,18 @@ static void dualcmp_sve_classify(const uint64_t *dst, const uint64_t *temp, static int neon_rot_ldr_at_top_rowmajor_dualcmp_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_rowmajor_dualcmp_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_rowmajor_dualcmp_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_dump_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_dump_sve.cpp index 717676421..7f38c3d89 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_dump_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_dump_sve.cpp @@ -40,11 +40,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_ROWMAJOR_DUMP_SVE_SLOTS 1024 @@ -112,14 +108,18 @@ static size_t neon_rot_ldr_at_top_rowmajor_dump_sve_slots(struct test *test) static int neon_rot_ldr_at_top_rowmajor_dump_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_rowmajor_dump_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_rowmajor_dump_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_gps_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_gps_sve.cpp index fa2d30b60..f7a1c071c 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_gps_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_gps_sve.cpp @@ -45,11 +45,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_ROWMAJOR_GPS_SVE_SLOTS 1024 @@ -105,14 +101,18 @@ static size_t neon_rot_ldr_at_top_rowmajor_gps_sve_slots(struct test *test) static int neon_rot_ldr_at_top_rowmajor_gps_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_rowmajor_gps_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_rowmajor_gps_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k3res_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k3res_sve.cpp index 3a7f507f6..cfe9f0129 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k3res_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k3res_sve.cpp @@ -41,11 +41,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_ROWMAJOR_K3RES_SVE_SLOTS 4096 /* 4x champion footprint */ @@ -99,14 +95,18 @@ static size_t neon_rot_ldr_at_top_rowmajor_k3res_sve_slots(struct test *test) static int neon_rot_ldr_at_top_rowmajor_k3res_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_rowmajor_k3res_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_rowmajor_k3res_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k5far_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k5far_sve.cpp index 9f2669993..2a12a8666 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k5far_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k5far_sve.cpp @@ -38,11 +38,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_ROWMAJOR_K5FAR_SVE_SLOTS 1024 @@ -96,14 +92,18 @@ static size_t neon_rot_ldr_at_top_rowmajor_k5far_sve_slots(struct test *test) static int neon_rot_ldr_at_top_rowmajor_k5far_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_rowmajor_k5far_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_rowmajor_k5far_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k5inter_rand_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k5inter_rand_sve.cpp index 882ad3642..908851727 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k5inter_rand_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k5inter_rand_sve.cpp @@ -33,11 +33,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_ROWMAJOR_K5IR_SVE_SLOTS 1024 @@ -79,14 +75,18 @@ static size_t neon_rot_ldr_at_top_rowmajor_k5inter_rand_sve_slots(struct test *t static int neon_rot_ldr_at_top_rowmajor_k5inter_rand_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_rowmajor_k5inter_rand_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_rowmajor_k5inter_rand_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k7pattern_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k7pattern_sve.cpp index a745095c0..82863989c 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k7pattern_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_k7pattern_sve.cpp @@ -46,11 +46,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_ROWMAJOR_K7P_SVE_SLOTS 1024 @@ -130,9 +126,14 @@ static size_t k7p_sve_slots(struct test *test) return v > 0 ? (size_t)v : (size_t)dflt; } -static int k7p_sve_init_common(struct test *test, K7pSvePattern pattern) +static int k7p_sve_init_common(struct test *test, K7pSvePattern pattern, long svl) { - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = k7p_sve_slots(test); const size_t elems = slots * (size_t)lanes; @@ -175,12 +176,12 @@ static int k7p_sve_init_common(struct test *test, K7pSvePattern pattern) static int k7p_zero_sve_init(struct test *test) { #if defined(__aarch64__) - if ((getauxval(AT_HWCAP) & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for k7p_zero_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - return k7p_sve_init_common(test, K7P_SVE_ZERO); + return k7p_sve_init_common(test, K7P_SVE_ZERO, svl); #else (void)test; log_skip(CpuNotSupportedSkipCategory, @@ -192,12 +193,12 @@ static int k7p_zero_sve_init(struct test *test) static int k7p_one_sve_init(struct test *test) { #if defined(__aarch64__) - if ((getauxval(AT_HWCAP) & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for k7p_one_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - return k7p_sve_init_common(test, K7P_SVE_ONE); + return k7p_sve_init_common(test, K7P_SVE_ONE, svl); #else (void)test; log_skip(CpuNotSupportedSkipCategory, @@ -209,12 +210,12 @@ static int k7p_one_sve_init(struct test *test) static int k7p_rand_sve_init(struct test *test) { #if defined(__aarch64__) - if ((getauxval(AT_HWCAP) & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for k7p_rand_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - return k7p_sve_init_common(test, K7P_SVE_RAND); + return k7p_sve_init_common(test, K7P_SVE_RAND, svl); #else (void)test; log_skip(CpuNotSupportedSkipCategory, @@ -226,12 +227,12 @@ static int k7p_rand_sve_init(struct test *test) static int k7p_hiham_sve_init(struct test *test) { #if defined(__aarch64__) - if ((getauxval(AT_HWCAP) & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for k7p_hiham_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - return k7p_sve_init_common(test, K7P_SVE_HIHAM); + return k7p_sve_init_common(test, K7P_SVE_HIHAM, svl); #else (void)test; log_skip(CpuNotSupportedSkipCategory, diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_str3_checkall_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_str3_checkall_sve.cpp index 972d85762..0e411bb38 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_str3_checkall_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_str3_checkall_sve.cpp @@ -41,11 +41,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_STR3_CHECKALL_SVE_SLOTS 1024 @@ -172,14 +168,18 @@ __attribute__((noinline)) static void str3_checkall_sve_cold_scan( static int neon_rot_ldr_at_top_str3_checkall_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_str3_checkall_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_str3_checkall_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_sve.cpp index 18f4b26ef..7a9806353 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_rowmajor_sve.cpp @@ -32,11 +32,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_ROWMAJOR_SVE_SLOTS 1024 @@ -78,14 +74,18 @@ static size_t neon_rot_ldr_at_top_rowmajor_sve_slots(struct test *test) static int neon_rot_ldr_at_top_rowmajor_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_rowmajor_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_rowmajor_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_str3_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_str3_sve.cpp index 03ffa7858..29bb20015 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_str3_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_str3_sve.cpp @@ -29,11 +29,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_STR3_SVE_SLOTS 1024 @@ -75,14 +71,18 @@ static size_t neon_rot_ldr_at_top_str3_sve_slots(struct test *test) static int neon_rot_ldr_at_top_str3_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_str3_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_str3_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_sub_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_sub_sve.cpp index 1db7acff3..e9b4322dc 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_sub_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_sub_sve.cpp @@ -31,11 +31,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_SUB_SVE_SLOTS 1024 @@ -77,14 +73,18 @@ static size_t neon_rot_ldr_at_top_sub_sve_slots(struct test *test) static int neon_rot_ldr_at_top_sub_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_sub_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_sub_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_ldr_at_top_sve.cpp b/tests/cpu/sve/case/neon_rot_ldr_at_top_sve.cpp index 9e2e91c99..065cf7f15 100644 --- a/tests/cpu/sve/case/neon_rot_ldr_at_top_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_ldr_at_top_sve.cpp @@ -26,11 +26,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_LDR_AT_TOP_SVE_SLOTS 1024 @@ -72,14 +68,18 @@ static size_t neon_rot_ldr_at_top_sve_slots(struct test *test) static int neon_rot_ldr_at_top_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_ldr_at_top_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int lanes = (int)svcntd(); + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %d outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t slots = neon_rot_ldr_at_top_sve_slots(test); const size_t elems = slots * (size_t)lanes; diff --git a/tests/cpu/sve/case/neon_rot_store_only_sve.cpp b/tests/cpu/sve/case/neon_rot_store_only_sve.cpp index d16585682..d10c9b2f9 100644 --- a/tests/cpu/sve/case/neon_rot_store_only_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_store_only_sve.cpp @@ -32,11 +32,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_STORE_ONLY_SVE_COUNT 1024 /* uint64 elements per buffer */ @@ -68,15 +64,21 @@ static int neon_rot_store_only_sve_init(struct test *test) { size_t count = NEON_ROT_STORE_ONLY_SVE_COUNT; #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_store_only_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } count = neon_rot_store_only_sve_count(test); /* asm ldr z 全向量源加载: count 向下取整到 svcntd() 的整倍数 (倍数约束保留) */ - const size_t lanes = (size_t)svcntd(); + const size_t lanes = (size_t)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + /* arm64_vl.h unit convention: release-effective range check catches + * a wrong-divisor drift (e.g. svl/4 here would compile silently). */ + if (lanes < 2 || lanes > 16) { + log_error("%s: f64 lanes %zu outside [2,16] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } const size_t rem = count - count / lanes * lanes; /* % 表达式触发 GCC SVE ICE, 改用除法组合 */ if (rem != 0) { const size_t rounded = count - rem; diff --git a/tests/cpu/sve/case/neon_rot_u8x16_sve.cpp b/tests/cpu/sve/case/neon_rot_u8x16_sve.cpp index 7d0c45142..4cd4b3d2d 100644 --- a/tests/cpu/sve/case/neon_rot_u8x16_sve.cpp +++ b/tests/cpu/sve/case/neon_rot_u8x16_sve.cpp @@ -40,11 +40,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define NEON_ROT_U8X16_SVE_BYTES 16384 /* bytes per buffer */ @@ -82,23 +78,22 @@ static int neon_rot_u8x16_sve_init(struct test *test) { size_t buffer_bytes = NEON_ROT_U8X16_SVE_BYTES; #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_rot_u8x16_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } buffer_bytes = neon_rot_u8x16_sve_buffer_bytes(test); /* 全 VL ldr/str 访问 + aligned_alloc(64,·) 尺寸约束 (原 16/64 对齐保留): * 向下取整到 svcntb() 与 64 的公倍数 (均为 2 的幂, 取大者即公倍数) */ - size_t align = (size_t)svcntb(); + size_t align = (size_t)svl; /* VL 字节 = SVL bytes (svcntb 同值) */ if (align < 64) align = 64; if (buffer_bytes % align != 0) { const size_t rounded = buffer_bytes - buffer_bytes % align; log_warning("neon_rot_u8x16_sve: buffer_bytes=%zu 不是 svcntb()=%d 与 64 的公倍数, " "向下取整为 %zu", - buffer_bytes, (int)svcntb(), rounded); + buffer_bytes, (int)svl, rounded); buffer_bytes = rounded; } #endif diff --git a/tests/cpu/sve/eigen/eigen_svd_bidiag_sve.cpp b/tests/cpu/sve/eigen/eigen_svd_bidiag_sve.cpp index 9864b2eb0..3ff8b2815 100644 --- a/tests/cpu/sve/eigen/eigen_svd_bidiag_sve.cpp +++ b/tests/cpu/sve/eigen/eigen_svd_bidiag_sve.cpp @@ -71,7 +71,11 @@ * RUNTIME-UNVERIFIABLE (SVE): developed on a host without SVE * (HWCAP_SVE clear); compile-verified and the skip path executed for * real, but the SVE datapath itself has not run on hardware - * (cf. 8502e491 / 73ebbd3f for the precedent). The PR #244-review + * (cf. 8502e491 / 73ebbd3f for the precedent). test_init gates via + * the framework layer (arm64_require_sve_vl: HWCAP_SVE capability + + * 128..1024-bit range in one call, all-VL Phase 2 P6; the TU is true + * VLA — svwhilelt-stepped loops in svcntd()/svcntw() batches — so + * every tier in range is in-domain). The PR #244-review * gather/scatter left-update IS verified on gem5 SVE SE emulation * (O3, VL=128/256/512, n=64/68/128): the pre-fix contiguous-load * version diverges at ~1.7 vs the scalar reference (the review's bug @@ -90,11 +94,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif /* 维度 n 运行时可配置, 统一优先级链: @@ -361,12 +361,17 @@ static void bidiag_compare_or_fail(const double *got, const double *golden, static int eigen_svd_bidiag_sve_init(struct test *test) { - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for eigen_svd_bidiag_sve"); + /* All-VL Phase 2 P6: capability + 128..1024-bit range check in one + * framework-layer call, replacing the getauxval hand-probe (and its + * misleading "placeholder" skip wording — absence of SVE is a + * capability fact, not an unimplemented feature). Gate only: the + * golden is an n×n scalar reference and the run side sizes its + * per-thread scratch from a fresh svcntd() read, so no init/run VL + * state exists to drift. */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } + (void)svl; auto *d = new bidiag_data; if (!d) diff --git a/tests/cpu/sve/fma/fma_patterns_sve_wide_pd.cpp b/tests/cpu/sve/fma/fma_patterns_sve_wide_pd.cpp index 6dee2a1ca..88312decc 100644 --- a/tests/cpu/sve/fma/fma_patterns_sve_wide_pd.cpp +++ b/tests/cpu/sve/fma/fma_patterns_sve_wide_pd.cpp @@ -7,10 +7,7 @@ #ifdef __aarch64__ #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr int VECTOR_SIZE = 8; // 8 个双精度浮点数(与 fma_patterns_avx512_pd 负载一致) @@ -18,12 +15,11 @@ static constexpr int VECTOR_SIZE = 8; // 8 个双精度浮点数(与 fma_patte static int fma_patterns_sve_wide_pd_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fma_patterns_sve_wide_pd"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/fma/fma_patterns_sve_wide_ps.cpp b/tests/cpu/sve/fma/fma_patterns_sve_wide_ps.cpp index e188a25bc..f4199ef1a 100644 --- a/tests/cpu/sve/fma/fma_patterns_sve_wide_ps.cpp +++ b/tests/cpu/sve/fma/fma_patterns_sve_wide_ps.cpp @@ -7,10 +7,7 @@ #ifdef __aarch64__ #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr int VECTOR_SIZE = 16; // 16 个单精度浮点数(与 fma_patterns_avx512_ps 负载一致) @@ -18,12 +15,11 @@ static constexpr int VECTOR_SIZE = 16; // 16 个单精度浮点数(与 fma_pat static int fma_patterns_sve_wide_ps_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fma_patterns_sve_wide_ps"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/fma/fma_tail_sve.cpp b/tests/cpu/sve/fma/fma_tail_sve.cpp index ae61a0e78..597a98fcc 100644 --- a/tests/cpu/sve/fma/fma_tail_sve.cpp +++ b/tests/cpu/sve/fma/fma_tail_sve.cpp @@ -7,10 +7,7 @@ #ifdef __aarch64__ #include // ARM SVE 头文件 -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr int VECTOR_SIZE = 4; // 4 个双精度浮点数(与 fma_tail_avx2 负载一致) @@ -18,15 +15,11 @@ static constexpr int VECTOR_SIZE = 4; // 4 个双精度浮点数(与 fma_tail_ static int fma_tail_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - /* Runtime gate: probe HWCAP_SVE directly via getauxval (sleef_sve.cpp - * precedent — device_has_feature would be always-true here because this - * TU is compiled with +sve). */ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fma_tail_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/fma/fma_tail_sve_wide.cpp b/tests/cpu/sve/fma/fma_tail_sve_wide.cpp index 12862eabf..6065ec289 100644 --- a/tests/cpu/sve/fma/fma_tail_sve_wide.cpp +++ b/tests/cpu/sve/fma/fma_tail_sve_wide.cpp @@ -7,10 +7,7 @@ #ifdef __aarch64__ #include // ARM SVE 头文件 -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr int VECTOR_SIZE = 8; // 8 个双精度浮点数(与 fma_tail_avx512 负载一致) @@ -18,12 +15,11 @@ static constexpr int VECTOR_SIZE = 8; // 8 个双精度浮点数(与 fma_tail_ static int fma_tail_sve_wide_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fma_tail_sve_wide"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/fma/fmatail_double_nested_sve.cpp b/tests/cpu/sve/fma/fmatail_double_nested_sve.cpp index 99c5c3ce3..1677c7ce2 100644 --- a/tests/cpu/sve/fma/fmatail_double_nested_sve.cpp +++ b/tests/cpu/sve/fma/fmatail_double_nested_sve.cpp @@ -7,10 +7,7 @@ #ifdef __aarch64__ #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr int VECTOR_SIZE = 4; // 4 个双精度浮点数(与 fmatail_double_nested_avx2 负载一致) @@ -19,12 +16,11 @@ static constexpr int INNER_ITERATIONS = 10; // 内层循环每组生成的随 static int fmatail_double_nested_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fmatail_double_nested_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/fma/fmatail_double_nested_sve_wide.cpp b/tests/cpu/sve/fma/fmatail_double_nested_sve_wide.cpp index b9a54e657..29c23697e 100644 --- a/tests/cpu/sve/fma/fmatail_double_nested_sve_wide.cpp +++ b/tests/cpu/sve/fma/fmatail_double_nested_sve_wide.cpp @@ -7,10 +7,7 @@ #ifdef __aarch64__ #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr int VECTOR_SIZE = 8; // 8 个双精度浮点数(与 fmatail_double_nested_avx512 负载一致) @@ -19,12 +16,11 @@ static constexpr int INNER_ITERATIONS = 10; // 内层循环每组生成 static int fmatail_double_nested_sve_wide_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fmatail_double_nested_sve_wide"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/fma/fmatail_nested_sve.cpp b/tests/cpu/sve/fma/fmatail_nested_sve.cpp index 3f8503da8..622932320 100644 --- a/tests/cpu/sve/fma/fmatail_nested_sve.cpp +++ b/tests/cpu/sve/fma/fmatail_nested_sve.cpp @@ -7,10 +7,7 @@ #ifdef __aarch64__ #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr int VECTOR_SIZE = 4; // 4 个双精度浮点数(与 fmatail_nested_avx2 负载一致) @@ -19,12 +16,11 @@ static constexpr int INNER_ITERATIONS = 5; // 内层循环每组生成的随 static int fmatail_nested_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fmatail_nested_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/fma/fmatail_nested_sve_wide.cpp b/tests/cpu/sve/fma/fmatail_nested_sve_wide.cpp index 9488335d8..96ff732be 100644 --- a/tests/cpu/sve/fma/fmatail_nested_sve_wide.cpp +++ b/tests/cpu/sve/fma/fmatail_nested_sve_wide.cpp @@ -7,10 +7,7 @@ #ifdef __aarch64__ #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr int VECTOR_SIZE = 8; // 8 个双精度浮点数(与 fmatail_nested_avx512 负载一致) @@ -19,12 +16,11 @@ static constexpr int INNER_ITERATIONS = 5; // 内层循环每组生成 static int fmatail_nested_sve_wide_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fmatail_nested_sve_wide"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/fma/fmatail_sve.cpp b/tests/cpu/sve/fma/fmatail_sve.cpp index bc4a42680..d05ae6edf 100644 --- a/tests/cpu/sve/fma/fmatail_sve.cpp +++ b/tests/cpu/sve/fma/fmatail_sve.cpp @@ -7,10 +7,7 @@ #ifdef __aarch64__ #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr int VECTOR_SIZE = 4; // 4 个双精度浮点数(与 fmatail_avx2 负载一致) @@ -18,12 +15,11 @@ static constexpr int VECTOR_SIZE = 4; // 4 个双精度浮点数(与 fmatail_a static int fmatail_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fmatail_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/fma/fmatail_sve_wide.cpp b/tests/cpu/sve/fma/fmatail_sve_wide.cpp index 662350c96..773f033df 100644 --- a/tests/cpu/sve/fma/fmatail_sve_wide.cpp +++ b/tests/cpu/sve/fma/fmatail_sve_wide.cpp @@ -7,10 +7,7 @@ #ifdef __aarch64__ #include -#include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr int VECTOR_SIZE = 8; // 8 个双精度浮点数(与 fmatail_avx512 负载一致) @@ -18,12 +15,11 @@ static constexpr int VECTOR_SIZE = 8; // 8 个双精度浮点数( static int fmatail_sve_wide_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fmatail_sve_wide"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/fma2/fma_sve.cpp b/tests/cpu/sve/fma2/fma_sve.cpp index fe77d7fa6..0007535ba 100644 --- a/tests/cpu/sve/fma2/fma_sve.cpp +++ b/tests/cpu/sve/fma2/fma_sve.cpp @@ -5,11 +5,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr size_t VECTOR_SIZE = 8; // 8 个单精度浮点数(与原版一致) @@ -38,12 +34,13 @@ struct TestData {}; static int fma_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fma_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/fma2/fpu_special_values_sve.cpp b/tests/cpu/sve/fma2/fpu_special_values_sve.cpp index 9fac57b11..a3b75261b 100644 --- a/tests/cpu/sve/fma2/fpu_special_values_sve.cpp +++ b/tests/cpu/sve/fma2/fpu_special_values_sve.cpp @@ -28,11 +28,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif // Type-punning helper (mirrors the original). @@ -101,12 +97,13 @@ static int fpu_special_values_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fpu_special_values_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/fma2/fsu_byteexact_sve.cpp b/tests/cpu/sve/fma2/fsu_byteexact_sve.cpp index 890a32c72..3f0921410 100644 --- a/tests/cpu/sve/fma2/fsu_byteexact_sve.cpp +++ b/tests/cpu/sve/fma2/fsu_byteexact_sve.cpp @@ -66,11 +66,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr size_t CACHE_LINE = 64; @@ -132,12 +128,13 @@ static constexpr size_t NUM_HH_PAIRS = sizeof(HH_PAIRS) / sizeof(HH_PAIRS[0]); static int fsu_byteexact_sve_init(struct test *test) { - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for fsu_byteexact_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } (void)test; return EXIT_SUCCESS; diff --git a/tests/cpu/sve/fma2/movdq2q_sve.cpp b/tests/cpu/sve/fma2/movdq2q_sve.cpp index 88a67fae7..aa9289df2 100644 --- a/tests/cpu/sve/fma2/movdq2q_sve.cpp +++ b/tests/cpu/sve/fma2/movdq2q_sve.cpp @@ -22,11 +22,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MOV_COUNT 1024 @@ -56,12 +52,13 @@ struct movdq2q_sve_data { static int movdq2q_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movdq2q_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = (movdq2q_sve_data *)malloc(sizeof(movdq2q_sve_data)); diff --git a/tests/cpu/sve/fma2/movmskpspd_sve.cpp b/tests/cpu/sve/fma2/movmskpspd_sve.cpp index faa5961be..74ab968b5 100644 --- a/tests/cpu/sve/fma2/movmskpspd_sve.cpp +++ b/tests/cpu/sve/fma2/movmskpspd_sve.cpp @@ -26,11 +26,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MOVMSK_COUNT 1024 @@ -65,12 +61,13 @@ struct MovmskpspdSveData { static int movmskpspd_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movmskpspd_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(MovmskpspdSveData))); diff --git a/tests/cpu/sve/fma2/movq2dq_sve.cpp b/tests/cpu/sve/fma2/movq2dq_sve.cpp index 3e993c0e6..3b2181230 100644 --- a/tests/cpu/sve/fma2/movq2dq_sve.cpp +++ b/tests/cpu/sve/fma2/movq2dq_sve.cpp @@ -23,11 +23,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define MOVQ2DQ_SVE_COUNT 1024 @@ -56,12 +52,13 @@ struct Movq2dqSveData { static int movq2dq_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for movq2dq_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(Movq2dqSveData))); diff --git a/tests/cpu/sve/fma2/neon_add_sve.cpp b/tests/cpu/sve/fma2/neon_add_sve.cpp index b85589d94..6799aa21e 100644 --- a/tests/cpu/sve/fma2/neon_add_sve.cpp +++ b/tests/cpu/sve/fma2/neon_add_sve.cpp @@ -20,12 +20,8 @@ #ifdef __aarch64__ #include -#include +#include #include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif #endif #define SVE_ADD_ELEMENTS (1u << 10) @@ -70,12 +66,13 @@ static void prv_do_add(const uint32_t *a, const uint32_t *b, uint32_t *res, size static int neon_add_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for neon_add_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } neon_add_sve_t *na = static_cast(malloc(sizeof(*na))); const size_t count = neon_add_sve_count(test); diff --git a/tests/cpu/sve/fma2/power_virus_dit_sve.cpp b/tests/cpu/sve/fma2/power_virus_dit_sve.cpp index 9f1b485b5..f7d1fe884 100644 --- a/tests/cpu/sve/fma2/power_virus_dit_sve.cpp +++ b/tests/cpu/sve/fma2/power_virus_dit_sve.cpp @@ -27,11 +27,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static inline uint32_t bits_of(float f) @@ -69,12 +65,13 @@ static int power_virus_dit_sve_scale(struct test *test) static int power_virus_dit_sve_init(struct test *test) { #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for power_virus_dit_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *d = static_cast(malloc(sizeof(PowerVirusDitSveData))); if (!d) diff --git a/tests/cpu/sve/kreg/arm0102_fma_f32_sve.cpp b/tests/cpu/sve/kreg/arm0102_fma_f32_sve.cpp index 5662ca692..987439908 100644 --- a/tests/cpu/sve/kreg/arm0102_fma_f32_sve.cpp +++ b/tests/cpu/sve/kreg/arm0102_fma_f32_sve.cpp @@ -39,11 +39,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define ARM0102_FMA_F32_SVE_COUNT 1024 @@ -106,14 +102,19 @@ static inline svfloat32_t fma_rotating_sve(svbool_t pg, svfloat32_t a, svfloat32 static int arm0102_fma_f32_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for arm0102_fma_f32_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int slack = svcntw(); /* asm ldr z 尾批松弛, 见文件头注释 */ + const int lanes = (int)(svl / 4); /* f32 lanes = SVL bytes / 4 */ + if (lanes < 4 || lanes > 32) { + log_error("%s: f32 lanes %d outside [4,32] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } + const int slack = lanes; /* asm ldr z 尾批松弛, 见文件头注释 */ const int count = (int)arm0102_fma_f32_sve_count(test); const size_t total = (size_t)(count + slack) * sizeof(float); auto *data = static_cast(malloc(sizeof(Arm0102FmaF32SveData))); @@ -133,7 +134,7 @@ static int arm0102_fma_f32_sve_init(struct test *test) { /* golden: 与 run 相同的子块结构 + 相位 = 子块序号 * (base+sub)/FMA_SVE_SUBLANES, 同 SVE 单元; 原式 (base+sub)%4 恒为 0 * (base 是 svcntw() 倍数、sub 是 4 的倍数), 旋转失效 */ - const int lanes = svcntw(); + /* lanes 已由上方门控 svl 换算 (f32 lanes = SVL bytes / 4) */ svbool_t pg4 = svwhilelt_b32((uint64_t)0, (uint64_t)FMA_SVE_SUBLANES); for (int base = 0; base < count; base += lanes) { const int n = (count - base < lanes) diff --git a/tests/cpu/sve/kreg/arm0102_kreg_logic_sve.cpp b/tests/cpu/sve/kreg/arm0102_kreg_logic_sve.cpp index beb4eb4a4..b61f4d4b2 100644 --- a/tests/cpu/sve/kreg/arm0102_kreg_logic_sve.cpp +++ b/tests/cpu/sve/kreg/arm0102_kreg_logic_sve.cpp @@ -31,11 +31,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define ARM0102_KREG_LOGIC_SVE_COUNT 1024 @@ -95,14 +91,19 @@ static inline svuint32_t logic_rotating_sve(svbool_t pg, svuint32_t a, svuint32_ static int arm0102_kreg_logic_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for arm0102_kreg_logic_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int slack = svcntw(); /* asm ldr z 尾批松弛, 见文件头注释 */ + const int lanes = (int)(svl / 4); /* f32 lanes = SVL bytes / 4 */ + if (lanes < 4 || lanes > 32) { + log_error("%s: f32 lanes %d outside [4,32] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } + const int slack = lanes; /* asm ldr z 尾批松弛, 见文件头注释 */ const int count = (int)arm0102_kreg_logic_sve_count(test); const size_t total = (size_t)(count + slack) * sizeof(uint32_t); auto *data = static_cast(malloc(sizeof(Arm0102KregLogicSveData))); @@ -114,7 +115,7 @@ static int arm0102_kreg_logic_sve_init(struct test *test) { memset_random(data->srcA, total); memset_random(data->srcB, total); - const int lanes = svcntw(); + /* lanes 已由上方门控 svl 换算 (f32 lanes = SVL bytes / 4) */ svbool_t pg4 = svwhilelt_b32((uint64_t)0, (uint64_t)KLOGIC_SVE_SUBLANES); for (int base = 0; base < count; base += lanes) { const int n = (count - base < lanes) diff --git a/tests/cpu/sve/kreg/arm0102_kreg_mask_sve.cpp b/tests/cpu/sve/kreg/arm0102_kreg_mask_sve.cpp index e0ef39883..6569e0b46 100644 --- a/tests/cpu/sve/kreg/arm0102_kreg_mask_sve.cpp +++ b/tests/cpu/sve/kreg/arm0102_kreg_mask_sve.cpp @@ -29,11 +29,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define ARM0102_KREG_MASK_SVE_COUNT 1024 /* elements per buffer (uint32) */ @@ -107,32 +103,49 @@ static inline svuint32_t kreg_expand_rotating(svbool_t pg, svuint32_t a, svuint3 } static int arm0102_kreg_mask_sve_init(struct test *test) { - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for arm0102_kreg_mask_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *data = static_cast(malloc(sizeof(Arm0102KregMaskSveData))); const int count = (int)arm0102_kreg_mask_sve_count(test); data->count = count; - data->srcA = static_cast(aligned_alloc(64, (size_t)count * sizeof(uint32_t))); - data->srcB = static_cast(aligned_alloc(64, (size_t)count * sizeof(uint32_t))); - data->expected = static_cast(aligned_alloc(64, (size_t)count * sizeof(uint32_t))); - - memset_random(data->srcA, (size_t)count * sizeof(uint32_t)); - memset_random(data->srcB, (size_t)count * sizeof(uint32_t)); /* golden: 同一旋转组合, 在相同 SVE 单元上预计算 */ [[maybe_unused]] svbool_t pg = svptrue_b32(); - const int lanes = svcntw(); + const int lanes = (int)(svl / 4); /* f32 lanes = SVL bytes / 4 */ + /* arm64_vl.h unit convention: release-effective range check catches + * a wrong-divisor drift (e.g. svl/8 here would compile silently). */ + if (lanes < 4 || lanes > 32) { + log_error("%s: f32 lanes %d outside [4,32] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } + /* 尾批 asm 全宽读松弛 = lanes (kreg_logic 同款, a6f753ce): run 侧 + * ldr z 按 svcntb() 全宽载, 最末子块最多读到 (count-1)+svcntw() + * 个元素, slack=lanes 严格充分 (任意 VL)。aligned_alloc_safe 为 + * 795e0d55 家族契约修法 (total 未必是 64 的倍数)。 */ + const int slack = lanes; + const size_t total = (size_t)(count + slack) * sizeof(uint32_t); + data->srcA = static_cast(aligned_alloc_safe(64, total)); + data->srcB = static_cast(aligned_alloc_safe(64, total)); + data->expected = static_cast(aligned_alloc_safe(64, total)); + + memset_random(data->srcA, total); + memset_random(data->srcB, total); + for (int base = 0; base < count; base += lanes) { int n = (count - base < lanes) ? (count - base) : lanes; [[maybe_unused]] svbool_t pgn = svwhilelt_b32((uint64_t)0, (uint64_t)n); - /* 与 run 完全相同的 4 元素子块结构 + 相位 (base+sub)%4 */ + /* 与 run 完全相同的 4 元素子块结构 + 相位按子块旋转 */ for (int sub = 0; sub < n; sub += 4) { - int phase = (base + sub) % 4; + /* 相位 = 子块序号 (base+sub)/KREG_SVE_SUBLANES, 按子块旋转; + * 原式 (base+sub)%4 恒为 0 (base 是 svcntw() 倍数、sub 是 4 + * 的倍数) —— 4 谓词路径只覆盖 eq, gt/eq-u/tst 全部死代码 + * (426dc5c6 家族同款修法, kreg_logic/not/select/fma 均已改)。 */ + const int phase = (base + sub) / KREG_SVE_SUBLANES; /* 单 lane 组: 用标量嵌入向量 */ uint32_t av[8], bv[8], ov[8]; for (int k = 0; k < 4 && sub + k < n; ++k) { @@ -156,12 +169,14 @@ static int arm0102_kreg_mask_sve_run(struct test *test, int cpu) { auto *data = static_cast(test->data); const int count = data->count; - uint32_t *temp = static_cast(aligned_alloc(64, (size_t)count * sizeof(uint32_t))); - uint32_t *dst = static_cast(aligned_alloc(64, (size_t)count * sizeof(uint32_t))); + /* run 侧 temp/dst 同享尾批松弛: load_vec_sve 的 asm ldr z 全宽读 + * 最末子块, (count + svcntw()) 与 init 的 total 同界 (kreg_logic 同款)。 */ + uint32_t *temp = static_cast(aligned_alloc_safe(64, (size_t)(count + svcntw()) * sizeof(uint32_t))); + uint32_t *dst = static_cast(aligned_alloc_safe(64, (size_t)(count + svcntw()) * sizeof(uint32_t))); TEST_LOOP(test, 1 << 13) { /* 与 golden 完全相同的 4 元素子块结构: 每 SVE 向量批内按 4 元素子块, - * 相位 = (base+sub) % 4 (与 init 的 golden 循环逐字一致) */ + * 相位 = 子块序号 (base+sub)/KREG_SVE_SUBLANES (与 init 一致) */ for (int base = 0; base < count; base += svcntw()) { int n = (count - base < svcntw()) ? (count - base) : svcntw(); for (int sub = 0; sub < n; sub += 4) { @@ -171,7 +186,8 @@ static int arm0102_kreg_mask_sve_run(struct test *test, int cpu) { svbool_t pg4 = svwhilelt_b32((uint64_t)0, (uint64_t)4); /* 载荷: 谓词比较掩码扩展 + svsel (相位与 golden 一致) */ - svuint32_t res = kreg_expand_rotating(pg4, a, b, base + sub); + svuint32_t res = kreg_expand_rotating(pg4, a, b, + (base + sub) / KREG_SVE_SUBLANES); /* 放大器: str z -> ldr z -> str z */ store_vec_sve(temp + base + sub, res); diff --git a/tests/cpu/sve/kreg/arm0102_kreg_not_sve.cpp b/tests/cpu/sve/kreg/arm0102_kreg_not_sve.cpp index d70417b3c..21b73d2df 100644 --- a/tests/cpu/sve/kreg/arm0102_kreg_not_sve.cpp +++ b/tests/cpu/sve/kreg/arm0102_kreg_not_sve.cpp @@ -32,11 +32,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define ARM0102_KREG_NOT_SVE_COUNT 1024 @@ -97,14 +93,19 @@ static inline svuint32_t not_rotating_sve(svbool_t pg, svuint32_t a, svuint32_t static int arm0102_kreg_not_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for arm0102_kreg_not_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int slack = svcntw(); /* asm ldr z 尾批松弛, 见文件头注释 */ + const int lanes = (int)(svl / 4); /* f32 lanes = SVL bytes / 4 */ + if (lanes < 4 || lanes > 32) { + log_error("%s: f32 lanes %d outside [4,32] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } + const int slack = lanes; /* asm ldr z 尾批松弛, 见文件头注释 */ const int count = (int)arm0102_kreg_not_sve_count(test); const size_t total = (size_t)(count + slack) * sizeof(uint32_t); auto *data = static_cast(malloc(sizeof(Arm0102KregNotSveData))); @@ -116,7 +117,7 @@ static int arm0102_kreg_not_sve_init(struct test *test) { memset_random(data->srcA, total); memset_random(data->srcB, total); - const int lanes = svcntw(); + /* lanes 已由上方门控 svl 换算 (f32 lanes = SVL bytes / 4) */ svbool_t pg4 = svwhilelt_b32((uint64_t)0, (uint64_t)KNOT_SVE_SUBLANES); for (int base = 0; base < count; base += lanes) { const int n = (count - base < lanes) diff --git a/tests/cpu/sve/kreg/arm0102_kreg_select_sve.cpp b/tests/cpu/sve/kreg/arm0102_kreg_select_sve.cpp index 63020ac16..671ea3aca 100644 --- a/tests/cpu/sve/kreg/arm0102_kreg_select_sve.cpp +++ b/tests/cpu/sve/kreg/arm0102_kreg_select_sve.cpp @@ -39,11 +39,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define ARM0102_KREG_SELECT_SVE_COUNT 1024 /* u32 elements */ @@ -113,14 +109,19 @@ static inline svuint32_t select_rotating_sve(svbool_t pg, svuint32_t a, svuint32 static int arm0102_kreg_select_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for arm0102_kreg_select_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } - const int slack = svcntw(); /* asm ldr z 尾批松弛, 见文件头注释 */ + const int lanes = (int)(svl / 4); /* f32 lanes = SVL bytes / 4 */ + if (lanes < 4 || lanes > 32) { + log_error("%s: f32 lanes %d outside [4,32] — unit drift (svl %ld bytes)", + test->id, lanes, svl); + return EXIT_FAILURE; + } + const int slack = lanes; /* asm ldr z 尾批松弛, 见文件头注释 */ const int count = (int)arm0102_kreg_select_sve_count(test); const size_t total = (size_t)(count + slack) * sizeof(uint32_t); auto *data = static_cast(malloc(sizeof(Arm0102KregSelectSveData))); @@ -138,7 +139,7 @@ static int arm0102_kreg_select_sve_init(struct test *test) { /* golden: 与 run 完全相同的 4 元素子块结构 + 相位 = 子块序号 * (base+sub)/KSEL_SVE_SUBLANES, 按子块旋转 op; 原式 (base+sub)%4 * 恒为 0 (base 是 svcntw() 倍数、sub 是 4 的倍数), 旋转失效 */ - const int lanes = svcntw(); + /* lanes 已由上方门控 svl 换算 (f32 lanes = SVL bytes / 4) */ svbool_t pg4 = svwhilelt_b32((uint64_t)0, (uint64_t)KSEL_SVE_SUBLANES); for (int base = 0; base < count; base += lanes) { const int n = (count - base < lanes) diff --git a/tests/cpu/sve/kreg/kreg2_sve.cpp b/tests/cpu/sve/kreg/kreg2_sve.cpp index 73ef44bc9..889c54639 100644 --- a/tests/cpu/sve/kreg/kreg2_sve.cpp +++ b/tests/cpu/sve/kreg/kreg2_sve.cpp @@ -9,22 +9,17 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static int kreg2_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for kreg2_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/kreg/kreg3_sve.cpp b/tests/cpu/sve/kreg/kreg3_sve.cpp index 1689a33ec..a76e1fc45 100644 --- a/tests/cpu/sve/kreg/kreg3_sve.cpp +++ b/tests/cpu/sve/kreg/kreg3_sve.cpp @@ -9,22 +9,17 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static int kreg3_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for kreg3_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/kreg/kreg5_sve.cpp b/tests/cpu/sve/kreg/kreg5_sve.cpp index 281af28af..d7fbb06da 100644 --- a/tests/cpu/sve/kreg/kreg5_sve.cpp +++ b/tests/cpu/sve/kreg/kreg5_sve.cpp @@ -9,22 +9,17 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static int kreg5_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for kreg5_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/kreg/kreg6_sve.cpp b/tests/cpu/sve/kreg/kreg6_sve.cpp index 354c031cb..104e64517 100644 --- a/tests/cpu/sve/kreg/kreg6_sve.cpp +++ b/tests/cpu/sve/kreg/kreg6_sve.cpp @@ -9,11 +9,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define KREG6_ELEMENTS 16 /* 原负载: 16 位掩码 → 16 个 32 位展开 */ @@ -21,12 +17,11 @@ static int kreg6_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for kreg6_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/kreg/kreg8_sve.cpp b/tests/cpu/sve/kreg/kreg8_sve.cpp index fb4dbab66..e84941af6 100644 --- a/tests/cpu/sve/kreg/kreg8_sve.cpp +++ b/tests/cpu/sve/kreg/kreg8_sve.cpp @@ -9,22 +9,17 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static int kreg8_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for kreg8_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/kreg/kreg9_sve.cpp b/tests/cpu/sve/kreg/kreg9_sve.cpp index c85d41464..5ed1b91cc 100644 --- a/tests/cpu/sve/kreg/kreg9_sve.cpp +++ b/tests/cpu/sve/kreg/kreg9_sve.cpp @@ -9,22 +9,17 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static int kreg9_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for kreg9_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/mem/agu_stress_2src_sve.cpp b/tests/cpu/sve/mem/agu_stress_2src_sve.cpp index dd380762f..e3fca7d37 100644 --- a/tests/cpu/sve/mem/agu_stress_2src_sve.cpp +++ b/tests/cpu/sve/mem/agu_stress_2src_sve.cpp @@ -21,11 +21,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif /* 每缓冲 u64 元素数(原 1024) — 统一优先级链: @@ -69,12 +65,13 @@ static inline svuint64_t load_vec_sve(const void *addr) { static int agu_stress_2src_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for agu_stress_2src_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(AguStress2srcSveData))); data->count = agu_2src_sve_count(test); diff --git a/tests/cpu/sve/mem/agu_stress_store_only_sve.cpp b/tests/cpu/sve/mem/agu_stress_store_only_sve.cpp index 86501dd0c..edc3ad5da 100644 --- a/tests/cpu/sve/mem/agu_stress_store_only_sve.cpp +++ b/tests/cpu/sve/mem/agu_stress_store_only_sve.cpp @@ -35,11 +35,7 @@ * SVE 架构最大 VL 2048bit = 256 字节 */ #define SVE_MAX_VECTOR_BYTES 256 #endif -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif /* 每缓冲 u64 元素数(原 1024) — 统一优先级链: @@ -69,12 +65,13 @@ struct AguStoreOnlySveData { static int agu_stress_store_only_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for agu_stress_store_only_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif auto *data = static_cast(malloc(sizeof(AguStoreOnlySveData))); data->count = agu_store_only_sve_count(test); diff --git a/tests/cpu/sve/mem/arm64_sdc_sve.cpp b/tests/cpu/sve/mem/arm64_sdc_sve.cpp index ae6b8ab03..8f9429bd3 100644 --- a/tests/cpu/sve/mem/arm64_sdc_sve.cpp +++ b/tests/cpu/sve/mem/arm64_sdc_sve.cpp @@ -24,11 +24,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #if defined(__aarch64__) @@ -107,12 +103,13 @@ static int sdc_sve_detect(const void *data, size_t len, static int arm64_sdc_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for arm64_sdc_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } crc_tables_init(); auto *data = new sdc_sve_data; diff --git a/tests/cpu/sve/mem/l2c_cross_cache_line_sve.cpp b/tests/cpu/sve/mem/l2c_cross_cache_line_sve.cpp index 5e5204f5c..59c2651ca 100644 --- a/tests/cpu/sve/mem/l2c_cross_cache_line_sve.cpp +++ b/tests/cpu/sve/mem/l2c_cross_cache_line_sve.cpp @@ -53,11 +53,7 @@ #include #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #include #include @@ -190,12 +186,13 @@ static inline void l2_dsb(void) {} static int l2c_cross_cache_line_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for l2c_cross_cache_line_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif (void)test; return EXIT_SUCCESS; diff --git a/tests/cpu/sve/mem/lsu_store_forward_sve.cpp b/tests/cpu/sve/mem/lsu_store_forward_sve.cpp index 462deba6a..53c813bd4 100644 --- a/tests/cpu/sve/mem/lsu_store_forward_sve.cpp +++ b/tests/cpu/sve/mem/lsu_store_forward_sve.cpp @@ -57,11 +57,7 @@ #include #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static constexpr size_t CACHE_LINE = 64; @@ -117,12 +113,13 @@ static inline void sf_load128(const void *a, uint64_t *lo, uint64_t *hi) { uint6 static int lsu_store_forward_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for lsu_store_forward_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif (void)test; return EXIT_SUCCESS; diff --git a/tests/cpu/sve/mem/mem_disambig_alu_sve.cpp b/tests/cpu/sve/mem/mem_disambig_alu_sve.cpp index cbb50db07..6a703c4ab 100644 --- a/tests/cpu/sve/mem/mem_disambig_alu_sve.cpp +++ b/tests/cpu/sve/mem/mem_disambig_alu_sve.cpp @@ -42,11 +42,7 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif /* 每线程消歧地址跨度(原 4096 字节) — 统一优先级链: @@ -78,16 +74,28 @@ struct MemDisambigAluSveData { static int mem_disambig_alu_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mem_disambig_alu_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; + const int lanes = (int)(svl / 8); /* f64 lanes = SVL bytes / 8 */ + if (lanes < 2 || lanes > 16) { /* [2,16] vs 128..1024-bit, NDEBUG-proof */ + log_error("mem_disambig_alu_sve: f64 lanes %d outside [2,16]" + " -- unit drift (svl %ld bytes)", lanes, svl); + return EXIT_FAILURE; } +#else + /* TU is aarch64-only in meson (tests/cpu/sve guard); keep the + * translation unit self-contained for single-TU compiles (the + * arm64_vl.h include above is conditionally compiled). */ + const int lanes = 0; #endif auto *data = static_cast(malloc(sizeof(MemDisambigAluSveData))); data->buffer_bytes = disambig_alu_sve_buffer_bytes(test); - data->lanes = (int)svcntd(); + data->lanes = lanes; data->offsets = static_cast(malloc(DISAMBIG_ALU_SVE_PATTERNS * sizeof(uint64_t))); data->values = static_cast(malloc(DISAMBIG_ALU_SVE_PATTERNS * sizeof(uint64_t))); data->expected = static_cast(malloc(DISAMBIG_ALU_SVE_PATTERNS * sizeof(uint64_t))); diff --git a/tests/cpu/sve/mem/mmu_split_tlb_sve.cpp b/tests/cpu/sve/mem/mmu_split_tlb_sve.cpp index db21516c0..b6143c39f 100644 --- a/tests/cpu/sve/mem/mmu_split_tlb_sve.cpp +++ b/tests/cpu/sve/mem/mmu_split_tlb_sve.cpp @@ -57,11 +57,7 @@ #include #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #include #include @@ -180,12 +176,13 @@ static inline uint64_t mmu_load128_hi(const void *addr) static int mmu_split_tlb_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mmu_split_tlb_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *data = static_cast(malloc(sizeof(MmuSplitTlbSveData))); if (!data) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mem/ooo_dep_chain_sve.cpp b/tests/cpu/sve/mem/ooo_dep_chain_sve.cpp index 63fe9db53..65bbf34dd 100644 --- a/tests/cpu/sve/mem/ooo_dep_chain_sve.cpp +++ b/tests/cpu/sve/mem/ooo_dep_chain_sve.cpp @@ -58,11 +58,7 @@ #include #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #include @@ -158,12 +154,13 @@ static void build_permutation(std::vector &chain, size_t n) static int ooo_dep_chain_sve_init(struct test *test) { #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for ooo_dep_chain_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif try { auto data = std::make_unique(); diff --git a/tests/cpu/sve/mem/partial_store_forwarding_sve.cpp b/tests/cpu/sve/mem/partial_store_forwarding_sve.cpp index 2bc13cc54..64a3a850f 100644 --- a/tests/cpu/sve/mem/partial_store_forwarding_sve.cpp +++ b/tests/cpu/sve/mem/partial_store_forwarding_sve.cpp @@ -21,23 +21,20 @@ #if defined(__aarch64__) #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif static int partial_store_forwarding_sve_init(struct test *test) { (void)test; #if defined(__aarch64__) - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for partial_store_forwarding_sve"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_asymm_distrib_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_asymm_distrib_int.cpp index ef2ae2f6f..d06886118 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_asymm_distrib_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_asymm_distrib_int.cpp @@ -6,15 +6,11 @@ #include #ifdef __aarch64__ #include -#include +#include #include #include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) #define BLOCK_ELEMENTS (VECTOR_SIZE * 2) // 每个块 8 个元素(两个向量) // 块数/总元素数在 init 中按目标内存动态计算(见 mesh_target_bytes)。 @@ -65,12 +61,13 @@ static size_t mesh_target_bytes(struct test *test) static int mesh_upi_sve_asymm_distrib_int_init(struct test *test) { if (sysconf(_SC_NPROCESSORS_ONLN) < 2) return -255; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_asymm_distrib_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_asymm_distrib_write_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_asymm_distrib_write_int.cpp index 0da70487d..0c5d1c146 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_asymm_distrib_write_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_asymm_distrib_write_int.cpp @@ -6,15 +6,11 @@ #include #ifdef __aarch64__ #include -#include +#include #include #include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) #define BLOCK_ELEMENTS (VECTOR_SIZE * 2) // 块数/总元素数在 init 中按目标内存动态计算(见 mesh_target_bytes)。 @@ -60,12 +56,13 @@ static size_t mesh_target_bytes(struct test *test) static int mesh_upi_sve_asymm_distrib_write_int_init(struct test *test) { if (sysconf(_SC_NPROCESSORS_ONLN) < 2) return -255; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_asymm_distrib_write_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_asymm_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_asymm_int.cpp index d8ec65ffa..c182c2e86 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_asymm_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_asymm_int.cpp @@ -6,15 +6,11 @@ #include #ifdef __aarch64__ #include -#include +#include #include #include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) #define BLOCK_ELEMENTS (VECTOR_SIZE * 2) // 每个块 8 个元素(两个向量) // 块数/总元素数在 init 中按目标内存动态计算(见 mesh_target_bytes)。 @@ -64,12 +60,13 @@ static size_t mesh_target_bytes(struct test *test) static int mesh_upi_sve_asymm_int_init(struct test *test) { if (sysconf(_SC_NPROCESSORS_ONLN) < 2) return -255; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_asymm_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_asymm_write_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_asymm_write_int.cpp index fa8edc8f3..9282a39f0 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_asymm_write_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_asymm_write_int.cpp @@ -6,15 +6,11 @@ #include #ifdef __aarch64__ #include -#include +#include #include #include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) #define BLOCK_ELEMENTS (VECTOR_SIZE * 2) // 块数/总元素数在 init 中按目标内存动态计算(见 mesh_target_bytes)。 @@ -61,12 +57,13 @@ static size_t mesh_target_bytes(struct test *test) static int mesh_upi_sve_asymm_write_int_init(struct test *test) { if (sysconf(_SC_NPROCESSORS_ONLN) < 2) return -255; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_asymm_write_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_read_L3_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_read_L3_int.cpp index c5db0039f..0c818ea34 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_read_L3_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_read_L3_int.cpp @@ -6,13 +6,9 @@ #include #ifdef __aarch64__ #include -#include +#include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) // 总元素数在 init 中按目标内存动态计算(见 mesh_target_bytes)。 @@ -48,12 +44,13 @@ static size_t mesh_target_bytes(struct test *test) } static int mesh_upi_sve_read_L3_int_init(struct test *test) { - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_read_L3_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_read_only_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_read_only_int.cpp index 53c93729a..dc4fe4619 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_read_only_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_read_only_int.cpp @@ -6,13 +6,9 @@ #include #ifdef __aarch64__ #include -#include +#include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) // 总元素数在 init 中按目标内存动态计算(见 mesh_target_bytes)。 @@ -48,12 +44,13 @@ static size_t mesh_target_bytes(struct test *test) } static int mesh_upi_sve_read_only_int_init(struct test *test) { - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_read_only_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_sym.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_sym.cpp index 77f1141ec..f690908c4 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_sym.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_sym.cpp @@ -6,15 +6,11 @@ #include #ifdef __aarch64__ #include -#include +#include #include #include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) /* 执行期勘误(B1-001 修复时发现):原移植为 (VECTOR_SIZE * 2),但写阶段 * 每块只存 1 个向量(4 元素)——块距 8、半数元素从未被 SVE store 覆盖 @@ -68,12 +64,13 @@ static size_t mesh_target_bytes(struct test *test) static int mesh_upi_sve_sym_init(struct test *test) { if (sysconf(_SC_NPROCESSORS_ONLN) < 2) return -255; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_sym"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_symm_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_symm_int.cpp index a69d7ee30..319aebce9 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_symm_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_symm_int.cpp @@ -6,15 +6,11 @@ #include #ifdef __aarch64__ #include -#include +#include #include #include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) #define BLOCK_ELEMENTS (VECTOR_SIZE * 2) // 每个块 8 个元素(两个向量) // 块数/总元素数在 init 中按目标内存动态计算(见 mesh_target_bytes)。 @@ -63,12 +59,13 @@ static size_t mesh_target_bytes(struct test *test) static int mesh_upi_sve_symm_int_init(struct test *test) { if (sysconf(_SC_NPROCESSORS_ONLN) < 2) return -255; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_symm_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_distrib_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_distrib_int.cpp index f2f643511..510bff6bc 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_distrib_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_distrib_int.cpp @@ -6,15 +6,11 @@ #include #ifdef __aarch64__ #include -#include +#include #include #include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define NEON_VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) #define BLOCK_ELEMENTS 16 // 每个块 16 个 int32(原由 4 个 NEON 向量组成) #define VECTORS_PER_BLOCK (BLOCK_ELEMENTS / NEON_VECTOR_SIZE) // = 4 @@ -60,12 +56,13 @@ static size_t mesh_target_bytes(struct test *test) static int mesh_upi_sve_wide_asymm_distrib_int_init(struct test *test) { if (sysconf(_SC_NPROCESSORS_ONLN) < 2) return -255; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_wide_asymm_distrib_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_distrib_write_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_distrib_write_int.cpp index 193e96616..1d38b5754 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_distrib_write_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_distrib_write_int.cpp @@ -6,15 +6,11 @@ #include #ifdef __aarch64__ #include -#include +#include #include #include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define NEON_VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) #define BLOCK_ELEMENTS 16 // 每个块 16 个 int32(原由 4 个 NEON 向量组成) #define VECTORS_PER_BLOCK (BLOCK_ELEMENTS / NEON_VECTOR_SIZE) // = 4 @@ -58,12 +54,13 @@ static size_t mesh_target_bytes(struct test *test) static int mesh_upi_sve_wide_asymm_distrib_write_int_init(struct test *test) { if (sysconf(_SC_NPROCESSORS_ONLN) < 2) return -255; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_wide_asymm_distrib_write_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_int.cpp index 4becef63b..45c2f384a 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_int.cpp @@ -6,15 +6,11 @@ #include #ifdef __aarch64__ #include -#include +#include #include #include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define NEON_VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) #define BLOCK_ELEMENTS 16 // 每个块 16 个 int32(原由 4 个 NEON 向量组成) #define VECTORS_PER_BLOCK (BLOCK_ELEMENTS / NEON_VECTOR_SIZE) // = 4 @@ -60,12 +56,13 @@ static size_t mesh_target_bytes(struct test *test) static int mesh_upi_sve_wide_asymm_int_init(struct test *test) { if (sysconf(_SC_NPROCESSORS_ONLN) < 2) return -255; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_wide_asymm_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_read_L3_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_read_L3_int.cpp index c395f6561..66c13c6c7 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_read_L3_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_read_L3_int.cpp @@ -6,11 +6,7 @@ #include #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #include #define NEON_VECTOR_SIZE 4 // NEON 一次处理 4 个 int32 diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_read_only_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_read_only_int.cpp index 0b10effc2..be979ae19 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_read_only_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_read_only_int.cpp @@ -6,11 +6,7 @@ #include #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #include #define NEON_VECTOR_SIZE 4 // NEON 一次处理 4 个 int32 @@ -50,12 +46,13 @@ static size_t mesh_target_bytes(struct test *test) } static int mesh_upi_sve_wide_asymm_read_only_int_init(struct test *test) { - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_wide_asymm_read_only_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; @@ -201,13 +198,6 @@ static int mesh_upi_sve_wide_asymm_read_only_int_finish(struct test *test) { #else static int mesh_upi_sve_wide_asymm_read_only_int_init(struct test *test) { - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_wide_asymm_read_only_int"); - return EXIT_SKIP; - } - (void)test; log_skip(CpuNotSupportedSkipCategory, "to be implemented (placeholder): ARM NEON required for mesh_upi_sve_wide_asymm_read_only_int"); diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_write_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_write_int.cpp index bc0dae5d2..6938fa954 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_write_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_write_int.cpp @@ -6,15 +6,11 @@ #include #ifdef __aarch64__ #include -#include +#include #include #include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define NEON_VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) #define BLOCK_ELEMENTS 16 // 每个块 16 个 int32(原由 4 个 NEON 向量组成) #define VECTORS_PER_BLOCK (BLOCK_ELEMENTS / NEON_VECTOR_SIZE) // = 4 @@ -58,12 +54,13 @@ static size_t mesh_target_bytes(struct test *test) static int mesh_upi_sve_wide_asymm_write_int_init(struct test *test) { if (sysconf(_SC_NPROCESSORS_ONLN) < 2) return -255; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_wide_asymm_write_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_write_only_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_write_only_int.cpp index b8df1d69f..c51b7defb 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_write_only_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_wide_asymm_write_only_int.cpp @@ -6,11 +6,7 @@ #include #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #include #include #include @@ -56,12 +52,13 @@ static size_t mesh_target_bytes(struct test *test) } static int mesh_upi_sve_wide_asymm_write_only_int_init(struct test *test) { - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_wide_asymm_write_only_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } if (sysconf(_SC_NPROCESSORS_ONLN) < 2) { return -255; // 需要至少 2 个线程 @@ -284,13 +281,6 @@ static int mesh_upi_sve_wide_asymm_write_only_int_finish(struct test *test) { #else static int mesh_upi_sve_wide_asymm_write_only_int_init(struct test *test) { - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_wide_asymm_write_only_int"); - return EXIT_SKIP; - } - (void)test; log_skip(CpuNotSupportedSkipCategory, "to be implemented (placeholder): ARM NEON required for mesh_upi_sve_wide_asymm_write_only_int"); diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_wide_sym.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_wide_sym.cpp index 03f7e4d24..69b3a61f8 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_wide_sym.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_wide_sym.cpp @@ -6,15 +6,11 @@ #include #ifdef __aarch64__ #include -#include +#include #include #include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define VECTOR_SIZE 4 // 原负载:一次处理 4 个元素(SVE 谓词分批) #define BLOCK_ELEMENTS 16 // 每个块 16 个元素(原由 4 个 NEON 向量组成) #define VECTORS_PER_BLOCK (BLOCK_ELEMENTS / VECTOR_SIZE) // = 4 @@ -65,12 +61,13 @@ static size_t mesh_target_bytes(struct test *test) static int mesh_upi_sve_wide_sym_init(struct test *test) { if (sysconf(_SC_NPROCESSORS_ONLN) < 2) return -255; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_wide_sym"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_wide_symm_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_wide_symm_int.cpp index 70a9ef5c4..2d455cfa3 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_wide_symm_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_wide_symm_int.cpp @@ -6,15 +6,11 @@ #include #ifdef __aarch64__ #include -#include +#include #include #include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define NEON_VECTOR_SIZE 4 // 原负载:一次处理 4 个 int32(SVE 谓词分批) #define BLOCK_SIZE 16 // 逻辑块大小(原由 4 个 NEON 向量组成) #define VECTORS_PER_BLOCK (BLOCK_SIZE / NEON_VECTOR_SIZE) // = 4 @@ -60,12 +56,13 @@ static size_t mesh_target_bytes(struct test *test) static int mesh_upi_sve_wide_symm_int_init(struct test *test) { if (sysconf(_SC_NPROCESSORS_ONLN) < 2) return -255; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_wide_symm_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/mesh/mesh_upi_sve_write_only_int.cpp b/tests/cpu/sve/mesh/mesh_upi_sve_write_only_int.cpp index cd43e428e..b0eda956d 100644 --- a/tests/cpu/sve/mesh/mesh_upi_sve_write_only_int.cpp +++ b/tests/cpu/sve/mesh/mesh_upi_sve_write_only_int.cpp @@ -6,13 +6,9 @@ #include #ifdef __aarch64__ #include -#include +#include #include -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif - #define VECTOR_SIZE 4 // 原负载:每次存储 4 个 int32(SVE 谓词分批) // 每线程元素数在 run 中按目标内存动态计算(见 mesh_target_bytes)。 @@ -48,12 +44,13 @@ static size_t mesh_target_bytes(struct test *test) } static int mesh_upi_sve_write_only_int_init(struct test *test) { - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for mesh_upi_sve_write_only_int"); + /* All-VL Phase 2 P6: per-test auxv hand-probe -> framework + * layer: arm64_require_sve_vl does the SVE capability check + * + 128..1024-bit range gate in one call (skip reason + * framework-issued). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } auto *td = new TestData; if (!td) return EXIT_FAILURE; diff --git a/tests/cpu/sve/sve_rot_ldr_at_top.cpp b/tests/cpu/sve/sve_rot_ldr_at_top.cpp index 4bf52676e..855567cfe 100644 --- a/tests/cpu/sve/sve_rot_ldr_at_top.cpp +++ b/tests/cpu/sve/sve_rot_ldr_at_top.cpp @@ -71,7 +71,7 @@ static size_t sve_rot_ldr_at_top_slots(struct test *test, size_t vl_bytes) struct SveRotLdrAtTopData { int vl_slots; /* element count in full z-register widths */ - size_t vl_bytes; /* svcntb() at init */ + size_t vl_bytes; /* init-time VL bytes returned by arm64_require_sve_vl */ uint8_t *srcA; uint8_t *srcB; uint8_t *scratch; diff --git a/tests/cpu/sve/vector2/insert_extract_sve.cpp b/tests/cpu/sve/vector2/insert_extract_sve.cpp index e47035ff7..cb071e00f 100644 --- a/tests/cpu/sve/vector2/insert_extract_sve.cpp +++ b/tests/cpu/sve/vector2/insert_extract_sve.cpp @@ -22,11 +22,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define IE_LANES 4 @@ -34,12 +30,11 @@ static int insert_extract_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for insert_extract_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/vector2/kreg1_sve.cpp b/tests/cpu/sve/vector2/kreg1_sve.cpp index 10b89e05c..c75330b02 100644 --- a/tests/cpu/sve/vector2/kreg1_sve.cpp +++ b/tests/cpu/sve/vector2/kreg1_sve.cpp @@ -23,22 +23,17 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #define KREG1_SVE_LANES 4 static int kreg1_sve_init(struct test *test) { (void)test; - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for kreg1_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/vector2/kreg4_sve.cpp b/tests/cpu/sve/vector2/kreg4_sve.cpp index 74fa71935..e03614fd9 100644 --- a/tests/cpu/sve/vector2/kreg4_sve.cpp +++ b/tests/cpu/sve/vector2/kreg4_sve.cpp @@ -23,11 +23,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #define KREG4_ELEMS 16 @@ -35,12 +31,11 @@ static int kreg4_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for kreg4_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/vector2/kreg7_sve.cpp b/tests/cpu/sve/vector2/kreg7_sve.cpp index 35de5c67e..6516116c6 100644 --- a/tests/cpu/sve/vector2/kreg7_sve.cpp +++ b/tests/cpu/sve/vector2/kreg7_sve.cpp @@ -24,11 +24,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif #ifdef __aarch64__ @@ -92,12 +88,11 @@ static typename Wider::U sve_topbit_mask(const T *data, int els) { static int kreg7_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for kreg7_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; } diff --git a/tests/cpu/sve/vector2/swizzle_sve.cpp b/tests/cpu/sve/vector2/swizzle_sve.cpp index 0380ff997..3916a4344 100644 --- a/tests/cpu/sve/vector2/swizzle_sve.cpp +++ b/tests/cpu/sve/vector2/swizzle_sve.cpp @@ -21,11 +21,7 @@ #ifdef __aarch64__ #include -#include - -#ifndef HWCAP_SVE -#define HWCAP_SVE (1 << 22) -#endif +#include #endif // 标量参考实现(与原版一致) @@ -38,12 +34,11 @@ static void swizzle_reference(const float *src, float *dst, const int *perm) { static int swizzle_sve_init(struct test *test) { (void)test; #ifdef __aarch64__ - unsigned long hwcap = getauxval(AT_HWCAP); - if ((hwcap & HWCAP_SVE) == 0) { - log_skip(CpuNotSupportedSkipCategory, - "to be implemented (placeholder): ARM SVE required for swizzle_sve"); + /* All-VL Phase 2 P6: SVE capability + 128..1024-bit VL range + * gate in one framework-layer call (device/cpu/arm64/arm64_vl.h). */ + const long svl = arm64_require_sve_vl(test, 128, 1024); + if (svl < 0) return EXIT_SKIP; - } #endif return EXIT_SUCCESS; }