Here are some (possibly) useful tweaks for SteamOS on the Steam Deck

My collection of Linux-related modifications which are easy to add/remove via copy & paste

A.B.T.
14 min readSep 16, 2023

--

LEGAL DISCLAIMER

By using any of the commands listed below, you acknowledge and accept that neither I nor the Valve Corporation are responsible for any damage that may occur to you personally or your Steam Deck.

The burden of full responsibility for your own actions lies entirely upon you, only.

Personal Usage Note

Although all of the commands listed below are provided on an “as-is” basis without any guarentees whatsoever, I can honestly state that I am making use of all of the following modifications listed below on my personal
Steam Deck.

This verified testing on my behalf was done upto and including the latest SteamOS 3.5 release at the time of writing.

TL;DR

  1. WARNING: This will permanently apply all of my changes at once;
    if in doubt, read down below for details!
    In order to remove all of these changes and revert back to SteamOS’ defaults, I’ve provided the necessary set of commands as part of this TL;DR block, as well.
  2. Switch over to the SteamOS desktop mode by clicking the lower left button on your Steam Deck labelled STEAM and navigating to the On/Off menu point where you will find the corresponding option, then open up the terminal application called Konsole (findable by clicking the icon in the lower left corner and then looking inside the System menu tab) and create a password via the passwd command if you haven’t already. (Best practice is to not use the same password twice, in other words don’t use your password for logging into Steam itself here!)
  3. Copy & paste the following block into the same terminal window as a whole (i.e. not line-by-line) & hit the enter key; when asked about your password, type in the one you created via the passwd command (i.e. not your password for your Steam account itself):
cat << EOF | sudo tee /etc/systemd/system/cpu_performance.service
[Unit]
Description=CPU performance governor
[Service]
Type=oneshot
ExecStart=/usr/bin/cpupower frequency-set -g performance
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable cpu_performance.service
cat << EOF | sudo tee /etc/tmpfiles.d/mglru.conf
w /sys/kernel/mm/lru_gen/enabled - - - - 7
w /sys/kernel/mm/lru_gen/min_ttl_ms - - - - 0
EOF
cat << EOF | sudo tee /etc/security/limits.d/memlock.conf
* hard memlock 2147484
* soft memlock 2147484
EOF
cat << EOF | sudo tee /etc/udev/rules.d/64-ioschedulers.rules
ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/scheduler}="kyber"
ACTION=="add|change", KERNEL=="sd[a-z]|mmcblk[0-9]*", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="kyber"
EOF
sudo sed -i -e '/home/s/\bdefaults\b/&,noatime/' /etc/fstab
sudo sed -i 's/\bGRUB_CMDLINE_LINUX_DEFAULT="\b/&mitigations=off nowatchdog nmi_watchdog=0 /' /etc/default/grub
sudo grub-mkconfig -o /boot/efi/EFI/steamos/grub.cfg

Wait until you see the word done in the terminal output and then just
reboot/restart SteamOS in order for the above changes to take effect.

4. PROFIT ?!

Optional:

To undo/revert all of the above changes at once, copy & paste the following block as a whole:

sudo systemctl disable cpu_performance.service
sudo rm /etc/tmpfiles.d/mglru.conf
sudo rm /etc/security/limits.d/memlock.conf
sudo rm /etc/udev/rules.d/64-ioschedulers.rules
sudo sed -i -e 's/,noatime//' /etc/fstab
sudo sed -i -e 's/mitigations=off nowatchdog nmi_watchdog=0 //' /etc/default/grub
sudo grub-mkconfig -o /boot/efi/EFI/steamos/grub.cfg

Preface

At least some of the people who are fortunate enough to own Valve’s
Steam Deck may have heard that the operating system powering this neat handheld PC is a Linux-based one, fittingly called SteamOS.

And unlike traditional gaming consoles, Valve stayed true to the open spirit of Linux, meaning that they didn’t lock-down their own device, thankfully.

The open nature of the Steam Deck allows anyone to change many parameters of the underlying Linux kernel and its surrounding software, which are the foundational building blocks of SteamOS.

For many years now I’ve modified countless Linux installations of my own, therefore I didn’t want to make an exception here.

I originally intended to write this article in order to collect all of the tuning I personally make to my SteamOS setup, neatly organized in one place.

Soon, I realized that perhaps other users of this nifty Linux distribution might be interested in replicating at least some of these on their end, too.

Thus, I decided to present my tweaks in such a way that makes replicating them as easy as simply copy & pasting whole commands into a console terminal application on the SteamOS desktop.

Additionally, I will also state the exact command needed in order to remove/undo any given alteration to the operating system.

