Configuration for ThinkPad T14s Gen 6 (Snapdragon X Elite X1E-78-100)

I would like to share the relevant part of my configuration as I spent quite some time to get NixOS booting on my ThinkPad T14s Gen 6 (Snapdragon X Elite X1E-78-100).

This would not have been possible without the working Ubuntu installer image and the support in Ubuntu 24.10 Concept ♥️ Snapdragon X Elite - Ubuntu Architectures - Ubuntu Community Hub

Some things like accelerated graphics, battery gauge and sound require firmware files from the Windows image, which I did not bother with.

boot = {
  kernelPackages = pkgs.linuxPackages_latest;
  kernelParams = [
    "clk_ignore_unused"
    "pd_ignore_unused"
  ];
  kernelPatches = [
    {
      name = "snapdragon-config";
      patch = null;
      extraConfig = ''
        TYPEC y
        PHY_QCOM_QMP y
        QCOM_CLK_RPM y
        MFD_QCOM_RPM y
        REGULATOR_QCOM_RPM y
        PHY_QCOM_QMP_PCIE y
        CLK_X1E80100_CAMCC y
      '';
    }
  ];
  loader = {
    efi.canTouchEfiVariables = true;
    systemd-boot = {
      enable = true;
    };
  };
};

hardware = {
  deviceTree = {
    enable = true;
    name = "qcom/x1e78100-lenovo-thinkpad-t14s.dtb";
  };
  enableRedistributableFirmware = true;
  firmware = [
    (
      let
        t14sPkgs = builtins.fetchTarball {
          url = "https://<redacted>/t14sfirmware.tar";
          sha256 = "03vgfhq16q95fdh00mvqbprw1m84lhgk5x6jjj7m4f981vcnapha";
        };
      in
      pkgs.runCommandNoCC "t14s" { } ''
          mkdir -p $out/lib/firmware/qcom/x1e80100/LENOVO/
        cp -r ${t14sPkgs} $out/lib/firmware/qcom/x1e80100/LENOVO/21N1/
      ''
    )
  ];
};

networking = {
  wireless = {
    iwd = {
      settings = {
        General = {
          ControlPortOverNL80211 = false;
        };
      };
    };
  };
};

nix = {
  settings = {
    cores = 4;
    max-jobs = 4;
  };
};

edit: forgot to merge the devicetree.
edit dec 2024:
- replace fetchgit with fetchurl
- add nix.settings.cores and max-jobs set to 4 to prevent overheat crash
- add:
networking.wireless.iwd.settings.General.ControlPortOverNL80211 = false to make wlan work: WCN7850 disconnects and reconnects in a loop
edit jan 2025:
-add hardware.firmware

6 Likes

Interesting, i assume performance isn’t great without HW-accel, but how usable is it? I moved the thread to Guides btw.

1 Like

The laptop is currently building libreoffice-24.8.2.1 which will likely take some time.

When done, I’ll test firefox and chromium with WebGL Aquarium

Oops, thanks!

(libreoffice build failed).

With 10k fish 12 fps in firefox and 5 fps in ungoogled chromium.
With 5k fish 17 fps in firefox and 8 fps in ungoogled chromium.
With 1k fish 25 fps in firefox, 18 fps in ungoogled chromium.

Kernel compile takes about 33 minutes.

Have not used it much but so far the T14s feels very snappy.

With the firmware blob qcdxkmsuc8380.mbn (pulled from Windows), running sway and firefox (programs.xwayland.enabled = false):

  • 10k fish = 60 fps
  • 20k fish = 44 fps
  • 30k fish = 30 fps

Thanks for sharing @ookhoi, I’ve just got a similar laptop and am trying this out with a configuration based on yours.

On my first attempt the system boots, but I get a blue screen (reminds me of Windows!) and a reboot as soon as I hit a key on the keyboard. Using an external keyboard works fine. I think this is probably due to not using the extracted Windows firmware, so I’m going to try that, but I just wondered if you also encountered this issue?

My 32GB T14s is fine, but with my brand new 64GB T14s I experience the same (dark)blue screen and instant reboot at the very first key press after boot. So I assume you have a 64GB configuration as well.

For now I’m booting with 16GB of memory:

kernelParams = [
  "clk_ignore_unused"
  "pd_ignore_unused"
  "mem=16G"
];

With mem=32G I still experience the blue screen. I have not tried values between 16 and 32.

I found Thinkpad_t14s | AArch64 Laptops which states at the bottom:

Boot issues with 64 GB version (disable upper 32 GB as workaround):
cutmem 0x8800000000 0x8fffffffff

Could be related.

I have not tried with Windows firmware but would be surprised if that helps. It happens with both 6.12.x and 6.13-rc5.

I’ve updated my post with a hardware.firmware stanza.

