Fixing random hard locks with Ryzen CPUs

Ryzen is great, and the low-end chips are ideal for home servers, but there's a compatibility issue with Linux. When the server idles, the CPU switches to the C6 power state and causes a hard lock; nothing gets logged, the server just freezes and has to be rebooted.

Fortunately, you can disable the C6 power state, and this blog post shows you how!


The AMD Ryzen 3 1200 CPU provides great performance for a low cost, and supports ECC RAM, albeit not officially advertised. These properties make it a great choice for a home server, and it allows me to run multiple services and benefit from on-the-fly data compression. I probably could do everything I do with a less powerful CPU (and the lower energy consumption would be nice), but the ~£50 price tag made the Ryzen chip very attractive.

There is, however, a very frustrating bug with the CPU when using Linux. The system will randomly hard lock, requiring a hard reboot to regain functionality. Typically these crashes happen during the night, and they leave no trace in any of the logs, making them very hard to diagnose. My initial work-around was to schedule reboots in the middle of the night; it helped, but its not ideal, and the server would still occasionally freeze.

After lots of Googling, I finally stumbled upon the problem and its solution. There's an issue with the C6 power state on Ryzen when running Linux. Switching to this power state causes a hard lock, and the solution is simply to disable the C6 power state on boot.

The commands and service file below are focused on Alpine Linux, but you can adapt them for any distro.

The Solution

Get ZenStates

ZenStates-Linux is a short Python script that uses the msr kernel module to disable the C6 state.

Since it needs to be run on every boot, its worth putting the script somewhere system-wide; I copied the script to /usr/local/bin/zenstates.py and made sure that it was executable. I also replaced the first line of the script with #!/usr/bin/env python3, but that was mostly a matter of preference.

Loading the msr module

If you want to test the zenstates.py script, you can load the msr kernel module using modprobe msr, but to make sure that it's loaded at boot, you need to add msr to /etc/modules (eg. echo msr >> /etc/modules).

Create a service

If you're using a distro with systemd instead of OpenRC, check out https://github.com/jfredrickson/disable-c6.

Alpine Linux uses OpenRC, so the following service file should be saved at /etc/init.d/zenstates:

#!/sbin/openrc-run

name="zenstates disable C6"

start() {
  /usr/local/bin/zenstates.py --c6-disable
}

You can now enable the service with rc-update add zenstates boot.

It doesn't really matter whether you make the service part of the boot or default runlevels, but it only needs to run once at boot, so I prefer to add it to that runlevel (it also has the benefit of not cluttering rc-status).

If you want to disable C6 without rebooting, you can rc-service zenstates run.