mirror of
				https://github.com/speed47/spectre-meltdown-checker.git
				synced 2025-10-31 20:50:55 +01:00 
			
		
		
		
	Check MSR in each CPU/Thread (#136)
This commit is contained in:
		| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user