Every single one of the following tweaks can be mixed & matched to your heart’s content, because none of them depend on each other; feel free to only try out those you are feeling comfortable with.

Also, any modification will only take effect after a reboot/restart of the
operating system.

Note that I haven’t conducted any “before & after” benchmarks myself, however should anyone out there feel inclined to do so themselves,
then please don’t hesitate to share your results in a comment below.

And just to reiterate, I won’t be held responsible for any damage that might occur due to the following commands, but you already know that.

So, without further ado, let’s get to it, shall we?

Prerequisites

In order to follow along, it would be advisable to attach a keyboard & mouse to the Steam Deck, since it makes copy-pasting the commands
easy and swift.

There are a variety of ways to accomplish this, but the quickest way is to simply pair a Bluetooth-enabled keyboard & mouse to the Steam Deck.

Alternatively, if you happen to have a USB-C dongle, then attaching a keyboard & mouse via USB-cables is also an option.

Should none of the above possiblities be available to you, then using the touchscreen in combination with the on-screen keyboard should still be feasible as a final resort, albeit a somewhat cumbersome one.

Desktop mode & terminal launch

We will do all of the work from a single CLI (Command-Line Interface) terminal window only, into which the commands will be pasted as a whole.

To be able to launch said terminal software, we first have to switch over to the desktop mode of SteamOS:

To do so, open up the Steam menu by pressing the physical STEAM button located towards the lower left of the Steam Deck.

This should bring up a menu on the left.

Navigate to the On/Off option at the bottom and select it with the A button.

In the following window, select the “Switch to Desktop” entry.

Once SteamOS’ desktop has launched, simply navigate the mouse cursor towards the bottom left corner of the screen and click on the icon located there to bring up the start menu.

Type Konsole into the search field and launch the aptly named terminal application.

Congratulations, you’re all set & ready to go!

First things first (as in: setting your own password)

For any of the following commands to work, we are going to need a password, which isn’t set by default for any new user of SteamOS.

Fortunately for us, creating a new password (which you definitely will park into your long-term memory, right?) is super simple.

Just type the following word into the freshly opened terminal window
(no, this is not a typo):

passwd

It will ask you to type in your new password twice.

And remember, please remember to remember this very password-y word of yours, okay?

With this out of the way, finally, let the tweaking begin!

Switching over to the “performance” CPU governor at start-up

Unfortunately, even the newest (at the time of writing) SteamOS 3.5 release still ships with a CPU governor called schedutil, which is less than desirable if you want a rather even & consistent frame-pacing, because of the erratic downclocking behavior it has become famous for in Linux enthusiast circles.

On the other hand, the performance governor does exactly what it says on the tin:

It always requests the highest performance state of the CPU that is available, thus either preventing or at the very least reducing many of the dreaded frame-time spikes plaguing the schedutil governor.

Now, I already know what you are thinking right now because I can actually read your mind over the internet:

But what about my temperatures — is it going to melt my Steam Deck ???

The short answer is: No, it won’t!

The slighty longer answer:

All modern CPUs (including the Steam Deck’s AMD Zen 2 architecture) have so-called “sleep states”, which allow the CPU to almost completely power-off certain parts of individual cores at any given opportunity, which ensures they save the most amount of energy & heat, way more so than what the simplistic downclocking strategy could ever hope to achieve.

So, what are you waiting for?
Go ahead and copy-paste the following code block as a whole (in other words, not line-by-line) and hit enter:

cat << EOF | sudo tee /etc/systemd/system/cpu_performance.service
[Unit]
Description=CPU performance governor
[Service]
Type=oneshot
ExecStart=/usr/bin/cpupower frequency-set -g performance
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable cpu_performance.service

To undo/revert this change:

sudo systemctl disable cpu_performance.service

MGLRU (Multi-Gen. Least Recently Used)

This is one of the most recent additions to the upstream Linux kernel, literally just merged for the 6.1 LTS (Long-Term Support) version which the SteamOS 3.5 release switched towards over the 5.13 kernel used previously.

It is a feature developed by a Google engineer to dramatically improve upon the memory management of Linux, and is already in use on both Android & ChromeOS.

However, the upstream kernel doesn’t enable this functionality by default, yet.

That is why we are going to take matters into our own hands and simply activate MGLRU with the following block:

cat << EOF | sudo tee /etc/tmpfiles.d/mglru.conf
w /sys/kernel/mm/lru_gen/enabled - - - - 7
w /sys/kernel/mm/lru_gen/min_ttl_ms - - - - 0
EOF

To undo/revert this change:

sudo rm /etc/tmpfiles.d/mglru.conf

Silencing the Watchdog

