Skip to content

Instantly share code, notes, and snippets.

@Freaky
Last active August 12, 2023 18:59
Show Gist options
  • Save Freaky/2560975d3c94246b86f464b8be75c967 to your computer and use it in GitHub Desktop.
Save Freaky/2560975d3c94246b86f464b8be75c967 to your computer and use it in GitHub Desktop.
FreeBSD Zenbleed mitigation rc script
#!/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"
@Freaky
Copy link
Author

Freaky commented Aug 12, 2023

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