Check MSR in each CPU/Thread (#136)

This commit is contained in:
Alex 2018-03-17 09:17:15 -07:00 committed by Stéphane Lesimple
parent 12ea49fe0c
commit ecdc448531
1 changed files with 109 additions and 11 deletions

View File

@ -1059,6 +1059,38 @@ sys_interface_check()
return 0
}
number_of_cpus()
{
n=$(grep -c ^processor /proc/cpuinfo)
return "$n"
}
# $1 - msr number
# $2 - cpu index
check_msr_enable()
{
dd if=/dev/cpu/"$2"/msr of=/dev/null bs=8 count=1 skip="$1" iflag=skip_bytes 2>/dev/null; ret=$?
return $ret
}
# $1 - msr number
# $2 - cpu index
# $3 - value
write_to_msr()
{
$echo_cmd -ne "$3" | dd of=/dev/cpu/"$2"/msr bs=8 count=1 seek="$1" oflag=seek_bytes 2>/dev/null; ret=$?
return $ret
}
# $1 - msr number
# $2 - cpu index
read_msr()
{
msr=$(dd if=/dev/cpu/"$2"/msr bs=8 count=1 skip="$1" iflag=skip_bytes 2>/dev/null | od -t u1 -A n | awk '{print $8}');
return "$msr"
}
check_cpu()
{
_info "\033[1;34mHardware check\033[0m"
@ -1066,6 +1098,9 @@ check_cpu()
_info "* Hardware support (CPU microcode) for mitigation techniques"
_info " * Indirect Branch Restricted Speculation (IBRS)"
_info_nol " * SPEC_CTRL MSR is available: "
number_of_cpus
ncpus=$?
idx_max_cpu=$((ncpus-1))
if [ ! -e /dev/cpu/0/msr ]; then
# try to load the module ourselves (and remember it so we can rmmod it afterwards)
load_msr
@ -1078,10 +1113,30 @@ check_cpu()
# here we use dd, it's the same as using 'rdmsr 0x48' but without needing the rdmsr tool
# if we get a read error, the MSR is not there. bs has to be 8 for msr
# skip=9 because 8*9=72=0x48
dd if=/dev/cpu/0/msr of=/dev/null bs=8 count=1 skip=9 2>/dev/null; ret=$?
if [ $ret -eq 0 ]; then
spec_ctrl_msr=1
pstatus green YES
val=0
cpu_mismatch=0
for i in $(seq 0 "$idx_max_cpu")
do
check_msr_enable 72 "$i"
ret=$?
if [ "$i" -eq 0 ]; then
val=$ret
else
if [ "$ret" -eq $val ]; then
continue
else
cpu_mismatch=1
fi
fi
done
if [ $val -eq 0 ]; then
if [ $cpu_mismatch -eq 0 ]; then
spec_ctrl_msr=1
pstatus green YES
else
spec_ctrl_msr=1
pstatus green YES "But not in all CPUs"
fi
else
spec_ctrl_msr=0
pstatus red NO
@ -1126,15 +1181,34 @@ check_cpu()
# the new MSR 'PRED_CTRL' is at offset 0x49, write-only
# here we use dd, it's the same as using 'wrmsr 0x49 0' but without needing the wrmsr tool
# if we get a write error, the MSR is not there
$echo_cmd -ne "\0\0\0\0\0\0\0\0" | dd of=/dev/cpu/0/msr bs=8 count=1 seek=73 oflag=seek_bytes 2>/dev/null; ret=$?
if [ $ret -eq 0 ]; then
pstatus green YES
val=0
cpu_mismatch=0
for i in $(seq 0 "$idx_max_cpu")
do
write_to_msr 73 "$i" "\0\0\0\0\0\0\0\0"
ret=$?
if [ "$i" -eq 0 ]; then
val=$ret
else
if [ "$ret" -eq $val ]; then
continue
else
cpu_mismatch=1
fi
fi
done
if [ $val -eq 0 ]; then
if [ $cpu_mismatch -eq 0 ]; then
pstatus green YES
else
pstatus green YES "But not in all CPUs"
fi
else
pstatus red NO
fi
fi
_info_nol " * CPU indicates IBPB capability: "
# CPUID EAX=0x80000008, ECX=0x00 return EBX[12] indicates support for just IBPB.
read_cpuid 2147483656 5 16; ret=$?
@ -1201,16 +1275,40 @@ check_cpu()
# the new MSR 'ARCH_CAPABILITIES' is at offset 0x10a
# here we use dd, it's the same as using 'rdmsr 0x10a' but without needing the rdmsr tool
# if we get a read error, the MSR is not there. bs has to be 8 for msr
capabilities=$(dd if=/dev/cpu/0/msr bs=8 count=1 skip=266 iflag=skip_bytes 2>/dev/null | od -t u1 -A n | awk '{print $8}'); ret=$?
val=0
val_cap_msr=0
cpu_mismatch=0
for i in $(seq 0 "$idx_max_cpu")
do
check_msr_enable 266 "$i"
ret=$?
read_msr 266 "$i"
capabilities=$?
if [ "$i" -eq 0 ]; then
val=$ret
val_cap_msr=$capabilities
else
if [ "$ret" -eq "$val" -a "$capabilities" -eq "$val_cap_msr" ]; then
continue
else
cpu_mismatch=1
fi
fi
done
capabilities=$val_cap_msr
capabilities_rdcl_no=0
capabilities_ibrs_all=0
if [ $ret -eq 0 ]; then
if [ $val -eq 0 ]; then
_debug "capabilities MSR lower byte is $capabilities (decimal)"
[ $(( capabilities & 1 )) -eq 1 ] && capabilities_rdcl_no=1
[ $(( capabilities & 2 )) -eq 2 ] && capabilities_ibrs_all=1
_debug "capabilities says rdcl_no=$capabilities_rdcl_no ibrs_all=$capabilities_ibrs_all"
if [ "$capabilities_ibrs_all" = 1 ]; then
pstatus green YES
if [ $cpu_mismatch -eq 0 ]; then
pstatus green YES
else:
pstatus green YES "But not in all CPUs"
fi
else
pstatus red NO
fi