A watchdog timer in computer terminology is either a piece of hardware or software which can be used for both detection & recovery of malfunctions.

These are critical components for enterprise devices in order to ensure that they meet high-availability demands, however the Steam Deck is none of that.

Therefore, disabling the watchdog timers has no ill-effects;
to the contrary, it can actually help the Steam Deck by not generating any interrupt requests of its own.

To permanently disable the watchdog timers, simply copy & paste the following block as a whole (not line-by-line):

sudo sed -i 's/\bGRUB_CMDLINE_LINUX_DEFAULT="\b/&nowatchdog nmi_watchdog=0 /' /etc/default/grub
sudo grub-mkconfig -o /boot/efi/EFI/steamos/grub.cfg

To undo/revert this change:

sudo sed -i -e 's/nowatchdog nmi_watchdog=0 //' /etc/default/grub
sudo grub-mkconfig -o /boot/efi/EFI/steamos/grub.cfg

Unlocking the memory lock

This is an optimization which will especially help RPCS3, which is an emulator for Sony’s PlayStation 3 console.

In fact, when you run RPCS3 from a terminal on Linux, it will complain with the following message:

Warning message:
Failed to set RLIMIT_MEMLOCK size to 2 GiB. Try to update your system configuration.

By default, the Linux kernel sets this particular value to just 64KiB, which is the maximum amount of memory the kernel will lock within a single operation, and the following is what one of the main developers of RPCS3 had to say on the topic:

64K is some outdated over-precautious limitation from 1990’s era.

Well, okay then, let’s increase our limit to 2GiB in order to advance into the 2020’s era:

cat << EOF | sudo tee /etc/security/limits.d/memlock.conf
* hard memlock 2147484
* soft memlock 2147484
EOF

To undo/revert this change:

sudo rm /etc/security/limits.d/memlock.conf

Changing the I/O (Input/Output) Scheduler

An I/O-scheduler tries to efficiently balance both read & write performance as well as the latency of access times to block devices such as a NVMe SSD, eMMC storage or even a microSD card.

SteamOS has three different I/O-schedulers to choose from.
[Technically, there’s also the option of having no I/O-scheduler at all.]

By default, it uses mq-deadline, which is a port of the older deadline scheduler from a time when the block subsystem of the Linux kernel only had a single queue to work with, towards the more efficient multi-queue design of contemporary Linux.

The other two remaining options are called bfq & kyber:

BFQ has a strict focus on providing low-latency I/O-operations even under heavy loads; however, that achievement comes at the cost of reduced throughput performance, in particular when it comes to write speeds.

Kyber on the other hand was developed by Facebook for use on their
high-end storage servers. Therefore, it has a rather simple design that is light on the strain it puts on the CPU.

In practice, I found Kyber to be the best all-rounder among the three, since it allows the diverse storage devices to both reach the maximum capacity of their respective throughput (i.e. read & write) speeds while at the same time still providing low enough latencies even among high I/O pressure.

That is why we are going to permanently swap the I/O-scheduler to Kyber with the following block (note that this will work with all cases, meaning NVMe SSD, eMMC & microSD):

cat << EOF | sudo tee /etc/udev/rules.d/64-ioschedulers.rules
ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/scheduler}="kyber"
ACTION=="add|change", KERNEL=="sd[a-z]|mmcblk[0-9]*", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="kyber"
EOF

To undo/revert this change:

sudo rm /etc/udev/rules.d/64-ioschedulers.rules

Preventing the superfluous book-keeping of File Access Times

A long time ago, the Linux kernel would update the access time of every file everytime it would work with it, meaning that even a read-only operation would immediately result in a write operation, because the access time of the file in question had to be updated.

Fortunately, that was in large part fixed by the relatime (relative access time) option, which ensures that the access time of any file is only updated once every 24 hours.

However, I say “in large part fixed” precisely because any time a new file is either created or after 24 hours have passed, a read-only operation on any file will still result in a corresponding write operation, too.

Now you’re maybe asking yourself:

How costly can such a write operation be, anyway?

I was in the same boat until I saw these benchmarks the excellent Phoronix website run by Michael Larabel did, where he compared the performance of Ubuntu 20.04 LTS versus Pop!_OS 20.04, which is actually a derivative of Ubuntu, as the same numbering convention implies.

Nevertheless, there’s a noticeable performance advantage of Pop!_OS when looking at the I/O throughput benchmarks.

The key differentiator between both operating systems is the use of the noatime flag by Pop!_OS, which ensures that the Linux kernel will simply cease to write any file access times at all.

And no, not keeping track of file access times won’t cause any issues;
to the contrary, it will actually help in extending the lifetime of your storage devices, since it will cut-down on the wear & tear write operations cause on flash-based storage mediums.

