解决华硕天选Air 2025 Linux启动时间过长
HiFiPhile
2025年08月25日 10:46

刚入了台天选Air 14寸 H350 + 5060 (FA401KM)点名吐槽云南国补,装上Arch Linux 发现启动时间超长,需要50秒才能进桌面。。。刷了目前最新的303 BIOS也没有提升😑

省流:直接看解决方法

分析了一下,内核启动就话了40多秒肯定不正常:

代码块
JavaScript
自动换行
复制代码
$ systemd-analyze
Startup finished in 5.721s (firmware) + 7.782s (loader) + 44.140s (kernel) + 2.460s (userspace) = 1min 105ms 
graphical.target reached after 1.705s in userspace.
复制成功

看dmesg的话,发现USB枚举完以后貌似等待了36秒:

代码块
JavaScript
自动换行
复制代码
# dmesg
...
[    2.165573] usb 3-5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[    2.166127] usb 3-5: Product: Bluetooth Radio
[    2.166671] usb 3-5: Manufacturer: Realtek
[    2.167208] usb 3-5: SerialNumber: 00e04c000001
[   38.188085] clk: Disabling unused clocks
[   38.188644] PM: genpd: Disabling unused power domains
[   38.191606] Freeing unused decrypted memory: 2028K
[   38.192520] Freeing unused kernel image (initmem) memory: 4644K
复制成功

直接trace了下initcall,大部分时间都花在了acpi_gpio_handle_deferred_request_irqs上面,和上面的36秒对应:

代码块
JavaScript
自动换行
复制代码
[    1.750332] calling  acpi_gpio_handle_deferred_request_irqs+0x0/0x40 @ 1
...
[   38.126886] initcall acpi_gpio_handle_deferred_request_irqs+0x0/0x40 returned 0 after 36376321 usecs
复制成功

为了看的更清楚使用ftrace跟踪了该函数,具体结果见连接,居然跑出了28万行的log😑

https://gist.github.com/HiFiPhile/324c330b204ef038ef8b3ff2aff7bb6c

从结果可以发现大部分时间花在了acpi_ex_system_do_sleep上,结合内核源码可以定位到BIOS ACPI DSDT表的解析过程,是DSDT代码要求的sleep😓

好家伙,藏的还挺深,DSDT我可从来每搞过,硬着头皮上吧。。。把DSDT dump出来并反编译,查找Sleep发现了如下可疑函数:

代码块
JavaScript
自动换行
复制代码
Method (NOD2, 1, Serialized)
{
    If ((IVGA == Zero))
    {
        If ((Arg0 != RDNT))
        {
            Local0 = Zero
            Local1 = DNOT /* \_SB_.PCI0.SBRG.DNOT */
            DNOT = Arg0
            RDNT = Zero
            While ((Arg0 != RDNT))
            {
                If ((Local0 >= 0x0f))
                {
                    DNOT = Local1
                    Break
                }

                Notify (^^GPP9.PEGP, Arg0)
                Local0++
                Local2 = (Local0 * 0x64)
                Sleep (Local2)
            }
        }
    }
}
复制成功

也不清楚是在干啥,第一次循环等待100ms,退出条件不成立则每次递增直到1500ms,完全对应log中的执行时间。

光脚不怕穿鞋的,把这个函数干掉试试:

代码块
JavaScript
自动换行
复制代码
Method (NOD2, 1, Serialized)
{
    If ((IVGA == Zero))
    {
        If ((Arg0 != RDNT))
        {
            Local1 = DNOT /* \_SB_.PCI0.SBRG.DNOT */
            DNOT = Arg0
            RDNT = Zero
            Notify (^^GPP9.PEGP, Arg0)
            Sleep (0x64)
            DNOT = Local1
        }
    }
}
复制成功

重新编译DSDT并用mkinitcpio的acpi_override hook把文件加入initramfs,问题解决,使用了一天目前还未冒烟🙄

代码块
JavaScript
自动换行
复制代码
$ systemd-analyze
Startup finished in 5.734s (firmware) + 2.246s (loader) + 5.370s (kernel) + 2.481s (userspace) = 15.832s 
graphical.target reached after 2.468s in userspace.
复制成功

解决方法:

声明:ACPI DSDT涉及硬件,错误的DSDT修改可能导致硬件损坏,本人不对此负责!

最稳妥的方法当然是等华硕发布修复版BIOS或是Linux添加对应补丁,该方法只是临时解决方案。

  • 从https://gist.github.com/HiFiPhile/324c330b204ef038ef8b3ff2aff7bb6c 下载修改好的DSDT文件dsdt.aml

代码块
JavaScript
自动换行
复制代码
wget https://gist.github.com/HiFiPhile/324c330b204ef038ef8b3ff2aff7bb6c/raw/791afbad504a61e28738a6ad147f08471d1a583a/dsdt.aml
复制成功
  • 复制到 /etc/initcpio/acpi_override/

代码块
JavaScript
自动换行
复制代码
mkdir /etc/initcpio/acpi_override/
cp dsdt.aml /etc/initcpio/acpi_override/
复制成功
  • 启用acpi_override

代码块
JavaScript
自动换行
复制代码
echo "HOOKS+=(acpi_override )" > /etc/mkinitcpio.conf.d/acpi.conf
复制成功
  • 重建initramfs

代码块
JavaScript
自动换行
复制代码
kernel-install add-all
复制成功