Thanks, yes I made a specialisation with mem=16G and that works fine. The interesting thing is that I installed Ubuntu before NixOS just to validate things, and I didn’t have any such problem. I guess it would be worth looking at the kernel they are using, I’ll have a look tomorrow.

The cutmem snippet you posted is for Grub. I don’t think systemd-boot has a direct equivalent, but there’s probably a way to do it.

1 Like

In Ubuntu you might have noticed only 32GB out of 64GB memory is reported/available.

According to Bug #2084178 “[X1E] Request: Add support for Lenovo Thinkpad T14...” : Bugs : ubuntu-concept Ubuntu: our installer images have the cutmem hack hardcoded otherwise booting from usb would be impossible

It’s odd, because I installed Ubuntu and booted it, and I don’t think the cutmem setting carried over to the installation. I’m pretty sure I checked /proc/meminfo and it reported 64GB with no crashes. It’s possible I was just lucky somehow, because I didn’t use the machine for long, or I’m misremembering.

For the moment I’ve just gone with mem=31G (32G also didn’t work for me). I also played with using memmap to exclude the region, but it seems that doesn’t do enough. I don’t think systemd-boot has a cutmem equivalent, but 31G will do for the moment I guess!

1 Like

I just got a T14s Gen6 with 64GB and installed Ubuntu on it to see what to expect before trying to install NixOS on it. Currently booted off of NVMe free shows it has 64GB (as does cat /proc/meminfo).

Is the mem option only needed when booting off USB?

1 Like

FWIW

root@pirayu:~# lscpu 
Architecture:             aarch64
  CPU op-mode(s):         64-bit
  Byte Order:             Little Endian
CPU(s):                   12
  On-line CPU(s) list:    0-11
Vendor ID:                Qualcomm
  BIOS Vendor ID:         Qualcomm Technologies Inc
  Model name:             -
    BIOS Model name:      Snapdragon(R) X Elite - X1E78100 - Qualcomm(R) Oryon(TM) CPU 446 CPU @ 0.7GHz
    BIOS CPU family:      280
    Model:                1
    Thread(s) per core:   1
    Core(s) per socket:   4
    Socket(s):            1
    Stepping:             0x2
    CPU(s) scaling MHz:   64%
    CPU max MHz:          3417.6001
    CPU min MHz:          710.4000
    BogoMIPS:             38.40
    Flags:                fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 asimdfhm dit uscat ilrcpc flagm ssbs sb paca pacg dcpodp flagm2 frint i8mm bf16 rng bti ecv afp rpres
  Model name:             -
    BIOS Model name:      Snapdragon(R) X Elite - X1E78100 - Qualcomm(R) Oryon(TM) CPU 446 CPU @ 0.7GHz
    BIOS CPU family:      280
    Model:                1
    Thread(s) per core:   1
    Core(s) per socket:   8
    Socket(s):            1
    Stepping:             0x1
    CPU(s) scaling MHz:   26%
    CPU max MHz:          3417.6001
    CPU min MHz:          710.4000
    BogoMIPS:             38.40
    Flags:                fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 asimdfhm dit uscat ilrcpc flagm ssbs sb paca pacg dcpodp flagm2 frint i8mm bf16 rng bti ecv afp rpres
NUMA:                     
  NUMA node(s):           1
  NUMA node0 CPU(s):      0-11
Vulnerabilities:          
  Gather data sampling:   Not affected
  Itlb multihit:          Not affected
  L1tf:                   Not affected
  Mds:                    Not affected
  Meltdown:               Not affected
  Mmio stale data:        Not affected
  Reg file data sampling: Not affected
  Retbleed:               Not affected
  Spec rstack overflow:   Not affected
  Spec store bypass:      Mitigation; Speculative Store Bypass disabled via prctl
  Spectre v1:             Mitigation; __user pointer sanitization
  Spectre v2:             Mitigation; CSV2, BHB
  Srbds:                  Not affected
  Tsx async abort:        Not affected
root@pirayu:~# lsmem 
RANGE                                  SIZE  STATE REMOVABLE     BLOCK
0x0000000080000000-0x0000000087ffffff  128M online       yes        16
0x0000000090000000-0x00000000f7ffffff  1.6G online       yes     18-30
0x0000000880000000-0x0000000fffffffff   30G online       yes   272-511
0x0000008800000000-0x0000008fffffffff   32G online       yes 4352-4607

Memory block size:       128M
Total online memory:    63.8G
Total offline memory:      0B
root@pirayu:~# free
               total        used        free      shared  buff/cache   available
