From: Martin Storsjö martin@martin.st
Don't use strstr() for finding features - some feature names may be substrings of other feature names.
Verify that the strings that are found are surrounded by whitespace, or are located at the start/end of the string. --- dlls/ntdll/unix/system.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index 9343d13262c..2d6beae0689 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -541,6 +541,25 @@ static void get_cpuinfo( SYSTEM_CPU_INFORMATION *info )
#elif defined(__arm__) || defined(__aarch64__)
+static int has_feature( const char *line, const char *feat ) +{ + const char *linepos = line; + size_t featlen = strlen(feat); + while (1) + { + const char *ptr = strstr(linepos, feat); + if (!ptr) + return 0; + /* Check that the match is surrounded by whitespace, or at the + start/end of the string. */ + if ((ptr == line || isspace(ptr[-1])) && + (isspace(linepos[featlen]) || !linepos[featlen])) + return 1; + linepos += featlen; + } + return 0; +} + static void get_cpuinfo( SYSTEM_CPU_INFORMATION *info ) { ULONGLONG features = 0; @@ -570,15 +589,15 @@ static void get_cpuinfo( SYSTEM_CPU_INFORMATION *info ) else if (!strcmp( line, "Features" )) { #ifdef __arm__ - if (strstr(value, "vfpv3")) features |= CPU_FEATURE_ARM_VFP_32; - if (strstr(value, "neon")) features |= CPU_FEATURE_ARM_NEON; + if (has_feature(value, "vfpv3")) features |= CPU_FEATURE_ARM_VFP_32; + if (has_feature(value, "neon")) features |= CPU_FEATURE_ARM_NEON; #else - if (strstr(value, "crc32")) features |= CPU_FEATURE_ARM_V8_CRC32; - if (strstr(value, "aes")) features |= CPU_FEATURE_ARM_V8_CRYPTO; - if (strstr(value, "atomics")) features |= CPU_FEATURE_ARM_V81_ATOMIC; - if (strstr(value, "asimddp")) features |= CPU_FEATURE_ARM_V82_DP; - if (strstr(value, "jscvt")) features |= CPU_FEATURE_ARM_V83_JSCVT; - if (strstr(value, "lrcpc")) features |= CPU_FEATURE_ARM_V83_LRCPC; + if (has_feature(value, "crc32")) features |= CPU_FEATURE_ARM_V8_CRC32; + if (has_feature(value, "aes")) features |= CPU_FEATURE_ARM_V8_CRYPTO; + if (has_feature(value, "atomics")) features |= CPU_FEATURE_ARM_V81_ATOMIC; + if (has_feature(value, "asimddp")) features |= CPU_FEATURE_ARM_V82_DP; + if (has_feature(value, "jscvt")) features |= CPU_FEATURE_ARM_V83_JSCVT; + if (has_feature(value, "lrcpc")) features |= CPU_FEATURE_ARM_V83_LRCPC; #endif continue; }
From: Martin Storsjö martin@martin.st
These were defined in WinSDK 10.0.26100. --- include/winnt.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/include/winnt.h b/include/winnt.h index 81244e4ab31..df5113051d2 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -1127,6 +1127,21 @@ typedef enum _HEAP_INFORMATION_CLASS { #define PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE 43 #define PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE 44 #define PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE 45 +#define PF_ARM_SVE_INSTRUCTIONS_AVAILABLE 46 +#define PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE 47 +#define PF_ARM_SVE2_1_INSTRUCTIONS_AVAILABLE 48 +#define PF_ARM_SVE_AES_INSTRUCTIONS_AVAILABLE 49 +#define PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE 50 +#define PF_ARM_SVE_BITPERM_INSTRUCTIONS_AVAILABLE 51 +#define PF_ARM_SVE_BF16_INSTRUCTIONS_AVAILABLE 52 +#define PF_ARM_SVE_EBF16_INSTRUCTIONS_AVAILABLE 53 +#define PF_ARM_SVE_B16B16_INSTRUCTIONS_AVAILABLE 54 +#define PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE 55 +#define PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE 56 +#define PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE 57 +#define PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE 58 +#define PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE 59 +#define PF_BMI2_INSTRUCTIONS_AVAILABLE 60
/* Execution state flags */
From: Martin Storsjö martin@martin.st
--- dlls/ntdll/signal_arm64.c | 16 +++++++++++++++- dlls/ntdll/unix/system.c | 30 ++++++++++++++++++++++-------- include/winternl.h | 14 ++++++++++++++ programs/wineboot/wineboot.c | 14 ++++++++++++++ 4 files changed, 65 insertions(+), 9 deletions(-)
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 0531083ba4e..a93e3641684 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -623,7 +623,21 @@ BOOLEAN WINAPI RtlIsProcessorFeaturePresent( UINT feature ) (1ull << PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE) | (1ull << PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE) | (1ull << PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE) | - (1ull << PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE); + (1ull << PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE2_1_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE_AES_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE_BITPERM_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE_BF16_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE_EBF16_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE_B16B16_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE) | + (1ull << PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE);
return (feature < PROCESSOR_FEATURE_MAX && (arm64_features & (1ull << feature)) && user_shared_data->ProcessorFeatures[feature]); diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index 2d6beae0689..f47925018b8 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -589,15 +589,29 @@ static void get_cpuinfo( SYSTEM_CPU_INFORMATION *info ) else if (!strcmp( line, "Features" )) { #ifdef __arm__ - if (has_feature(value, "vfpv3")) features |= CPU_FEATURE_ARM_VFP_32; - if (has_feature(value, "neon")) features |= CPU_FEATURE_ARM_NEON; + if (has_feature(value, "vfpv3")) features |= CPU_FEATURE_ARM_VFP_32; + if (has_feature(value, "neon")) features |= CPU_FEATURE_ARM_NEON; #else - if (has_feature(value, "crc32")) features |= CPU_FEATURE_ARM_V8_CRC32; - if (has_feature(value, "aes")) features |= CPU_FEATURE_ARM_V8_CRYPTO; - if (has_feature(value, "atomics")) features |= CPU_FEATURE_ARM_V81_ATOMIC; - if (has_feature(value, "asimddp")) features |= CPU_FEATURE_ARM_V82_DP; - if (has_feature(value, "jscvt")) features |= CPU_FEATURE_ARM_V83_JSCVT; - if (has_feature(value, "lrcpc")) features |= CPU_FEATURE_ARM_V83_LRCPC; + if (has_feature(value, "crc32")) features |= CPU_FEATURE_ARM_V8_CRC32; + if (has_feature(value, "aes")) features |= CPU_FEATURE_ARM_V8_CRYPTO; + if (has_feature(value, "atomics")) features |= CPU_FEATURE_ARM_V81_ATOMIC; + if (has_feature(value, "asimddp")) features |= CPU_FEATURE_ARM_V82_DP; + if (has_feature(value, "jscvt")) features |= CPU_FEATURE_ARM_V83_JSCVT; + if (has_feature(value, "lrcpc")) features |= CPU_FEATURE_ARM_V83_LRCPC; + if (has_feature(value, "sve")) features |= CPU_FEATURE_ARM_SVE; + if (has_feature(value, "sve2")) features |= CPU_FEATURE_ARM_SVE2; + if (has_feature(value, "sve2p1")) features |= CPU_FEATURE_ARM_SVE2_1; + if (has_feature(value, "sveaes")) features |= CPU_FEATURE_ARM_SVE_AES; + if (has_feature(value, "svepmull")) features |= CPU_FEATURE_ARM_SVE_PMULL128; + if (has_feature(value, "svebitperm")) features |= CPU_FEATURE_ARM_SVE_BITPERM; + if (has_feature(value, "svebf16")) features |= CPU_FEATURE_ARM_SVE_BF16; + if (has_feature(value, "sveebf16")) features |= CPU_FEATURE_ARM_SVE_EBF16; + if (has_feature(value, "sveb16b16")) features |= CPU_FEATURE_ARM_SVE_B16B16; + if (has_feature(value, "svesha3")) features |= CPU_FEATURE_ARM_SVE_SHA3; + if (has_feature(value, "svesm4")) features |= CPU_FEATURE_ARM_SVE_SM4; + if (has_feature(value, "svei8mm")) features |= CPU_FEATURE_ARM_SVE_I8MM; + if (has_feature(value, "svef32mm")) features |= CPU_FEATURE_ARM_SVE_F32MM; + if (has_feature(value, "svef64mm")) features |= CPU_FEATURE_ARM_SVE_F64MM; #endif continue; } diff --git a/include/winternl.h b/include/winternl.h index 6a7aa84dfdb..828fbc6e915 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2777,6 +2777,20 @@ typedef struct _SYSTEM_CPU_INFORMATION { #define CPU_FEATURE_ARM_V82_DP 0x00000020 #define CPU_FEATURE_ARM_V83_JSCVT 0x00000040 #define CPU_FEATURE_ARM_V83_LRCPC 0x00000080 +#define CPU_FEATURE_ARM_SVE 0x00000100 +#define CPU_FEATURE_ARM_SVE2 0x00000200 +#define CPU_FEATURE_ARM_SVE2_1 0x00000400 +#define CPU_FEATURE_ARM_SVE_AES 0x00000800 +#define CPU_FEATURE_ARM_SVE_PMULL128 0x00001000 +#define CPU_FEATURE_ARM_SVE_BITPERM 0x00002000 +#define CPU_FEATURE_ARM_SVE_BF16 0x00004000 +#define CPU_FEATURE_ARM_SVE_EBF16 0x00008000 +#define CPU_FEATURE_ARM_SVE_B16B16 0x00010000 +#define CPU_FEATURE_ARM_SVE_SHA3 0x00020000 +#define CPU_FEATURE_ARM_SVE_SM4 0x00040000 +#define CPU_FEATURE_ARM_SVE_I8MM 0x00080000 +#define CPU_FEATURE_ARM_SVE_F32MM 0x00100000 +#define CPU_FEATURE_ARM_SVE_F64MM 0x00200000
typedef struct _SYSTEM_PROCESSOR_FEATURES_INFORMATION { diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c index 1dc3fdb78e7..71082af8807 100644 --- a/programs/wineboot/wineboot.c +++ b/programs/wineboot/wineboot.c @@ -471,6 +471,20 @@ static void create_user_shared_data(void) features[PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_V82_DP); features[PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_V83_JSCVT); features[PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_V83_LRCPC); + features[PF_ARM_SVE_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE); + features[PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE2); + features[PF_ARM_SVE2_1_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE2_1); + features[PF_ARM_SVE_AES_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE_AES); + features[PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE_PMULL128); + features[PF_ARM_SVE_BITPERM_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE_BITPERM); + features[PF_ARM_SVE_BF16_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE_BF16); + features[PF_ARM_SVE_EBF16_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE_EBF16); + features[PF_ARM_SVE_B16B16_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE_B16B16); + features[PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE_SHA3); + features[PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE_SM4); + features[PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE_I8MM); + features[PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE_F32MM); + features[PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE] = !!(sci.ProcessorFeatureBits & CPU_FEATURE_ARM_SVE_F64MM); features[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE; features[PF_NX_ENABLED] = TRUE; features[PF_FASTFAIL_AVAILABLE] = TRUE;
I wonder if advertising sve without supporting sve xstate is a good idea, though it'll be a while till devices ship with that to implement it accurately