Therefore, let’s permanently switch over to the noatime setting with the following command:

sudo sed -i -e '/home/s/\bdefaults\b/&,noatime/' /etc/fstab

To undo/revert this change:

sudo sed -i -e 's/,noatime//' /etc/fstab

Disabling CPU security flaw mitigations

(a.k.a. Here Be Dragons!)

Let me start by explicitly stating that the change described in this segment has the hypothetical potential of becoming a security risk for SteamOS,
so caveat emptor!

Having said that, I am limiting my personal risk exposure by only disabling the CPU mitigations when my Steam Deck is in offline mode.

This has the added benefit of preserving battery life, because an active WLAN/WiFi connection requires energy to operate, obviously.

And since I exclusively play offline single-player games which don’t require an active Internet connection anyway, disabling the costly CPU mitigations is viable for me personally.

Now, disabling the security flaw mitigations can boost the performance of SteamOS quite a bit on Steam Deck’s AMD Zen 2 CPU architecture, especially with the most recent hardware bug named Retbleed.

For a good demonstration of the current penalty and the potential performance uplift by deactivating the mitigations on Zen 2 CPUs, I can once again point you towards this benchmark done by Phoronix.

Thus, if you personally are comfortable with running an operating system with a known security risk that theoretically could be exploited, then the following command will have you covered:

sudo sed -i 's/\bGRUB_CMDLINE_LINUX_DEFAULT="\b/&mitigations=off /' /etc/default/grub
sudo grub-mkconfig -o /boot/efi/EFI/steamos/grub.cfg

To undo/revert this change:

sudo sed -i -e 's/mitigations=off //' /etc/default/grub
sudo grub-mkconfig -o /boot/efi/EFI/steamos/grub.cfg

An observation about CryoByte33’s steam-deck-utilities script

First of all, I want to start this segment by saying that I appreciate the work CryoByte33 has poured into the creation & promotion of his script for the Steam Deck.

And yes, that script is fully compatible with all of my above tweaks, since I don’t touch upon any of the values he is modifying.

However, there is just one suggestion I would like to make:

By default, his utility will set the value related to the activation of THP (Transparent HugePages) to always, meaning that they are unconditionally used for memory management by the Linux kernel.

This is a deviation from the default value unironically named madvise set by both the upstream Linux kernel developers and Valve, which boils down to meaning that THPs are only being used if explicitly requested by an
user-space application such as Proton.

In fact, at one point in its history the Linux kernel did enable THP by default, only to retreat from that position later on since it became apparent that it could cause both a massive increase in memory usage (a.k.a. RAM consumption) & huge latency-spikes (as in the system becoming totally unresponsive for a certain period of time).

Now there are of course possible performance benefits in making use of THP, which the madvise kernel option still explicitly allows, mind you, with the only barrier to entrance being that any user-space software has to explicitly opt-in for it.

This is why I’d like to humbly request from CryoByte33 to make the setting of THP a user-facing choice instead of forcing that feature to be always activated by default, in order to both raise awareness about the potential pitfalls of THP and giving the users of his utility an easy way to change back to the default value set by Valve.

Also, please note that Valve must have deliberately set the value for THP to madvise, because the Arch Linux kernel (which their downstream kernel is based upon) actually sets the value related to the use of THP to always as well, which most likely means that Valve’s internal testing of the Steam Deck probably exhibited problems with that particular option, so they went out of their way to restore the value back to the upstream default.

A humble request for VALVe

As far as I can tell, you guys are using the same 300 Hz kernel tick the standard Arch Linux kernel is using by default, too.

Should the above assumption still be true, then I’d humbly request that you folks consider switching over to the 1000 Hz kernel tick option the upstream kernel offers at build time.

Here is what Linux’s official documentation has to say about it:

1000 Hz is the preferred choice for desktop systems and other systems requiring fast interactive responses to events.

Please also consider that Ubuntu’s so-called “lowlatency” kernel flavor and Google’s Linux configuration on both Android & ChromeOS is defaulting to the 1000 Hz tick option, as well.

From my own experience, gaming on Linux feels the smoothest when using a 1000 Hz kernel.

Therefore, I’d strongly suggest seriously evaluating the jump over to the 1000 Hz configuration option at build time on your end.

Thanks in advance & please keep up the amazing work for the greater good of Linux!

Closing Words

I really hope my collection of tweaks I personally apply to my Steam Deck prove to be useful for you, too.

In any case, please feel free to share your experience should you be inclined to apply these to your own SteamOS setup as well, in order to let me know whether any of the above tweaks are having any impact at all! ;-)

Sincerely,

A. B. T.

--

--