By David A. Wheeler (2025-10-15)
IMPORTANT: This applies ONLY to Intel-based Macs running x86/x86_64 Linux VMs on Apple's Hypervisor Framework (HVF) with UTM and similar, not Apple Silicon (ARM) Macs.
While I use a Mac, I spend a lot of my time in Linux virtual machines. So when a Linux virtual machine isn't reliable, it matters to me. This particular bug took a while to track down and fix. I hope writing this down will help others. The Linux kernel is awesome, but its proper performance requires reliable timers. When timers don't work well, say because the virtual machine monitor (VMM) configuration doesn't provide good timers, the Linux kernel's attempts to compensate are sometimes not enough. This is a tale of one such problem and how to fix it.
If you're running Ubuntu (or another Linux distribution) in a UTM virtual machine on an Intel Mac, you may experience severe UI freezing after it works for a short while. The symptoms are:
From within the guest Ubuntu system, you can quickly diagnose this issue:
cat /sys/devices/system/clocksource/clocksource0/current_clocksource
If the output shows only acpi_pm
(ACPI Power Management timer), you have this problem. The system should be using tsc
(Time Stamp Counter) for optimal performance.
You can also check available clocksources:
cat /sys/devices/system/clocksource/clocksource0/available_clocksource
If tsc
is not listed in the available clocksources, the CPU type misconfiguration is preventing proper timer initialization.
The root cause is actually two separate but related issues with x86 virtualization on Intel Macs:
UTM's default CPU type setting prevents proper Time Stamp Counter (TSC) passthrough. TSC is an x86/x86_64 CPU feature critical for high-precision timing:
acpi_pm
clocksource (approximately 1000x slower than TSC)Even if you fix the CPU type, there's a second problem:
acpi_pm
The TSC is critical for system performance. Modern x86-64 systems expect nanosecond-level timer precision, but acpi_pm
only provides microsecond-level precision. This mismatch causes the kernel scheduler to make poor decisions, leading to the UI freezing behavior.
The drift occurs because QEMU/HVF lacks proper paravirtualization support (kvm-clock) and VM scheduling on macOS causes TSC discontinuities. However, the drift rate is small and acceptable for VM workloads - the watchdog is being overly sensitive.
Both steps are required for a permanent fix:
This enables TSC at boot time:
This prevents the watchdog from disabling TSC at runtime:
sudo nano /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT
tsc=reliable
inside the quotes. For example, change:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"to:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash tsc=reliable"
sudo update-grub
sudo reboot
After rebooting with both changes:
cat /sys/devices/system/clocksource/clocksource0/current_clocksource
You should see tsc
as the current clocksource, and it should remain tsc
even after hours of uptime. The UI freezing should be completely eliminated.
To monitor that TSC remains stable, you can check periodically:
watch -n 60 'cat /sys/devices/system/clocksource/clocksource0/current_clocksource'
It should continuously show tsc
and never revert to acpi_pm
.
If you originally allocated 8 vCPUs, consider reducing to 4 vCPUs.
The tsc=reliable
kernel parameter tells Linux to trust the TSC even if the clocksource watchdog detects drift. This is safe because:
The watchdog's strict threshold is designed for bare metal systems where TSC should be perfectly stable. In VM environments, small drift is expected and acceptable.
Without Step 1, TSC never becomes available. Without Step 2, TSC gets disabled after about half an hour. Both steps together provide a complete, permanent fix.
While HVF (Apple's Hypervisor Framework) is the recommended and fastest virtualization option for Intel Macs, QEMU/HVF has some limitations when virtualizing x86 Linux guests compared to KVM on Linux:
The kernel message "Booting paravirtualized kernel on bare hardware" reveals that the kernel expects paravirtualization support that QEMU/HVF doesn't provide. This is the fundamental limitation that requires the tsc=reliable workaround.
Apple Silicon Macs (M1/M2/M3) running ARM Linux VMs use:
The tsc=reliable
kernel parameter doesn't even exist on ARM Linux - it's specific to x86/x86_64 architecture.
This two-step fix resolves a severe usability problem with x86/x86_64 Linux VMs on UTM running on Intel-based Macs. If you're experiencing UI freezing on an Intel Mac:
The diagnosis is straightforward (check the clocksource), the cause is well-understood (TSC calibration failure and watchdog drift detection), and the solution requires two simple configuration changes. The result is stable, high-performance VM operation without UI freezing.
Note: If you're using an Apple Silicon Mac (M1/M2/M3) with ARM Linux VMs, this fix does not apply - ARM uses completely different timer hardware and virtualization technology that doesn't have this TSC-related issue.
Note 2: I found the problem and solution working with Claude Code (thanks Anthropic!). However, my first foray was a complete failure. I learned that when debugging deep problems like this, AI/ML is often intellectually lazy; it often wants to repeatedly find something that might work and propose it. I went down various useless rabbit holes. I restarted and demanded that it list all possible causes of the problem, then repeatedly analyze to disprove all other options and prove the one remaining option. Demanding airtight proof didn't immediately get the answer, but forcing it to prove its diagnosis before doing stuff was a key in getting to success.