refactor: separate hw checks for Intel & AMD

This commit is contained in:
Stéphane Lesimple 2018-04-08 14:41:08 +02:00
parent 2a4bfad835
commit 51e8261a32
1 changed files with 98 additions and 41 deletions

View File

@ -754,6 +754,10 @@ load_cpuid()
fi fi
} }
# shellcheck disable=SC2034
{
EAX=1; EBX=2; ECX=3; EDX=4;
}
read_cpuid() read_cpuid()
{ {
# leaf is the value of the eax register when calling the cpuid instruction: # leaf is the value of the eax register when calling the cpuid instruction:
@ -869,7 +873,7 @@ parse_cpu_details()
fi fi
# get raw cpuid, it's always useful (referenced in the Intel doc for firmware updates for example) # get raw cpuid, it's always useful (referenced in the Intel doc for firmware updates for example)
if read_cpuid 0x1 1 0 0xFFFFFFFF; then if read_cpuid 0x1 $EAX 0 0xFFFFFFFF; then
cpuid="$read_cpuid_value" cpuid="$read_cpuid_value"
fi fi
@ -1428,30 +1432,49 @@ check_cpu()
_info_nol " * CPU indicates IBRS capability: " _info_nol " * CPU indicates IBRS capability: "
# from kernel src: { X86_FEATURE_SPEC_CTRL, CPUID_EDX,26, 0x00000007, 0 }, # from kernel src: { X86_FEATURE_SPEC_CTRL, CPUID_EDX,26, 0x00000007, 0 },
read_cpuid 0x7 4 26 1 1; ret=$? # amd: https://developer.amd.com/wp-content/resources/Architecture_Guidelines_Update_Indirect_Branch_Control.pdf
# amd: 8000_0008 EBX[14]=1
if is_intel; then
read_cpuid 0x7 $EDX 26 1 1; ret=$?
if [ $ret -eq 0 ]; then if [ $ret -eq 0 ]; then
pstatus green YES "SPEC_CTRL feature bit" pstatus green YES "SPEC_CTRL feature bit"
cpuid_spec_ctrl=1 cpuid_spec_ctrl=1
cpuid_ibrs='SPEC_CTRL'
fi
elif is_amd; then
read_cpuid 0x80000008 $EBX 14 1 1; ret=$?
if [ $ret -eq 0 ]; then
pstatus green YES "IBRS_SUPPORT feature bit"
cpuid_ibrs='IBRS_SUPPORT'
fi
else
ret=-1
pstatus yellow UNKNOWN "unknown CPU"
fi
if [ $ret -eq 1 ]; then
pstatus yellow NO
elif [ $ret -eq 2 ]; then elif [ $ret -eq 2 ]; then
pstatus yellow UNKNOWN "is cpuid kernel module available?" pstatus yellow UNKNOWN "is cpuid kernel module available?"
cpuid_spec_ctrl=-1
fi
if is_amd; then
_info_nol " * CPU indicates preferring IBRS always-on: "
# amd
read_cpuid 0x80000008 $EBX 16 1 1; ret=$?
if [ $ret -eq 0 ]; then
pstatus green YES
else else
pstatus yellow NO pstatus yellow NO
fi fi
# hardware support according to kernel _info_nol " * CPU indicates preferring IBRS over retpoline: "
if [ "$opt_verbose" -ge 2 ]; then # amd
# the spec_ctrl flag in cpuinfo is set if and only if the kernel sees read_cpuid 0x80000008 $EBX 18 1 1; ret=$?
# that the spec_ctrl cpuinfo bit set. we already check that ourselves above if [ $ret -eq 0 ]; then
# but let's check it anyway (in verbose mode only) pstatus green YES
_verbose_nol " * Kernel has set the spec_ctrl flag in cpuinfo: "
if [ "$opt_live" = 1 ]; then
if grep ^flags "$procfs/cpuinfo" | grep -qw spec_ctrl; then
pstatus blue YES
else else
pstatus blue NO pstatus yellow NO
fi
else
pstatus blue N/A "not testable in offline mode"
fi fi
fi fi
@ -1495,18 +1518,27 @@ check_cpu()
_info_nol " * CPU indicates IBPB capability: " _info_nol " * CPU indicates IBPB capability: "
# CPUID EAX=0x80000008, ECX=0x00 return EBX[12] indicates support for just IBPB. # CPUID EAX=0x80000008, ECX=0x00 return EBX[12] indicates support for just IBPB.
read_cpuid 0x80000008 2 12 1 1; ret=$? if [ "$cpuid_spec_ctrl" = 1 ]; then
if [ $ret -eq 0 ]; then # spec_ctrl implies ibpb
cpu_ibpb_supported='IBPB_SUPPORT' cpuid_ibpb='SPEC_CTRL'
pstatus green YES "IBPB_SUPPORT feature bit"
elif [ "$cpuid_spec_ctrl" = 1 ]; then
cpu_ibpb_supported='SPEC_CTRL'
pstatus green YES "SPEC_CTRL feature bit" pstatus green YES "SPEC_CTRL feature bit"
elif [ $ret -eq 2 ]; then elif is_intel; then
if [ "$cpuid_spec_ctrl" = -1 ]; then
pstatus yellow UNKNOWN "is cpuid kernel module available?" pstatus yellow UNKNOWN "is cpuid kernel module available?"
else else
pstatus yellow NO pstatus yellow NO
fi fi
elif is_amd; then
read_cpuid 0x80000008 $EBX 12 1 1; ret=$?
if [ $ret -eq 0 ]; then
cpuid_ibpb='IBPB_SUPPORT'
pstatus green YES "IBPB_SUPPORT feature bit"
elif [ $ret -eq 1 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN "is cpuid kernel module available?"
fi
fi
# STIBP # STIBP
_info " * Single Thread Indirect Branch Predictors (STIBP)" _info " * Single Thread Indirect Branch Predictors (STIBP)"
@ -1520,21 +1552,46 @@ check_cpu()
fi fi
_info_nol " * CPU indicates STIBP capability: " _info_nol " * CPU indicates STIBP capability: "
# A processor supports STIBP if it enumerates CPUID (EAX=7H,ECX=0):EDX[27] as 1 # intel: A processor supports STIBP if it enumerates CPUID (EAX=7H,ECX=0):EDX[27] as 1
read_cpuid 0x7 4 27 1 1; ret=$? # amd: 8000_0008 EBX[15]=1
if is_intel; then
read_cpuid 0x7 $EDX 27 1 1; ret=$?
if [ $ret -eq 0 ]; then if [ $ret -eq 0 ]; then
pstatus green YES pstatus green YES "Intel STIBP feature bit"
#cpuid_stibp='Intel STIBP'
fi
elif is_amd; then
read_cpuid 0x80000008 $EBX 15 1 1; ret=$?
if [ $ret -eq 0 ]; then
pstatus green YES "AMD STIBP feature bit"
#cpuid_stibp='AMD STIBP'
fi
else
ret=-1
pstatus yellow UNKNOWN "unknown CPU"
fi
if [ $ret -eq 1 ]; then
pstatus yellow NO
elif [ $ret -eq 2 ]; then elif [ $ret -eq 2 ]; then
pstatus yellow UNKNOWN "is cpuid kernel module available?" pstatus yellow UNKNOWN "is cpuid kernel module available?"
fi
if is_amd; then
_info_nol " * CPU indicates preferring STIBP always-on: "
read_cpuid 0x80000008 $EBX 17 1 1; ret=$?
if [ $ret -eq 0 ]; then
pstatus green YES
else else
pstatus yellow NO pstatus yellow NO
fi fi
fi
_info " * Enhanced IBRS (IBRS_ALL)" _info " * Enhanced IBRS (IBRS_ALL)"
_info_nol " * CPU indicates ARCH_CAPABILITIES MSR availability: " _info_nol " * CPU indicates ARCH_CAPABILITIES MSR availability: "
cpuid_arch_capabilities=-1 cpuid_arch_capabilities=-1
# A processor supports the ARCH_CAPABILITIES MSR if it enumerates CPUID (EAX=7H,ECX=0):EDX[29] as 1 # A processor supports the ARCH_CAPABILITIES MSR if it enumerates CPUID (EAX=7H,ECX=0):EDX[29] as 1
read_cpuid 0x7 4 29 1 1; ret=$? read_cpuid 0x7 $EDX 29 1 1; ret=$?
if [ $ret -eq 0 ]; then if [ $ret -eq 0 ]; then
pstatus green YES pstatus green YES
cpuid_arch_capabilities=1 cpuid_arch_capabilities=1
@ -2281,13 +2338,13 @@ check_variant2_linux()
_explain_hypervisor="An updated CPU microcode will have IBRS/IBPB capabilities indicated in the Hardware Check section above. If you're running under an hypervisor (KVM, Xen, VirtualBox, VMware, ...), the hypervisor needs to be up to date to be able to export the new host CPU flags to the guest. You can run this script on the host to check if the host CPU is IBRS/IBPB. If it is, and it doesn't show up in the guest, upgrade the hypervisor." _explain_hypervisor="An updated CPU microcode will have IBRS/IBPB capabilities indicated in the Hardware Check section above. If you're running under an hypervisor (KVM, Xen, VirtualBox, VMware, ...), the hypervisor needs to be up to date to be able to export the new host CPU flags to the guest. You can run this script on the host to check if the host CPU is IBRS/IBPB. If it is, and it doesn't show up in the guest, upgrade the hypervisor."
# IBPB (amd & intel) # IBPB (amd & intel)
if [ "$ibpb_enabled" = 0 ] && ( is_intel || is_amd ); then if [ "$ibpb_enabled" = 0 ] && ( is_intel || is_amd ); then
if [ -z "$cpu_ibpb_supported" ]; then if [ -z "$cpuid_ibpb" ]; then
explain "The microcode of your CPU needs to be upgraded to be able to use IBPB. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section). $_explain_hypervisor" explain "The microcode of your CPU needs to be upgraded to be able to use IBPB. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section). $_explain_hypervisor"
fi fi
if [ -z "$ibpb_supported" ]; then if [ -z "$ibpb_supported" ]; then
explain "Your kernel doesn't have IBPB support, so you need to either upgrade your kernel (if you're using a distro) or recompiling a more recent kernel." explain "Your kernel doesn't have IBPB support, so you need to either upgrade your kernel (if you're using a distro) or recompiling a more recent kernel."
fi fi
if [ -n "$cpu_ibpb_supported" ] && [ -n "$ibpb_supported" ]; then if [ -n "$cpuid_ibpb" ] && [ -n "$ibpb_supported" ]; then
if [ -e "$specex_knob_dir/ibpb_enabled" ]; then if [ -e "$specex_knob_dir/ibpb_enabled" ]; then
explain "Both your CPU and your kernel have IBPB support, but it is currently disabled. You may enable it with \`echo 1 > $specex_knob_dir/ibpb_enabled\`." explain "Both your CPU and your kernel have IBPB support, but it is currently disabled. You may enable it with \`echo 1 > $specex_knob_dir/ibpb_enabled\`."
else else
@ -2299,13 +2356,13 @@ check_variant2_linux()
# IBRS (intel only) # IBRS (intel only)
if [ "$ibrs_enabled" = 0 ] && is_intel; then if [ "$ibrs_enabled" = 0 ] && is_intel; then
if [ "$cpuid_spec_ctrl" != 1 ]; then if [ -n "$cpuid_ibrs" ]; then
explain "The microcode of your CPU needs to be upgraded to be able to use IBRS. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section). $_explain_hypervisor" explain "The microcode of your CPU needs to be upgraded to be able to use IBRS. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section). $_explain_hypervisor"
fi fi
if [ -z "$ibrs_supported" ]; then if [ -z "$ibrs_supported" ]; then
explain "Your kernel doesn't have IBRS support, so you need to either upgrade your kernel (if you're using a distro) or recompiling a more recent kernel." explain "Your kernel doesn't have IBRS support, so you need to either upgrade your kernel (if you're using a distro) or recompiling a more recent kernel."
fi fi
if [ "$cpuid_spec_ctrl" = 1 ] && [ -n "$ibrs_supported" ]; then if [ -n "$cpuid_ibrs" ] && [ -n "$ibrs_supported" ]; then
if [ -e "$specex_knob_dir/ibrs_enabled" ]; then if [ -e "$specex_knob_dir/ibrs_enabled" ]; then
explain "Both your CPU and your kernel have IBRS support, but it is currently disabled. You may enable it with \`echo 1 > $specex_knob_dir/ibrs_enabled\`." explain "Both your CPU and your kernel have IBRS support, but it is currently disabled. You may enable it with \`echo 1 > $specex_knob_dir/ibrs_enabled\`."
else else