Last active
August 12, 2023 18:59
-
-
Save Freaky/2560975d3c94246b86f464b8be75c967 to your computer and use it in GitHub Desktop.
FreeBSD Zenbleed mitigation rc script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# | |
# PROVIDE: zenbleed_workaround | |
# REQUIRE: root mountcritlocal microcode_update | |
# BEFORE: SERVERS | |
# KEYWORD: nojail resume | |
# Source: https://gist.github.com/Freaky/2560975d3c94246b86f464b8be75c967 | |
# | |
# Copyright (c) 2023 Thomas Hurst <[email protected]> | |
# License: https://opensource.org/license/mit/ | |
. /etc/rc.subr | |
name="zenbleed_workaround" | |
desc="Zenbleed MSR chicken bit workaround" | |
rcvar="zenbleed_workaround_enable" | |
extra_commands="resume" | |
start_precmd="check_zen2" | |
resume_precmd="${start_precmd}" | |
stop_precmd="${start_precmd}" | |
start_cmd="workaround_zenbleed" | |
resume_cmd="${start_cmd}" | |
stop_cmd="restore_zenbleed" | |
load_rc_config "${name}" | |
: "${zenbleed_workaround_enable:=NO}" | |
CPUCTL="/usr/sbin/cpucontrol" | |
check_zen2() { | |
if ! kldstat -q -m cpuctl; then | |
if ! kldload cpuctl > /dev/null 2>&1; then | |
warn "Can't load cpuctl module." | |
return 1 | |
fi | |
fi | |
authenticamd="0x68747541 0x444d4163 0x69746e65" | |
if ! ${CPUCTL} -i 0x0 /dev/cpuctl0 | grep -q "$authenticamd"; then | |
warn "Not an AMD processor, ignoring" | |
return 1 | |
fi | |
cpuid=$(${CPUCTL} -i 0x1 /dev/cpuctl0 | awk '{ print $4 }') | |
family=$(( ((cpuid & 0xf00) >> 8) + ((cpuid & 0x0ff00000) >> 20) )) | |
model=$(( (cpuid & 0xf0) >> 4 | (cpuid & 0x000f0000) >> 12 )) | |
# Zen 2 is Family 23 Model 49 - 160 | |
if ! { [ $family -eq 23 ] && [ $model -ge 49 ] && [ $model -le 160 ]; } then | |
warn "Not a Zen 2 processor, ignoring" | |
return 1 | |
fi | |
hmicrocode=$(${CPUCTL} -m 0x8b /dev/cpuctl0 | awk '{ print $4 }') | |
microcode=$((hmicrocode)) | |
# Numbers sourced from Linux patch: | |
# https://freshbsd.org/linux/linux/commit/0a9266b79cacdd02b888aed1308c308ad6d4ee4e | |
if [ $model -ge $((0x30)) ] && [ $model -le $((0x3f)) ] && [ $microcode -ge $((0x0830107a)) ] || | |
[ $model -ge $((0x60)) ] && [ $model -le $((0x67)) ] && [ $microcode -ge $((0x0860010b)) ] || | |
[ $model -ge $((0x68)) ] && [ $model -le $((0x6f)) ] && [ $microcode -ge $((0x08608105)) ] || | |
[ $model -ge $((0x70)) ] && [ $model -le $((0x7f)) ] && [ $microcode -ge $((0x08701032)) ] || | |
[ $model -ge $((0xa0)) ] && [ $model -le $((0xaf)) ] && [ $microcode -ge $((0x08a00008)) ]; then | |
warn "Known-good microcode detected: ${hmicrocode}, ignoring" | |
return 1 | |
fi | |
} | |
check_date() { | |
# Start whinging mid-December | |
if [ "$(/bin/date +%s)" -ge 1702684800 ]; then | |
warn "Zenbleed should be resolved by updated AMD microcode, please check." | |
warn "Updated microcode is provided by sysutils/devcpu-data" | |
fi | |
} | |
workaround_zenbleed() { | |
check_date | |
check_startmsgs && echo "Applying Zenbleed MSR workaround" | |
for D in /dev/cpuctl* | |
do | |
${CPUCTL} -m "0xc0011029|=0x200" "$D" | |
done | |
} | |
restore_zenbleed() { | |
check_startmsgs && echo "Removing Zenbleed MSR workaround" | |
for D in /dev/cpuctl* | |
do | |
${CPUCTL} -m "0xc0011029&=~0x200" "$D" | |
done | |
} | |
run_rc_command "$1" | |
I added known-good microcode checks (just EPYC "Rome" CPUs right now I believe), and a warning that appears if you use the script after mid December.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Good point. I added a
resume_precmd
.