From 3ce87464b13acc0f85a9bb690321f7756021708d Mon Sep 17 00:00:00 2001 From: Martin Kroeker Date: Thu, 15 Oct 2026 00:59:08 +0200 Subject: [PATCH 1/8] Pick SVE fallback kernel by vector length instead of defaulting to ARMV8SVE --- driver/others/dynamic_arm64.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/driver/others/dynamic_arm64.c b/driver/others/dynamic_arm64.c index 6ad4c71527..d9424cbb97 100644 --- a/driver/others/dynamic_arm64.c +++ b/driver/others/dynamic_arm64.c @@ -550,7 +550,18 @@ static gotoblas_t *get_coretype(void) { #ifndef NO_SVE if ((getauxval(AT_HWCAP) & HWCAP_SVE)) { - return &gotoblas_ARMV8SVE; + int veclen = svcntw(); + switch(veclen) { + case 4: + return &gotoblas_ARMV8SVE; + break; + case 8: + return &gotoblas_NEOVERSEV1; + break; + case 16: + default: + return &gotoblas_A64FX; + } } #endif From 429a5bf9e2a12ccd4a71717c6845d0d5d1e7948e Mon Sep 17 00:00:00 2001 From: Martin Kroeker Date: Thu, 15 Oct 2026 11:22:08 +0200 Subject: [PATCH 2/8] Use inline asm for sve vector length --- driver/others/dynamic_arm64.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/driver/others/dynamic_arm64.c b/driver/others/dynamic_arm64.c index d9424cbb97..ed85cf8f56 100644 --- a/driver/others/dynamic_arm64.c +++ b/driver/others/dynamic_arm64.c @@ -550,7 +550,9 @@ static gotoblas_t *get_coretype(void) { #ifndef NO_SVE if ((getauxval(AT_HWCAP) & HWCAP_SVE)) { - int veclen = svcntw(); + uint64_t veclen; + asm(svcntw" %[SIZE_]" : [SIZE_] "=r" (veclen) : : ); + switch(veclen) { case 4: return &gotoblas_ARMV8SVE; From 53a1a57681bb5169d7ec76ee29f2dd9138182e93 Mon Sep 17 00:00:00 2001 From: Martin Kroeker Date: Thu, 15 Oct 2026 11:53:52 +0200 Subject: [PATCH 3/8] fix quotes --- driver/others/dynamic_arm64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/others/dynamic_arm64.c b/driver/others/dynamic_arm64.c index ed85cf8f56..e7a24bfd1b 100644 --- a/driver/others/dynamic_arm64.c +++ b/driver/others/dynamic_arm64.c @@ -551,7 +551,7 @@ static gotoblas_t *get_coretype(void) { #ifndef NO_SVE if ((getauxval(AT_HWCAP) & HWCAP_SVE)) { uint64_t veclen; - asm(svcntw" %[SIZE_]" : [SIZE_] "=r" (veclen) : : ); + asm("svcntw %[SIZE_]" : [SIZE_] "=r" (veclen) : : ); switch(veclen) { case 4: From 31b7bf88d99ce5fbaaf218ea4d8c1c454cb9a82d Mon Sep 17 00:00:00 2001 From: Martin Kroeker Date: Thu, 15 Oct 2026 12:10:59 +0200 Subject: [PATCH 4/8] use correct mnemonic --- driver/others/dynamic_arm64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/others/dynamic_arm64.c b/driver/others/dynamic_arm64.c index e7a24bfd1b..f300ad3e56 100644 --- a/driver/others/dynamic_arm64.c +++ b/driver/others/dynamic_arm64.c @@ -551,7 +551,7 @@ static gotoblas_t *get_coretype(void) { #ifndef NO_SVE if ((getauxval(AT_HWCAP) & HWCAP_SVE)) { uint64_t veclen; - asm("svcntw %[SIZE_]" : [SIZE_] "=r" (veclen) : : ); + asm("cntw %[SIZE_]" : [SIZE_] "=r" (veclen) : : ); switch(veclen) { case 4: From def9aeec744efab3b8ff5dd7e8da8809024c2c66 Mon Sep 17 00:00:00 2001 From: Martin Kroeker Date: Thu, 15 Oct 2026 13:12:08 +0200 Subject: [PATCH 5/8] Fall back to prctl on Linux if sve not available to the compiler --- driver/others/dynamic_arm64.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/driver/others/dynamic_arm64.c b/driver/others/dynamic_arm64.c index f300ad3e56..61ef6e64c1 100644 --- a/driver/others/dynamic_arm64.c +++ b/driver/others/dynamic_arm64.c @@ -48,6 +48,7 @@ #if (defined OS_LINUX || defined OS_ANDROID) #include #include +#include #endif #ifdef __APPLE__ @@ -550,9 +551,16 @@ static gotoblas_t *get_coretype(void) { #ifndef NO_SVE if ((getauxval(AT_HWCAP) & HWCAP_SVE)) { - uint64_t veclen; + int veclen; +#ifdef __ARM_FEATURE_SVE asm("cntw %[SIZE_]" : [SIZE_] "=r" (veclen) : : ); - +#elif defined(OS_LINUX) + veclen = prctl(PR_SVE_GET_VL); + if (veclen > -1 ) veclen &= PR_SVE_VL_MASK; + else veclen = 4; +#else + veclen = 4; +#endif switch(veclen) { case 4: return &gotoblas_ARMV8SVE; From df61124ae4fa7aeb89e7a9a843a21da434f5b452 Mon Sep 17 00:00:00 2001 From: Martin Kroeker Date: Thu, 15 Oct 2026 13:38:28 +0200 Subject: [PATCH 6/8] Update dynamic_arm64.c --- driver/others/dynamic_arm64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/others/dynamic_arm64.c b/driver/others/dynamic_arm64.c index 61ef6e64c1..c2296588bc 100644 --- a/driver/others/dynamic_arm64.c +++ b/driver/others/dynamic_arm64.c @@ -556,7 +556,7 @@ static gotoblas_t *get_coretype(void) { asm("cntw %[SIZE_]" : [SIZE_] "=r" (veclen) : : ); #elif defined(OS_LINUX) veclen = prctl(PR_SVE_GET_VL); - if (veclen > -1 ) veclen &= PR_SVE_VL_MASK; + if (veclen > -1 ) veclen &= PR_SVE_VL_LEN_MASK; else veclen = 4; #else veclen = 4; From 8d91f9493e39d97ab3a3fb8dccbcfe2ab6ccee3b Mon Sep 17 00:00:00 2001 From: Martin Kroeker Date: Thu, 15 Oct 2026 16:45:33 +0200 Subject: [PATCH 7/8] Scale prctl result to match cntw unit --- driver/others/dynamic_arm64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/others/dynamic_arm64.c b/driver/others/dynamic_arm64.c index c2296588bc..aaf4ab6e47 100644 --- a/driver/others/dynamic_arm64.c +++ b/driver/others/dynamic_arm64.c @@ -556,7 +556,7 @@ static gotoblas_t *get_coretype(void) { asm("cntw %[SIZE_]" : [SIZE_] "=r" (veclen) : : ); #elif defined(OS_LINUX) veclen = prctl(PR_SVE_GET_VL); - if (veclen > -1 ) veclen &= PR_SVE_VL_LEN_MASK; + if (veclen > -1) veclen = (veclen & PR_SVE_VL_LEN_MASK) / 4; else veclen = 4; #else veclen = 4; From 912f266773ed157d4cca20ba345a7f4e990ab708 Mon Sep 17 00:00:00 2001 From: Martin Kroeker Date: Fri, 16 Oct 2026 22:48:11 +0200 Subject: [PATCH 8/8] Fall back to ARMV8 if veclen of unknown SVE-capable cpu is not among 128, 256 or 512 --- driver/others/dynamic_arm64.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/driver/others/dynamic_arm64.c b/driver/others/dynamic_arm64.c index aaf4ab6e47..db543ba23d 100644 --- a/driver/others/dynamic_arm64.c +++ b/driver/others/dynamic_arm64.c @@ -232,7 +232,7 @@ extern gotoblas_t gotoblas_VORTEXM4; extern void openblas_warning(int verbose, const char * msg); #define FALLBACK_VERBOSE 1 #define NEOVERSEN1_FALLBACK "OpenBLAS : Your OS does not support SVE instructions. OpenBLAS is using Neoverse N1 kernels as a fallback, which may give poorer performance.\n" - +#define VECLEN_FALLBACK "OpenBLAS : None of the supported targets matches the SVE vector length of your system. Falling back to plain ARMV8 which may give poorer performance.\n" #define NUM_CORETYPES 21 /* @@ -569,8 +569,10 @@ static gotoblas_t *get_coretype(void) { return &gotoblas_NEOVERSEV1; break; case 16: - default: return &gotoblas_A64FX; + default: + openblas_warning(FALLBACK_VERBOSE, VECLEN_FALLBACK); + return &gotoblas_ARMV8; } } #endif