Check MSR in each CPU/Thread

This commit is contained in:
Oleksandr Bazhaniuk 2018-02-06 11:37:02 -08:00
parent 253e180807
commit 6111de5435
1 changed files with 109 additions and 11 deletions

View File

@ -1041,6 +1041,38 @@ sys_interface_check()
return 0
}
number_of_cpus()
{
n=$(cat /proc/cpuinfo | grep processor| wc -l)
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"
@ -1048,6 +1080,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
@ -1060,10 +1095,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
@ -1108,15 +1163,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=$?
@ -1183,16 +1257,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 && $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