Adventures with the Thinkpad T440p, dGPU and Coreboot in "Mid 2022"
This is my documentation about the process of flashing and tweaking coreboot to run properly on my T440p with a dedicated NVIDIA GPU, colloquially known as a ‘dGPU’. There are multiple guides that will teach you how to build, flash, or build and flash coreboot on a T440p without issue. However, if you have a T440p with a dGPU, you will quickly realize that the GPU is mysteriously absent from your PCI device list. Information about why or how to enable this is scattered and often dated, so I’ve created this page to dump it all to. Hopefully other people who are in the same position can make use of it. This is assuming you are installing a GNU/Linux distro on your machine; I can’t speak to any of this working with Windows.
tl;dr - You’re already familiar with coreboot but just want dGPU support
The current coreboot code for the T440p has the PCI Express Graphics (PEG) device that handles the dGPU disabled. Thanks to nullenvk, you can restore dGPU functions by applying this commit, which adds the “Enable dedicated graphics (experimental)” option to nconfig. Enabling this will re-enable the PEG device in your next coreboot build. You need to include the VBIOS for both the iGPU and dGPU. You can extract both using VBiosFinder. If you’re building coreboot from master branch, the current SeaBIOS payload will result in a bootloop. Use SeaBIOS 1.15 or TianoCore (UEFI OS only).
The Long Version
Intro
The Thinkpad T440p is a 14" laptop released in November 2013 by Lenovo. They’re tough, upgradable and plentiful on the used market. There are multiple writeups espousing their virtues and limitations.
Back in December I managed to get a good deal on a second hand T440p. The listing was sparse and mostly listed the 4GB RAM and 4-core low power i5 CPU, but I could source upgrades for both. I got it home to find out it also had a locked BIOS and an NVIDIA dedicated GPU. I wasn’t counting on either of these but thankfully there neither would be a problem. As of November 2019, The T440p supports Coreboot, an open source firmware platform. There are multiple good guides that step through how to build (or give you an already built) coreboot and flash the whole thing for the first time. However, information on getting a dGPU working is scattered and outdated. It seems that, even when coreboot users have the dGPU on-board, they typically opt not to use it. The dGPU adds a lot of battery drain and heat to keep under control. The heatsink and fan on this unit handle both the CPU and GPU, and if one was focussing on CPU performance thanks to an upgrade, they would likely want to avoid the heat contest with the dGPU. To make matters more confusing, if one recently followed the instructions to manually build coreboot for themselves and chose to use the current SeaBIOS (1.16) payload, they’d get a bootloop.
Given that the dGPU is much higher power draw for questionable performance gains, it might seem somewhat redundant to try and get it going. However in my testing I’ve found the GT 730M to play older games at reasonable (720p) framerates. Additionally, the GT 730M has ‘complete’ Vulkan support, while the HD 4600 warns that the implementation is incomplete; the only example I have is that the iGPU cannot run Half-Life 2 via Proton/DXVK, but has no problem with the ToGL ‘native’ Linux port. The dGPU can do either, which opens up the possibility of running older or lower spec Windows games on the machine.
Building Coreboot with dGPU Support
Here’s the stuff that helped me the most:
- Skulls Pre-built Coreboot Images for T440p - Follow this guide to get a working, albeit slightly outdated coreboot install with a SeaBIOS 1.15 payload. Requires the least amount of steps for a working install imo.
- Conor Burns Excellent T440p Coreboot Flashing Guide - Following this will get you a working coreboot install with a Tianocore payload, which only supports booting UEFI OSes, however this guide takes you through manually building and flashing coreboot yourself, is fairly recent, and comes with a good base set of config parameters. Highly recommended.
These are both excellent, but unfortunately neither will yield a coreboot install with dedicated GPU support, since in coreboot itself the PCIe device that handles the dGPU is disabled by default. This helps iGPU only units, but is crucial for dGPU units to access the dGPU. Thanks to nullenvk figuring this out, there is a commit that will add the option to re-enable this PEG device in the coreboot configuration. You can apply this as a patch to a local copy of the coreboot repo. The whole process looks something like this:
git clone https://github.com/coreboot/coreboot
cd coreboot
curl https://github.com/nullenvk/coreboot/commit/aef930dcb6089ef21f00820b2af93654138e1f83.patch | git apply -v
This will patch some files in the t440p section of the coreboot source, and then when running make nconfig, you will have the extra dGPU toggle. Thanks nullenvk!
Here’s a summary of my steps:
- Followed Conor’s guide, up to Configuration section, but used the coreboot master branch instead of the suggested branch and did not downgrade gcc.
- Applied nullenvk’s changes as a patch to local coreboot repo - see above
- Extracted both VBIOS blobs from the t440p-original.rom made during the guide using VBiosFinder
- Continued Conor’s guide. During make nconfig, enabled dedicated graphics and added both VBIOS files.
- Draw the rest of the fucking owl (build coreboot)
At this point you can either split it as per the guide and do the first ever flash, or (in my case, since I already had a skulls image installed) flash coreboot from the OS… and Voila! The dGPU is… still not listed in lscpi or dmesg. The last step you will need to do is build nvramtool and use it to enable the “Dual Graphics” feature. Then after a reboot, you should have a working dGPU using the nouveau driver. Now you can enjoy the pain of configuring the nvidia proprietary driver alongside i915/mesa and getting it to meaningfully work and switch on your whim. Have fun! I put some of that down below if you’re still looking to punish yourself a little.
Optimus PRIME
You are now working with an NVIDIA Optimus environment, the name for their hybrid graphics solution that puts the dGPU behind the iGPU and creates all kinds of cursed power consumption, tearing, sync, Wayland/X11 issues, etc. This is a hardware-level implementation, so you unfortunately can’t magic it away with FOSS. You are spoilt for many (unsatisfactory) choices when picking a way of handling this. Here’s the Arch Wiki page that covers most of the options.
FWIW I use EnvyControl. This tool will let you switch between pure iGPU with the dGPU disabled, full dGPU, and “Hybrid” mode, requiring a system reboot between each change. These all come with caveats, but I think I am happy with switching between iGPU only and Hybrid. This allows me to use Wayland most of the time since the iGPU will handle the Desktop Environment, passing OGL/Vulkan workloads to the dGPU on demand. Envycontrol will also handle the kernel parameter necessary for getting tear-free sync when the dGPU is running, which typically gets in the way of fully disabling the nvidia GPU in other solutions.
On an aside, what the fuck is NVIDIA doing with the tearing sync? If you don’t use the nvidia-drm.modeset=1
parameter when using the dGPU on it’s own, you get diagonal tearing. What the hell kinda order are they drawing the framebuffer?
Anyway, some useful variables when operating in hybrid mode:
__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia __VK_LAYER_NV_optimus=NVIDIA_only
will enable offload rendering and tell OpenGL and Vulkan programs to use the nvidia driver. An easy drop in solution is to put all of these variables in a script like below, and throw it in your $PATH somewhere, as per this askubuntu answer: https://askubuntu.com/a/1368463
#!/bin/bash
export __NV_PRIME_RENDER_OFFLOAD=1
export __GLX_VENDOR_LIBRARY_NAME=nvidia
export __VK_LAYER_NV_optimus=NVIDIA_only
export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json
exec "$@"
- I’ve found Vulkan programs seem to correctly select the dGPU on their own since it shows up as Vulkan device 0 in hybrid mode for me. The above
__VK_LAYER_NV_optimus=NVIDIA_only
parameter should force this regardless. Most of the Vulkan programs will let you pick the Vulkan device via an argument/config file/menu/etc. - If you are using Proton/DXVK, you can use the parameter
DXVK_FILTER_DEVICE_NAME="GeForce GT 730M"
to force the dGPU orDXVK_FILTER_DEVICE_NAME="HD Graphics 4600"
to force the iGPU. Device names might need to be changed depending on model, and you can find them usingvulkaninfo
. This won’t work for native Vulkan games/programs since they don’t use DXVK.
Miscellaneous
- Despite what I read online, you can use libgfxinit to boot as well as install both VBIOS blobs for the Intel and NVIDIA GPUs.
- The last NVIDIA driver the GT 730M supports is nvidia-470. These are available on the AUR as
nvidia-470xx-dkms
. - If you use MangoHud, enable the vulkan_driver option and you will be able to identify which GPU the current software is running on based on which driver is providing Vulkan; “470…” for NVIDIA and “Mesa…” for Intel.
- When using Wayland in hybrid mode, whatever it’s enforcing on XWayland causes the dGPU to enforce Vsync even when manually disabled by other means. I can only get an uncapped framerate in 3d workloads on the dGPU by using X11. I might be overlooking something.
- Steam Big Picture warns against using the iGPU at 1080p due to the limited (256mb) of assigned RAM -> VRAM. In hybrid mode, you can run steam itself with the above rendering offload commands to get Big Picture to use the dGPU (with it’s dedicated 1GB VRAM) and circumvent this issue.
- Steam Remote Play uses VAAPI regardless of which GPU you give it, and results in roughly the same ~14ms latency on either. Tested at 1080p to a desktop machine running Earth Defense Force 5. Very playable. I wouldn’t bother offloading remote game streaming to the dGPU.
- My specific touchpad stops responding correctly or entirely after suspend. This was fixed for me with the kernel parameter
psmouse.synaptics_intertouch=0
. YMMV depending on the touchpad make/model. - Under coreboot on the T440p, The SD Card Reader doesn’t work.
That’s everything for now. I’ve tried to play a few older or lower spec games at 720p such as HL2, Portal and ULTRAKILL, all of which ran well enough. Over the next few weeks I will be trying other software to see if the additional acceleration is worth the time. I was thinking of benchmarking some things to compare using Mangohud, but the logging function appears to fail to write with certain game names. I may need to check my configuration.