From 83c1fb9fd3631921f7bd151c941ec25f50febe1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bob=20Dr=C3=B6ge?= Date: Fri, 18 Sep 2026 16:52:00 +0200 Subject: [PATCH 1/3] use cpu_features to detect Granite Rapids and newer --- init/eessi_archdetect.sh | 42 +++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/init/eessi_archdetect.sh b/init/eessi_archdetect.sh index 1dbe6b51..fcb4ff10 100755 --- a/init/eessi_archdetect.sh +++ b/init/eessi_archdetect.sh @@ -70,6 +70,24 @@ get_cpuinfo(){ grep -i "$cpuinfo_pattern" ${EESSI_PROC_CPUINFO:-/proc/cpuinfo} | tail -n 1 | sed "s/$cpuinfo_pattern//i" } +# CPU specification of host system as reported by cpu_features +get_cpu_features(){ + # Return the value from list_cpu_features for the matching key + # 1: string with key pattern + + [ -z "$1" ] && log "ERROR" "get_cpu_features: missing key pattern in argument list" + cpu_features_pattern="^${1}\s*:\s*" + + if [ ! -z ${EESSI_CPU_FEATURES_FILE} ]; then + cpu_features_output=$(cat ${EESSI_CPU_FEATURES_FILE}) + else + cpu_features_output=$(list_cpu_features | sed '/^flags[[:space:]]*:/ s/,/ /g' | sed '/^flags[[:space:]]*:/ s/fma3/fma/g') # | grep flags | awk '{print $3}' | sed 's/,/ /g' | sed 's/fma3/fma/' + fi + + # case insensitive match of key pattern and delete key pattern from result + echo "${cpu_features_output}" | grep -i "$cpu_features_pattern" | tail -n 1 | sed "s/$cpu_features_pattern//i" +} + check_allinfirst(){ # Return true if all given arguments after the first are found in the first one # 1: reference string of space separated values @@ -168,26 +186,40 @@ cpupath(){ # each flag in this CPU specification must be found in the list of flags of the host check_allinfirst "${cpu_flags[*]}" ${arch_spec[2]} && best_arch_match=${arch_spec[0]} && \ all_arch_matches="$best_arch_match:$all_arch_matches" && \ - log "DEBUG" "cpupath: host CPU best match updated to $best_arch_match" + log "DEBUG" "cpupath: host CPU best match updated to $best_arch_match" fi done # Some Intel microarchitectures are flag-indistinguishable from an older one because their # new features are not exposed in /proc/cpuinfo. Granite Rapids (Xeon 6) shows the exact same # visible flags as Sapphire/Emerald Rapids (its extras like amx_fp16 are hidden by the kernel), - # so the flag match above lands on 'sapphirerapids'. Refine using the CPU model number - the - # only reliable discriminator on Linux. If no dedicated graniterapids subdir is shipped yet, - # downstream subdir resolution falls back to the next entry in the chain, so prepending is safe. + # so the flag match above lands on 'sapphirerapids'. + # Refine using the list_cpu_features tool from Google's cpu_features if available, + # and otherwise use the CPU model number. if [ "${best_arch_match}" == "x86_64/intel/sapphirerapids" ]; then local cpu_family=$(get_cpuinfo "cpu[ _]family") local cpu_model=$(get_cpuinfo "model") log "DEBUG" "cpupath: refining Sapphire Rapids match (family='$cpu_family', model='$cpu_model')" + if command -v "list_cpu_features" >/dev/null 2>&1; then + log "DEBUG" "Calling list_cpu_features tool to find all relevant CPU flags" >&2 + # cpu_features uses fma3 instead of fma, we simply replace it to ensure the matching still works + cpu_features_flags=$(get_cpu_features "$cpu_flag_tag" | sed 's/fma3/fma/') + log "DEBUG" "Flags reported by list_cpu_features: ${cpu_features_flags}" + for arch in "${cpu_arch_spec[@]}"; do + eval "arch_spec=$arch" + if [ "${cpu_vendor}x" == "${arch_spec[1]}x" ]; then + # each flag in this CPU specification must be found in the list of flags of the host + check_allinfirst "${cpu_features_flags[*]}" ${arch_spec[2]} && best_arch_match=${arch_spec[0]} && \ + all_arch_matches="$best_arch_match:$all_arch_matches" && \ + log "DEBUG" "cpupath: host CPU best match updated to $best_arch_match" + fi + done # Intel family 6 model numbers below come from the kernel's authoritative table # arch/x86/include/asm/intel-family.h (what the kernel itself uses for model dispatch): # INTEL_GRANITERAPIDS_X = IFM(6, 0xAD) -> family 6, model 173 (Granite Rapids-SP/AP) # INTEL_GRANITERAPIDS_D = IFM(6, 0xAE) -> family 6, model 174 (Granite Rapids-D) # (cf. INTEL_SAPPHIRERAPIDS_X = 0x8F/143, INTEL_EMERALDRAPIDS_X = 0xCF/207) - if [ "${cpu_family}" == "6" ] && { [ "${cpu_model}" == "173" ] || [ "${cpu_model}" == "174" ]; }; then + elif [ "${cpu_family}" == "6" ] && { [ "${cpu_model}" == "173" ] || [ "${cpu_model}" == "174" ]; }; then best_arch_match="x86_64/intel/graniterapids" all_arch_matches="$best_arch_match:$all_arch_matches" log "DEBUG" "cpupath: model $cpu_model identifies Granite Rapids; best match upgraded to $best_arch_match" From 1a30fa82989034161359a8609aaa4dd864e5fdb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bob=20Dr=C3=B6ge?= Date: Fri, 18 Sep 2026 16:57:00 +0200 Subject: [PATCH 2/3] add comment about reformatting the output of cpu_features --- init/eessi_archdetect.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/init/eessi_archdetect.sh b/init/eessi_archdetect.sh index fcb4ff10..990a4df3 100755 --- a/init/eessi_archdetect.sh +++ b/init/eessi_archdetect.sh @@ -81,6 +81,8 @@ get_cpu_features(){ if [ ! -z ${EESSI_CPU_FEATURES_FILE} ]; then cpu_features_output=$(cat ${EESSI_CPU_FEATURES_FILE}) else + # /proc/cpuinfo uses space-separated flags and uses "fma" instead of "fma3", + # so we reformat and rename things a bit here to make it easier to do the comparisons cpu_features_output=$(list_cpu_features | sed '/^flags[[:space:]]*:/ s/,/ /g' | sed '/^flags[[:space:]]*:/ s/fma3/fma/g') # | grep flags | awk '{print $3}' | sed 's/,/ /g' | sed 's/fma3/fma/' fi From 0ac6f7e403753b600d36f31f33e86dd7310c7726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bob=20Dr=C3=B6ge?= Date: Fri, 18 Sep 2026 17:00:37 +0200 Subject: [PATCH 3/3] add graniterapids --- init/arch_specs/eessi_arch_x86.spec | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/init/arch_specs/eessi_arch_x86.spec b/init/arch_specs/eessi_arch_x86.spec index ad33ec76..ea17df25 100755 --- a/init/arch_specs/eessi_arch_x86.spec +++ b/init/arch_specs/eessi_arch_x86.spec @@ -1,12 +1,13 @@ # x86_64 CPU architecture specifications # The overview at https://github.com/InstLatx64/InstLatX64_Misc/tree/main/SIMD_Euler may be helpful in defining this list # Software path in EESSI | Vendor ID | List of defining CPU features -"x86_64/intel/haswell" "GenuineIntel" "avx2 fma" # Intel Haswell, Broadwell -"x86_64/intel/skylake_avx512" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl" # Intel Skylake -"x86_64/intel/cascadelake" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl avx512_vnni" # Intel Cascade Lake -"x86_64/intel/icelake" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl avx512_vnni avx512_vbmi2" # Intel Icelake Lake -"x86_64/intel/sapphirerapids" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl avx512_bf16 amx_tile" # Intel Sapphire/Emerald Rapids -"x86_64/amd/zen2" "AuthenticAMD" "avx2 fma" # AMD Rome -"x86_64/amd/zen3" "AuthenticAMD" "avx2 fma vaes" # AMD Milan, Milan-X -"x86_64/amd/zen4" "AuthenticAMD" "avx2 fma vaes avx512f avx512ifma" # AMD Genoa, Genoa-X -"x86_64/amd/zen5" "AuthenticAMD" "avx2 fma vaes avx512f avx512ifma avx512_vp2intersect avx_vnni movdiri" # AMD Turin +"x86_64/intel/haswell" "GenuineIntel" "avx2 fma" # Intel Haswell, Broadwell +"x86_64/intel/skylake_avx512" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl" # Intel Skylake +"x86_64/intel/cascadelake" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl avx512_vnni" # Intel Cascade Lake +"x86_64/intel/icelake" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl avx512_vnni avx512_vbmi2" # Intel Icelake Lake +"x86_64/intel/sapphirerapids" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl avx512_bf16 amx_tile" # Intel Sapphire/Emerald Rapids +"x86_64/intel/graniterapids" "GenuineIntel" "avx2 fma avx512f avx512bw avx512cd avx512dq avx512vl avx512_bf16 amx_tile amx_fp16" # Granite +"x86_64/amd/zen2" "AuthenticAMD" "avx2 fma" # AMD Rome +"x86_64/amd/zen3" "AuthenticAMD" "avx2 fma vaes" # AMD Milan, Milan-X +"x86_64/amd/zen4" "AuthenticAMD" "avx2 fma vaes avx512f avx512ifma" # AMD Genoa, Genoa-X +"x86_64/amd/zen5" "AuthenticAMD" "avx2 fma vaes avx512f avx512ifma avx512_vp2intersect avx_vnni movdiri" # AMD Turin