Mem:        63860052     2752968    59572616      304688     2426060    61107084
Swap:        8388604           0     8388604
root@pirayu:~# cat /proc/meminfo 
MemTotal:       63860052 kB
MemFree:        59575100 kB
MemAvailable:   61109568 kB
Buffers:           78356 kB
Cached:          2226392 kB
SwapCached:            0 kB
Active:          2287912 kB
Inactive:        1091784 kB
Active(anon):    1379684 kB
Inactive(anon):        0 kB
Active(file):     908228 kB
Inactive(file):  1091784 kB
Unevictable:      234960 kB
Mlocked:              16 kB
SwapTotal:       8388604 kB
SwapFree:        8388604 kB
Zswap:                 0 kB
Zswapped:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:       1310252 kB
Mapped:           513596 kB
Shmem:            304688 kB
KReclaimable:     121312 kB
Slab:             338736 kB
SReclaimable:     121312 kB
SUnreclaim:       217424 kB
KernelStack:       18816 kB
ShadowCallStack:    4748 kB
PageTables:        29372 kB
SecPageTables:       852 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    40318628 kB
Committed_AS:    6794108 kB
VmallocTotal:   135288315904 kB
VmallocUsed:       57932 kB
VmallocChunk:          0 kB
Percpu:            12336 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
FileHugePages:         0 kB
FilePmdMapped:         0 kB
CmaTotal:         131072 kB
CmaFree:            3704 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:               0 kB
root@pirayu:~# uname -a
Linux pirayu 6.12.0-21-qcom-x1e #21-Ubuntu SMP PREEMPT_DYNAMIC Thu Dec 19 15:37:44 UTC 2024 aarch64 aarch64 aarch64 GNU/Linux
root@pirayu:~# lsb_release 
No LSB modules are available.
root@pirayu:~# lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 24.10
Release:	24.10
Codename:	oracular
1 Like

Thanks for confirming what @graham33 also remembered. I’ve only used the Ubuntu live boot which I seem to remember as limited to 32GB.

I boot NixOS from the internal nvme drive and need mem= to get rid of the blue screen at first keystroke.

You’re right. Booting from the Ubuntu Live CD only shows 32GB for me too, while booting from the installed Ubuntu shows 64GB. Neither had a mem option in /proc/cmdline FWIW

Anyway, I now have NixOS installed on it (struggled trying to get Grub to work for a while before trying systemd-boot) and I also got a the blue screen on first keystroke issue until I added the mem=31GB workaround. I noticed the keystroke did echo on the screen right before it crashed, but I have not experimented with it much yet.

Thanks for figuring this all out and documenting it for us! I would never have thought to try systemd-boot if not for seeing that it had worked for you. (Ubuntu is using Grub, though it seems they may have needed to patch it.)

1 Like

BTW, in case anyone is wondering, NixOS 24.11 does work on the Snapdragon X Elite, though I probably will be upgrading to unstable soon.

ivan@pirayu:~$ nixos-version 
24.11.20250109.530de2c (Vicuna)
ivan@pirayu:~$ uname -a
Linux pirayu 6.12.8 #1-NixOS SMP Thu Jan  2 09:34:26 UTC 2025 aarch64 GNU/Linux
ivan@pirayu:~$ uptime 
 21:22:06  up 192 days  9:19,  5 users,  load average: 0.09, 0.17, 0.25

Something seems a little wonky with the uptime calculation though. :sweat_smile:

Most relevant seems to be the devicetree, which has not seen much change since its inception last august:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dts

Yeah, I see the same on all my arm devices and use journalctl -b -g 'Initial clock synchronization' to find the boot time.

Could be solved in 6.14: LKML: Johan Hovold: [PATCH 0/7] arm64: dts: qcom: x1e80100: enable rtc

his series adds support for utilising the UEFI firmware RTC offset to
the Qualcomm PMIC RTC driver and uses that to enable the RTC on all X
Elite machines.

:sunglasses:

1 Like

Just wondering if anyone’s successfully running a recent NixOS unstable on the t14s? 24.11 has worked fine, but as soon as I’ve upgraded to unstable I’ve been seeing issues with systemd-boot not loading the kernel. I haven’t narrowed it down yet, but it’d be useful to know if people are doing this successfully.

This is a known UEFI issue for the T14s, not related to Linux distribution, kernel version or boot loader: Bug #2086540 “[T14s] (sometimes) unbootable system” : Bugs : ubuntu-concept - [T14s] (sometimes) unbootable system

I’ve cleaned duplicate boot entries with efibootmgr which might or might not help. It seems safe to delete the Lenovo boot entries as well: they got re-created on mine.

When systemd-boot fails to load the kernel it is usually sufficient to press F12 to enter the boot menu, press arrow down once to select the only option (nvme drive), and press enter to boot from nvme.

If that fails, boot with any random USB-A device plugged in. If even that fails, try to plug in the USB-A device during boot, or unplug at the systemd-boot menu.

I’m tracking nixpkgs-unstable btw, have been running 6.14-rc3 past week, about to compile 6.14-rc4.

1 Like

Ah, thanks! I hadn’t seen this issue I assumed the problem was related to the upgrade, but sounds like it was more just because I was adding/changing boot entries and must have perturbed it. I’ll try the workarounds, thanks!