From 550e0983d57d40e7ee9c52ce3de09de6182d74d2 Mon Sep 17 00:00:00 2001 From: michael tesch Date: Wed, 21 Oct 2026 14:00:46 -0500 Subject: [PATCH] arm64: read the SME2 vector length only after the FEAT_SME2 test svcntsw() has no side effects for clang, which if-converted the expression and ran RDSVL before the FEAT_SME2 result was tested. On a CPU without SME that is SIGILL. A noinline function with volatile inline asm keeps RDSVL behind the test. Fixes #6150 --- kernel/arm64/sme2_gemm_detect.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel/arm64/sme2_gemm_detect.h b/kernel/arm64/sme2_gemm_detect.h index 8830e7dd32..9b4dd8dcf7 100644 --- a/kernel/arm64/sme2_gemm_detect.h +++ b/kernel/arm64/sme2_gemm_detect.h @@ -41,6 +41,13 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #endif +/* Streaming vector length in fp32 lanes; volatile asm and noinline keep RDSVL behind the FEAT_SME2 test. */ +static __attribute__((noinline)) int s2_svl_lanes(void) { + unsigned long svl; + __asm__ volatile("rdsvl %0, #1" : "=r"(svl)); + return (int)(svl / 4); +} + /* SME2 with a 512-bit streaming vector length (the kernels assume 16 fp32 lanes). */ static inline int s2_usable(void) { static int ok = -1; @@ -53,7 +60,7 @@ static inline int s2_usable(void) { #elif defined(__linux__) sme2 = (getauxval(AT_HWCAP2) & (1UL << 37)) != 0; /* HWCAP2_SME2 */ #endif - ok = sme2 && svcntsw() == 16; + ok = sme2 ? s2_svl_lanes() == 16 : 0; } return ok; }