# vim: set ts=4 sw=4 sts=4 et: # Check whether the CPU is known to not perform speculative execution # Returns: 0 if the CPU is speculation-free, 1 otherwise is_cpu_specex_free() { # source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c#n882 # { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL, X86_FEATURE_ANY }, # { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL_TABLET, X86_FEATURE_ANY }, # { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_BONNELL_MID, X86_FEATURE_ANY }, # { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL_MID, X86_FEATURE_ANY }, # { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_BONNELL, X86_FEATURE_ANY }, # { X86_VENDOR_CENTAUR, 5 }, # { X86_VENDOR_INTEL, 5 }, # { X86_VENDOR_NSC, 5 }, # { X86_VENDOR_ANY, 4 }, parse_cpu_details if is_intel; then if [ "$cpu_family" = 6 ]; then if [ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_TABLET" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL_MID" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_MID" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL" ]; then return 0 fi elif [ "$cpu_family" = 5 ]; then return 0 fi fi # Centaur family 5 and NSC family 5 are also non-speculative if [ "$cpu_vendor" = "CentaurHauls" ] && [ "$cpu_family" = 5 ]; then return 0 fi if [ "$cpu_vendor" = "Geode by NSC" ] && [ "$cpu_family" = 5 ]; then return 0 fi [ "$cpu_family" = 4 ] && return 0 return 1 } # Check whether the CPU is known to be unaffected by microarchitectural data sampling (MDS) # Returns: 0 if MDS-free, 1 if affected or unknown is_cpu_mds_free() { # source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c #VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF), #VULNWL_INTEL(ATOM_GOLDMONT_X, NO_MDS | NO_L1TF), #VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF), #/* AMD Family 0xf - 0x12 */ #VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS), #VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS), #VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS), #VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS), #/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */ #VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS), #VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS), parse_cpu_details if is_intel; then if [ "$cpu_family" = 6 ]; then if [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ]; then return 0 fi fi [ "$cap_mds_no" = 1 ] && return 0 fi # official statement from AMD says none of their CPUs are affected # https://www.amd.com/en/corporate/product-security # https://www.amd.com/system/files/documents/security-whitepaper.pdf if is_amd; then return 0 elif is_hygon; then return 0 elif [ "$cpu_vendor" = CAVIUM ]; then return 0 elif [ "$cpu_vendor" = PHYTIUM ]; then return 0 elif [ "$cpu_vendor" = ARM ]; then return 0 fi return 1 } # Check whether the CPU is known to be unaffected by TSX Asynchronous Abort (TAA) # Returns: 0 if TAA-free, 1 if affected or unknown is_cpu_taa_free() { if ! is_intel; then return 0 # is intel elif [ "$cap_taa_no" = 1 ] || [ "$cap_rtm" = 0 ]; then return 0 fi return 1 } # Check whether the CPU is known to be unaffected by Special Register Buffer Data Sampling (SRBDS) # Returns: 0 if SRBDS-free, 1 if affected or unknown is_cpu_srbds_free() { # source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c # # A processor is affected by SRBDS if its Family_Model and stepping is in the # following list, with the exception of the listed processors # exporting MDS_NO while Intel TSX is available yet not enabled. The # latter class of processors are only affected when Intel TSX is enabled # by software using TSX_CTRL_MSR otherwise they are not affected. # # ============= ============ ======== # common name Family_Model Stepping # ============= ============ ======== # IvyBridge 06_3AH All (INTEL_FAM6_IVYBRIDGE) # # Haswell 06_3CH All (INTEL_FAM6_HASWELL) # Haswell_L 06_45H All (INTEL_FAM6_HASWELL_L) # Haswell_G 06_46H All (INTEL_FAM6_HASWELL_G) # # Broadwell_G 06_47H All (INTEL_FAM6_BROADWELL_G) # Broadwell 06_3DH All (INTEL_FAM6_BROADWELL) # # Skylake_L 06_4EH All (INTEL_FAM6_SKYLAKE_L) # Skylake 06_5EH All (INTEL_FAM6_SKYLAKE) # # Kabylake_L 06_8EH <=0xC (MDS_NO) (INTEL_FAM6_KABYLAKE_L) # # Kabylake 06_9EH <=0xD (MDS_NO) (INTEL_FAM6_KABYLAKE) # ============= ============ ======== parse_cpu_details if is_intel; then if [ "$cpu_family" = 6 ]; then if [ "$cpu_model" = "$INTEL_FAM6_IVYBRIDGE" ] || [ "$cpu_model" = "$INTEL_FAM6_HASWELL" ] || [ "$cpu_model" = "$INTEL_FAM6_HASWELL_L" ] || [ "$cpu_model" = "$INTEL_FAM6_HASWELL_G" ] || [ "$cpu_model" = "$INTEL_FAM6_BROADWELL_G" ] || [ "$cpu_model" = "$INTEL_FAM6_BROADWELL" ] || [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] || [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ]; then return 1 elif [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] && [ "$cpu_stepping" -le 12 ] || [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] && [ "$cpu_stepping" -le 13 ]; then if [ "$cap_mds_no" -eq 1 ] && { [ "$cap_rtm" -eq 0 ] || [ "$cap_tsx_ctrl_rtm_disable" -eq 1 ] || [ "$cap_tsx_force_abort_rtm_disable" -eq 1 ]; }; then return 0 else return 1 fi fi fi fi return 0 } # Check whether the CPU is known to be unaffected by MMIO Stale Data (CVE-2022-21123/21125/21166) # Returns: 0 if MMIO-free, 1 if affected or unknown is_cpu_mmio_free() { # source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c # # CPU affection logic from kernel (51802186158c, v5.19): # Bug is set when: cpu_matches(blacklist, MMIO) AND NOT arch_cap_mmio_immune() # arch_cap_mmio_immune() requires ALL THREE bits set: # ARCH_CAP_FBSDP_NO (bit 14) AND ARCH_CAP_PSDP_NO (bit 15) AND ARCH_CAP_SBDR_SSDP_NO (bit 13) # # Intel Family 6 model blacklist (unchanged since v5.19): # HASWELL_X (0x3F) # BROADWELL_D (0x56), BROADWELL_X (0x4F) # SKYLAKE_X (0x55), SKYLAKE_L (0x4E), SKYLAKE (0x5E) # KABYLAKE_L (0x8E), KABYLAKE (0x9E) # ICELAKE_L (0x7E), ICELAKE_D (0x6C), ICELAKE_X (0x6A) # COMETLAKE (0xA5), COMETLAKE_L (0xA6) # LAKEFIELD (0x8A) # ROCKETLAKE (0xA7) # ATOM_TREMONT (0x96), ATOM_TREMONT_D (0x86), ATOM_TREMONT_L (0x9C) # # Vendor scope: Intel only. Non-Intel CPUs are not affected. parse_cpu_details # ARCH_CAP immunity: all three bits must be set if [ "$cap_sbdr_ssdp_no" = 1 ] && [ "$cap_fbsdp_no" = 1 ] && [ "$cap_psdp_no" = 1 ]; then return 0 fi if is_intel; then if [ "$cpu_family" = 6 ]; then if [ "$cpu_model" = "$INTEL_FAM6_HASWELL_X" ] || [ "$cpu_model" = "$INTEL_FAM6_BROADWELL_D" ] || [ "$cpu_model" = "$INTEL_FAM6_BROADWELL_X" ] || [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] || [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] || [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ] || [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] || [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] || [ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] || [ "$cpu_model" = "$INTEL_FAM6_ICELAKE_D" ] || [ "$cpu_model" = "$INTEL_FAM6_ICELAKE_X" ] || [ "$cpu_model" = "$INTEL_FAM6_COMETLAKE" ] || [ "$cpu_model" = "$INTEL_FAM6_COMETLAKE_L" ] || [ "$cpu_model" = "$INTEL_FAM6_LAKEFIELD" ] || [ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_D" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_L" ]; then return 1 fi fi fi return 0 } # Check whether the CPU is known to be unaffected by Speculative Store Bypass (SSB) # Returns: 0 if SSB-free, 1 if affected or unknown is_cpu_ssb_free() { # source1: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c#n945 # source2: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/tree/arch/x86/kernel/cpu/common.c # Only list CPUs that speculate but are immune, to avoid duplication of cpus listed in is_cpu_specex_free() #{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT }, #{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, #{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_X }, #{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_MID }, #{ X86_VENDOR_INTEL, 6, INTEL_FAM6_CORE_YONAH }, #{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL }, #{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM }, #{ X86_VENDOR_AMD, 0x12, }, #{ X86_VENDOR_AMD, 0x11, }, #{ X86_VENDOR_AMD, 0x10, }, #{ X86_VENDOR_AMD, 0xf, }, parse_cpu_details if is_intel; then if [ "$cpu_family" = 6 ]; then if [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_D" ] || [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ]; then return 0 elif [ "$cpu_model" = "$INTEL_FAM6_CORE_YONAH" ] || [ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] || [ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ]; then return 0 fi fi fi if is_amd; then if [ "$cpu_family" = "18" ] || [ "$cpu_family" = "17" ] || [ "$cpu_family" = "16" ] || [ "$cpu_family" = "15" ]; then return 0 fi fi if is_hygon; then return 1 fi [ "$cpu_family" = 4 ] && return 0 return 1 }