Lenovo ThinkPad X1 Extreme

From ArchWiki

Tango-edit-clear.pngThis article or section does not follow the Laptop page guidelines.Tango-edit-clear.png

Reason: Hardware table needs IDs and a function keys section should be added (Discuss in Talk:Lenovo ThinkPad X1 Extreme)
Hardware PCI/USB ID Working?
Touchpad Yes
Keyboard Yes
GPU (Intel) Yes
GPU (Nvidia) Yes
Webcam Yes
Ethernet Yes
Bluetooth Yes
Card reader Yes
Audio Yes
Wireless Yes
Thunderbolt Yes
Fingerprint reader 06cb:009a Experimental
Note: The Lenovo ThinkPad P1 is a workstation version of the same laptop which uses extremely similar hardware. Most of the information on this page should be applicable to P1 models as well.

Firmware update

A UEFI firmware update is strongly recommended for general use of the laptop - the initial 1.13 version devices seem to ship with contains multiple bugs that can result in bricking the laptop: Reddit thread discussing the issue; another Reddit thread discussing a different bricking issue.

Firmware updates are available via fwupd, the Lenovo Vantage application on Windows, or from Lenovo's website.

The latest version, v1.35, is highly recommended. All information on this page assumes the latest firmware.

Video

Both the HDMI port and DisplayPort outputs created when using either a USB-C adapter or Thunderbolt dock are wired to the Nvidia dGPU.

A BIOS setting can be used to disable the integrated GPU, and run everything on the dedicated Nvidia card. The dedicated GPU cannot be disabled through firmware, so enabling runtime power management in some form is highly recommended when using the iGPU.

CPU thermal throttling

This laptop is affected by a CPU throttling bug when using Linux.

Basically, the laptop's firmware uses an implementation of Intel's Dynamic Platform and Thermal Framework (DPTF) that does not work with Linux. While newer generations of ThinkPads have gotten a BIOS update to fix this, a Lenovo employee confirmed that older affected Thinkpads (including T580, T480, T480s, X1C6, P1G1 and X1E1) will not get the fix.

A stress test using s-tui indicates that the CPU is limited to 38W/80C at boot, resulting in a sustained all-core frequency of around 2850 MHz on the i7-8750H.

Fix using reverse-engineered DPTF implementation

There is an ongoing effort to reverse-engineer DPTF on Linux. Results can be found here. Most of the work has been upstreamed already, though the implementation is still far from complete.

Starting with kernel 5.12, the work-in-progress can be utilized by installing and enabling thermald, which will attempt to make use of the firmware's adaptive performance policy.

Unfortunately, the current implementation does not appear to help much on this laptop. While the CPU's limit is raised to 45W/83C, the all-core frequency is erratic, resulting in only a marginal performance improvement.

Fix using dptfxtract and manual DPTF profile setting

Another option, which does result in full performance, is to extract the DPTF tables and use them in combination with a manual change of the DPTF profile.

Configuring thermald to use extracted dptf tables

First, make sure thermald is installed. Next, use Intel's proprietary dptfxtract-binAUR tool to extract the DPTF tables:

# dptfxtract

This will populate /etc/thermald/ with multiple configuration files of the form thermal-conf.xml.*, each of which represents a converted DPTF table.

The tool also creates a copy of each of these files in the current working directory, so you may want to remove those:

# rm thermal-conf.xml.*

The thermald service file shipped with Arch Linux enables adaptive mode by default. In order to use the extracted tables we have to override it.

Create the necessary directory if it does not exist already:

# mkdir -p /etc/systemd/system/thermald.service.d

Then create the following file:

/etc/systemd/system/thermald.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/thermald --systemd --dbus-enable

Afterwards, reload the systemd manager configuration and enable thermald.

Selecting the appropriate configuration

Warning: Editing the configuration files in /etc/thermald/ is not recommended as it may result in your laptop running out of spec!

Out of all the generated configuration files, thermald will use thermal-conf.xml.auto by default. You can try any of the other configurations by adding the --config-file flag to the override.conf created earlier.

The default configuration file already unlocks full performance. A stress test indicates that the CPU is now limited to 45W/95C, resulting in a sustained all-core frequency of around 3300 MHz on the i7-8750H.

Manually setting a DPTF profile to prevent temporary re-throttling

The setup above is not perfect, every time the CPU temperature trips over 80C the laptop's embedded controller (EC) will re-throttle the CPU for a few seconds.

This issue can be fixed, without 'fighting the EC', by manually setting the adaptive performance DPTF profile using the following script:

set_dptf_adaptive.sh
#!/bin/bash
# Script that enables the adaptive performance DPTF profile, if available.

# Check for super user privileges.
if (( $EUID != 0 )); then
    echo "ERROR: script requires super user privileges. Exiting!"
    exit 1
fi

# from: https://github.com/torvalds/linux/blob/master/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
adaptive_performance_uuid='63BE270F-1C11-48FD-A6F7-3AF253FF3E2D'

# Check if the adaptive performance profile is supported.
available_uuids=$(cat /sys/devices/platform/INT3400:00/uuids/available_uuids)

if [[ $available_uuids != *$adaptive_performance_uuid* ]]; then
  echo "ERROR: adaptive performance profile not supported. Exiting!"
  exit 1
fi

# Find the INT3400 Thermal driver.
INT3400=$(grep INT3400 /sys/class/thermal/thermal_zone*/type |
          grep Thermal |
          sed '/\/sys\/class\/thermal\/thermal_zone/ s/\/type.*//')

if [[ "$INT3400" == '' ]]; then
  echo "ERROR: unable to find the INT3400 thermal driver. Exiting!"
  exit 1
fi

