背景

系统原本运行:

linux 7.1.8.arch1-3

并安装了针对:

7.1.8-arch1-3

编译的自定义 i915。

运行状态:

Panel power cycle delay: 2000

随后系统更新提供:

linux
7.1.8.arch1-3
→
7.1.9.arch1-2

以及:

linux-headers
7.1.8.arch1-3
→
7.1.9.arch1-2

这意味着旧模块不能继续使用。


一、为什么考虑 LTS

Arch 普通:

linux

更新频率较高。

而这种机器每次内核 release 改变后,都需要重新编译:

i915.ko

因此长期维护成本较高。

于是改用:

linux-lts

作为唯一主力内核。

需要注意:

LTS 并不意味着永远不用重新编译模块。

只要:

uname -r

发生变化,自定义 i915 原则上仍应重新编译。

但 LTS 的主线变化更保守,更适合作为长期维护基础。


二、安装 LTS

完整升级时安装:

sudo pacman -Syu linux-lts linux-lts-headers

当时实际得到:

linux-lts 6.18.45-2
linux-lts-headers 6.18.45-2

运行 release:

6.18.45-2-lts

三、升级后不要立即重启

这是整个维护流程中最重要的规则:

内核升级完成后,在新自定义 i915 准备完成之前不要重启。

此时:

磁盘上 = 新内核
内存中 = 旧内核

旧内核已经加载的自定义 i915 仍然正常工作。

这为编译新模块提供了一个安全窗口。


四、获取精确 Arch linux-lts 源码

使用 Arch 官方 packaging repository:

archlinux/packaging/packages/linux-lts

确认 tag:

6.18.45-2

对应:

pkgver=6.18.45
pkgrel=2

Git tag 为 annotated tag,因此:

tag object
→
实际 commit

属于正常现象。


五、PKGBUILD 中的 Arch 补丁

对应版本包含几个 Arch patch,例如:

0001-add-sysctl-to-allow-disabling-unprivileged-CLONE_NEW.patch
0002-drm-amdgpu-avoid-memory-allocation-in-the-critical-c.patch
0003-drm-amdgpu-use-GFP_ATOMIC-instead-of-NOWAIT-in-the-c.patch

这些 patch 与 i915 无直接关系,但仍应使用 Arch 的真实 package source tree,而不是随便下载 vanilla kernel 后假设二者完全相同。


六、PGP 验证

执行:

makepkg --nobuild --nodeps

首次遇到:

unknown public key 38DBBDC86092693E

通过 kernel.org 的 WKD 获取发布者公钥:

gpg --locate-keys gregkh@kernel.org

随后核对 fingerprint,并重新运行。

这一次:

linux-6.18.45.tar ... Passed

源码签名验证成功。


七、Rust build dependencies

完整 PKGBUILD 需要:

rust-bindgen
rust-src

由于目标只是单独构建 C 实现的 i915,没有必要为了这个目的安装完整 Rust 内核构建环境。

因此使用:

makepkg --nobuild --nodeps

准备源码。

olddefconfig 会使部分 Rust 相关选项发生变化,例如:

CONFIG_RUST
CONFIG_RUST_FW_LOADER_ABSTRACTIONS
CONFIG_ANDROID_BINDER_IPC_RUST

但关键模块配置仍一致:

CONFIG_DRM_I915=m
CONFIG_MODULE_SIG=y
CONFIG_MODULE_COMPRESS=y
CONFIG_MODULE_COMPRESS_ZSTD=y

八、确认 kernelrelease

Arch LTS 使用:

localversion.10-pkgrel
-2

以及:

localversion.20-pkgname
-lts

最终:

make -s kernelrelease

必须得到:

6.18.45-2-lts

与:

/usr/lib/modules/6.18.45-2-lts/build/include/config/kernel.release

完全一致。


九、重新应用 2000 ms patch

在:

drivers/gpu/drm/i915/display/intel_pps.c

找到:

intel_dp->pps.panel_power_cycle_delay =
        pps_units_to_msecs(final->power_cycle);

增加:

intel_dp->pps.panel_power_cycle_delay =
        max(intel_dp->pps.panel_power_cycle_delay, 2000);

使用 diff 确认整个源码只增加这一行。


十、构建 LTS i915

复制正式:

Module.symvers

然后:

make modules_prepare

make -j"$(nproc)" \
    M=drivers/gpu/drm/i915 \
    modules

成功得到:

i915.ko

大小约:

176 MiB

未压缩。


十一、验证 vermagic

自定义模块:

vermagic:
6.18.45-2-lts SMP preempt mod_unload

