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
if [ $ret -eq 0 ]; then # amd: 8000_0008 EBX[14]=1
pstatus green YES "SPEC_CTRL feature bit" if is_intel; then
cpuid_spec_ctrl=1 read_cpuid 0x7 $EDX 26 1 1; ret=$?
if [ $ret -eq 0 ]; then
pstatus green YES "SPEC_CTRL feature bit"
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?"
else cpuid_spec_ctrl=-1
pstatus yellow NO
fi fi
# hardware support according to kernel if is_amd; then
if [ "$opt_verbose" -ge 2 ]; then _info_nol " * CPU indicates preferring IBRS always-on: "
# the spec_ctrl flag in cpuinfo is set if and only if the kernel sees # amd
# that the spec_ctrl cpuinfo bit set. we already check that ourselves above read_cpuid 0x80000008 $EBX 16 1 1; ret=$?
# but let's check it anyway (in verbose mode only) if [ $ret -eq 0 ]; then
_verbose_nol " * Kernel has set the spec_ctrl flag in cpuinfo: " pstatus green YES
if [ "$opt_live" = 1 ]; then
if grep ^flags "$procfs/cpuinfo" | grep -qw spec_ctrl; then
pstatus blue YES
else
pstatus blue NO
fi
else else
pstatus blue N/A "not testable in offline mode" pstatus yellow NO
fi
_info_nol " * CPU indicates preferring IBRS over retpoline: "
# amd
read_cpuid 0x80000008 $EBX 18 1 1; ret=$?
if [ $ret -eq 0 ]; then
pstatus green YES
else
pstatus yellow NO
fi fi
fi fi
@ -1495,17 +1518,26 @@ 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
pstatus yellow UNKNOWN "is cpuid kernel module available?" if [ "$cpuid_spec_ctrl" = -1 ]; then
else pstatus yellow UNKNOWN "is cpuid kernel module available?"
pstatus yellow NO else
pstatus yellow NO
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 fi
# STIBP # 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 [ $ret -eq 0 ]; then if is_intel; then
pstatus green YES read_cpuid 0x7 $EDX 27 1 1; ret=$?
if [ $ret -eq 0 ]; then
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?"
else fi
pstatus yellow NO
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
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