# Temporarily disable the INT3400 thermal driver.
echo 'disabled' > "$INT3400"/mode

if [[ $(cat "$INT3400"/mode) != 'disabled' ]]; then
  echo "ERROR: unable to disable the INT3400 thermal driver. Exiting!"
  exit 1
fi

# Enable the adaptive performance profile.
echo "$adaptive_performance_uuid" > /sys/devices/platform/INT3400:00/uuids/current_uuid

current_uuid=$(cat /sys/devices/platform/INT3400:00/uuids/current_uuid)
if [[ "$current_uuid" != "$adaptive_performance_uuid" ]]; then
  echo "ERROR: unable to set the adaptive performance profile. Exiting!"
  exit 1
fi

# Re-enable the INT3400 thermal driver.
echo 'enabled' > "$INT3400"/mode

if [[ $(cat "$INT3400"/mode) != 'enabled' ]]; then
  echo "ERROR: unable to re-enable the INT3400 thermal driver. Exiting!"
  exit 1
fi

echo "Successfully set the adaptive performance DPTF profile."

Save the script somewhere and create a systemd service for it:

/etc/systemd/system/dptf_adaptive.service
[Unit]
Description=Set Intel DPTF policy to adaptive performance

[Service]
Type=oneshot
ExecStart=/path/to/script/set_dptf_adaptive.sh

[Install]
WantedBy=default.target

Do not forget to replace /path/to/script/ in the service file.

Finally, reload the systemd manager configuration and enable the service.

Disabling BDPROCHOT to prevent throttling on battery

Warning:
  • After this fix the laptop may run hotter than is comfortable when using it on your lap or similar positions.
  • Disabling BDPROCHOT can be considered a 'nuclear option' in terms of power management. Use at your own risk!
Note: Writing to MSRs requires that Secure Boot is disabled in the BIOS.

The laptop's performance on battery is far below expectations when using Linux. The cause appears to be something called 'lap mode' (documented by Lenovo, here).

Basically, when unplugged, the laptop will by default assume that it is being used on the user's lap. And since Linux has no working DPTF implementation to tell the the laptop otherwise, it will always assume it is being used the user's lap. Consequently, In order to keep the laptop base at a 'skin friendly' temperature, the laptop's EC throttles the CPU with BDPROCHOT (BiDirectional PROCessor HOT) when one of many thermal sensors trips a predetermined value. Effectively this will keep the CPU at around 70C max while simultaneously preventing the fans from properly spinning up. A repeated on-again off-again all-core stress test causes the CPU to throttle as low as 800 MHz.

Since there is currently no known way to disable 'lap mode', the only path to full performance on battery is to disable BDPROCHOT altogether. This can be done using the following script:

bdprochot_disable.sh
#!/bin/bash
# Script that unsets the BDPROCHOT-bit on some Intel CPUs.

# Check for super user privileges.
if (( $EUID != 0 )); then
    echo "ERROR: script requires super user privileges. Exiting!"
    exit 1
fi

# Enable writing to model-specific registers of the CPU.
modprobe msr

# Get current state of the CPU power-related bits (in base-10).
flags=$(rdmsr 0x1FC -d)

# Check if BDPROCHOT-bit is already unset.
if [[ $(("$flags" & 0x00000001)) == 0 ]]; then
    echo "INFO: BDPROCHOT-bit is already unset. Exiting!"
    exit 0
fi

# Unset BRPROCHOT-bit.
wrmsr -a 0x1FC $(("$flags" & 0xfffffffe))

# Check if we were successful.
flags=$(rdmsr 0x1FC -d)

if [[ $(("$flags" & 0x00000001)) == 1 ]]; then
    echo "ERROR: unable to unset BDPROCHOT-bit. Exiting!"
    exit 1
fi

echo "Successfully disabled BDPROCHOT."

Save the script somewhere and create a systemd service for it:

/etc/systemd/system/bdprochot_disable.service
[Unit]
Description=Disable BDPROCHOT

[Service]
Type=oneshot
ExecStart=/path/to/script/bdprochot_disable.sh

[Install]
WantedBy=default.target

A suspend/resume-cycle will cause the EC to re-set the BDPROCHOT-bit.

Create the following file (and make it executable) to run the script on resume:

/lib/systemd/system-sleep/bdprochot
#!/bin/sh

case "$1" in
    post)
        /path/to/script/bdprochot_disable.sh
        ;;
esac

Do not forget to replace /path/to/script/ in both files.

Finally, reload the systemd manager configuration, enable the service and reboot.

The CPU's performance on battery should now be roughly equal as when plugged in.

Microphone noise reduction

PulseAudio's PulseAudio#Microphone echo/noise cancellation can be used to reduce the amount of microphone noise by adding the following to /etc/pulse/default.pa:

/etc/pulse/default.pa
### Enable Echo/Noise-Cancellation
load-module module-echo-cancel use_master_format=1 aec_method=webrtc aec_args="beamforming=1 mic_geometry=-0.0257,0,0,0.0257,0,0" source_name=echoCancel_source sink_name=echoCancel_sink
set-default-source echoCancel_source
set-default-sink echoCancel_sink

The above mic_geometry is specific to the X1 Extreme.

The module-filter-heuristics and module-filter-apply modules can sometimes result in adding additional noise, so the lines that enable them should be commented out:

/etc/pulse/default.pa
#load-module module-filter-heuristics
#load-module module-filter-apply

Bad sound quality may also result from audio clipping, which can occur if "Internal Mic Boost" is larger than zero in alsamixer.

Fingerprint reader

A reverse engineering effort is ongoing here, and an experimental driver is available on the AUR as python-validityAUR.

Upstream libfprint bug is tracked here.

See also