官方模块:

vermagic:
6.18.45-2-lts SMP preempt mod_unload

完全一致。


十二、模块签名

Arch 官方模块带:

Build time autogenerated kernel key

而自行构建模块没有官方 signer。

但内核配置:

CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_ALL=y
# CONFIG_MODULE_SIG_FORCE is not set

同时 kernel command line 也没有:

module.sig_enforce=1

因此未签名自定义模块可以正常加载。


十三、压缩和安装

使用 zstd:

zstd -T0 -19 i915.ko \
    -o /tmp/i915-custom.ko.zst

安装:

/usr/lib/modules/6.18.45-2-lts/updates/i915.ko.zst

然后:

sudo depmod -a 6.18.45-2-lts

验证:

modinfo -k 6.18.45-2-lts -n i915

得到:

/lib/modules/6.18.45-2-lts/updates/i915.ko.zst

modprobe --show-depends 也明确选择:

updates/i915.ko.zst

十四、官方模块继续保留

原始 Arch 模块仍位于:

/usr/lib/modules/6.18.45-2-lts/kernel/drivers/gpu/drm/i915/i915.ko.zst

因此没有进行破坏性覆盖。

需要回退时只需要删除:

updates/i915.ko.zst

然后:

sudo depmod -a 6.18.45-2-lts

即可恢复官方模块。


十五、GRUB 最初没有 LTS 项

安装 LTS 后发现:

/boot/vmlinuz-linux-lts
/boot/initramfs-linux-lts.img

已经存在。

但旧:

grub.cfg

是在安装 LTS 之前生成的,因此没有 LTS 启动项。

重新:

sudo grub-mkconfig -o /boot/grub/grub.cfg

后,默认:

Arch Linux

已经指向:

/boot/vmlinuz-linux-lts
/boot/initramfs-linux-lts.img

十六、第一次实际启动验证

重启后:

uname -r

得到:

6.18.45-2-lts

检查:

modinfo -n i915

得到:

/lib/modules/6.18.45-2-lts/updates/i915.ko.zst

最后读取:

i915_panel_timings

结果:

Panel power up delay: 200
Panel power down delay: 60
Panel power cycle delay: 2000
Backlight on delay: 1
Backlight off delay: 200

说明:

LTS kernel
+
custom i915
+
2000 ms workaround

全部真正进入运行状态。


十七、删除普通 Arch 内核

确认 LTS 稳定后,希望只保留:

linux-lts
linux-lts-headers

最初:

sudo pacman -R linux linux-headers

失败:

removing linux breaks dependency 'linux' required by tp_smapi

十八、发现 tp_smapi 遗留包

检查:

tp_smapi

说明:

Modules for ThinkPad's SMAPI functionality

其依赖:

Depends On: linux

且:

Required By: None

当前机器也没有加载:

tp_smapi
thinkpad_ec
hdaps

因此它属于完全不适用于当前硬件的遗留包。

正常删除:

sudo pacman -R tp_smapi linux linux-headers

没有使用:

-Rdd

这种绕过依赖数据库的方式。


十九、最终状态

完成后:

linux-lts 6.18.45-2
linux-lts-headers 6.18.45-2

普通:

linux
linux-headers

已经移除。

/boot 只剩:

vmlinuz-linux-lts
initramfs-linux-lts.img

GRUB 也只引用:

linux-lts

运行中的自定义驱动仍为:

/lib/modules/6.18.45-2-lts/updates/i915.ko.zst

并保持:

Panel power cycle delay: 2000

系统中历史遗留的:

/usr/lib/modules/5.x
/usr/lib/modules/6.x
/usr/lib/modules/7.x

旧目录暂时没有处理。

它们不参与当前启动,可以以后单独审计。


二十、以后升级 LTS 的标准流程

对于存在自定义 i915 的系统,以后不能简单:

pacman -Syu
reboot

推荐固定流程:

1. pacman -Syu
2. 不重启
3. 确认新的 linux-lts release
4. 获取精确 Arch linux-lts source
5. 应用 2000 ms PPS patch
6. 使用对应 Module.symvers 编译 i915
7. 检查 vermagic
8. 安装到新内核 updates/
9. depmod
10. modinfo -k <new-release> -n i915
11. 确认 GRUB
12. 最后 reboot
13. 验证 uname -r
14. 验证 modinfo -n i915
15. 验证 Panel power cycle delay = 2000

这就把一次临时 workaround,转化成了可以长期维护的内核升级流程。

Leave a Reply

Your email address will not be published. Required fields are marked *