Skip to content

Commit b0e643d

Browse files
committed
feat(quickemu): warn on unstable TSC for macOS Ventura+ on AMD
- Add check_macos_tsc_stability() to detect unstable TSC on Linux hosts with AuthenticAMD CPUs when launching macOS Ventura+ guests - Log a clear warning to the VM log and prompt interactively to continue or abort to avoid guest freezes - Abort by default in non-interactive mode to prevent unattended VM hangs - Add --ignore-tsc-warning to bypass the check and invoke the check during vm_boot so it runs early in startup Closes #1273 Signed-off-by: Martin Wimpress <martin@wimpress.org>
1 parent 0861285 commit b0e643d

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

quickemu

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,94 @@ function ignore_msrs_alert() {
3838
fi
3939
}
4040

41+
# Check for TSC instability that can cause macOS Ventura+ to freeze on AMD Ryzen mobile CPUs.
42+
# Returns 0 if check passes or user acknowledges warning, exits with 1 if user aborts.
43+
# Reference: https://github.com/quickemu-project/quickemu/issues/1273
44+
function check_macos_tsc_stability() {
45+
# Gate 1: Only on Linux hosts
46+
if [ "${OS_KERNEL}" != "Linux" ]; then
47+
return 0
48+
fi
49+
50+
# Gate 2: Only for AMD CPUs
51+
if [ "${HOST_CPU_VENDOR}" != "AuthenticAMD" ]; then
52+
return 0
53+
fi
54+
55+
# Gate 3: Only for macOS guests
56+
if [ "${guest_os}" != "macos" ]; then
57+
return 0
58+
fi
59+
60+
# Gate 4: Only for macOS Ventura (13) and newer
61+
case ${macos_release} in
62+
ventura|sonoma|sequoia|tahoe) ;;
63+
*) return 0 ;;
64+
esac
65+
66+
# Gate 5: Skip if user has already set tsc=reliable in kernel cmdline
67+
local cmdline=""
68+
if [ -r /proc/cmdline ]; then
69+
cmdline=$(cat /proc/cmdline)
70+
if [[ "${cmdline}" == *"tsc=reliable"* ]]; then
71+
return 0
72+
fi
73+
fi
74+
75+
# Gate 6: Check if TSC is the current clocksource (indicates stable TSC)
76+
local clocksource_path="/sys/devices/system/clocksource/clocksource0/current_clocksource"
77+
local current_clocksource=""
78+
if [ -r "${clocksource_path}" ]; then
79+
current_clocksource=$(cat "${clocksource_path}")
80+
if [ "${current_clocksource}" == "tsc" ]; then
81+
return 0
82+
fi
83+
else
84+
# Cannot determine clocksource - assume OK and let user discover issues
85+
return 0
86+
fi
87+
88+
# All gates failed - this system is at risk
89+
# Check if warning should be skipped
90+
if [ "${IGNORE_TSC_WARNING}" == "1" ]; then
91+
echo " - TSC: WARNING! Unstable TSC detected (clocksource: ${current_clocksource})"
92+
echo " Proceeding anyway due to --ignore-tsc-warning flag."
93+
return 0
94+
fi
95+
96+
# Display warning and prompt user
97+
echo " - TSC: WARNING! Unstable TSC detected (clocksource: ${current_clocksource})"
98+
echo " macOS ${macos_release^} may freeze on AMD Ryzen mobile CPUs."
99+
echo
100+
echo " Fix: Add 'tsc=reliable' to kernel boot parameters and reboot."
101+
echo " Or: Use macOS Big Sur (11) or Monterey (12) instead."
102+
echo " See: https://github.com/quickemu-project/quickemu/wiki/03-Create-macOS-virtual-machines#tsc-instability-on-amd-ryzen-mobile-cpus"
103+
echo
104+
105+
# Log the warning
106+
echo "TSC_WARNING: clocksource=${current_clocksource} macos_release=${macos_release} cpu_vendor=${HOST_CPU_VENDOR}" >> "${VMDIR}/${VMNAME}.log"
107+
108+
# Interactive prompt - check if stdin is a terminal
109+
if [ -t 0 ]; then
110+
echo -n "Do you want to continue anyway? [y/N] "
111+
read -r response
112+
case "${response}" in
113+
[yY]|[yY][eE][sS])
114+
echo " - TSC: Proceeding despite unstable TSC warning."
115+
return 0
116+
;;
117+
*)
118+
echo " - TSC: Aborting. Please apply one of the solutions above."
119+
exit 1
120+
;;
121+
esac
122+
else
123+
# Non-interactive mode - abort by default for safety
124+
echo "ERROR! Non-interactive mode detected. Use --ignore-tsc-warning to bypass this check."
125+
exit 1
126+
fi
127+
}
128+
41129
function delete_shortcut() {
42130
local SHORTCUT_DIR="${HOME}/.local/share/applications"
43131
if [ -e "${SHORTCUT_DIR}/${VMNAME}.desktop" ]; then
@@ -1364,6 +1452,7 @@ function vm_boot() {
13641452

13651453
configure_cpu
13661454
configure_ram
1455+
check_macos_tsc_stability
13671456
configure_bios
13681457
configure_os_quirks
13691458
configure_storage
@@ -1848,6 +1937,7 @@ function usage() {
18481937
echo " --display : Select display backend. 'sdl' (default), 'cocoa', 'gtk', 'none', 'spice' or 'spice-app'"
18491938
echo " --fullscreen : Starts VM in full screen mode (Ctl+Alt+f to exit)"
18501939
echo " --ignore-msrs-always : Configure KVM to always ignore unhandled machine-specific registers"
1940+
echo " --ignore-tsc-warning : Skip TSC stability warning for macOS VMs on AMD"
18511941
echo " --kill : Kill the VM process if it is running"
18521942
echo " --offline : Override all network settings and start the VM offline"
18531943
echo " --shortcut : Create a desktop shortcut"
@@ -2110,6 +2200,7 @@ sound_duplex="${sound_duplex:-hda-micro}"
21102200
ACCESS=""
21112201
ACTIONS=()
21122202
BRAILLE=""
2203+
IGNORE_TSC_WARNING=""
21132204
CPU_PINNING=""
21142205
FULLSCREEN=""
21152206
MONITOR_CMD=""
@@ -2202,6 +2293,9 @@ else
22022293
-ignore-msrs-always|--ignore-msrs-always)
22032294
ignore_msrs_always
22042295
exit;;
2296+
-ignore-tsc-warning|--ignore-tsc-warning)
2297+
IGNORE_TSC_WARNING="1"
2298+
shift;;
22052299
-kill|--kill)
22062300
ACTIONS+=(kill_vm)
22072301
shift;;

0 commit comments

Comments
 (0)