> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs-staging.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 优化启动时间

Qualcomm<sup>®</sup> Linux 内核启动时间的跨度是从第一条内核日志消息到第一个可响应的用户空间进程。缩短启动时间需要对 initcall 开销进行剖析、启用异步驱动探测（asynchronous driver probe），并去除未使用的编译进内核的子系统。

## **测量启动时间**

在优化之前，先建立基线测量。

### 添加 initcall\_debug

将 `initcall_debug` 添加到内核命令行。内核会为每个 initcall 打印一条带时间戳的条目及其持续时间：

```text theme={null}
[    1.243718] calling  clk_init+0x0/0x48 @ 1
[    1.243851] initcall clk_init+0x0/0x48 returned 0 after 127 usecs
```

对最慢的 initcall 进行排序：

```bash theme={null}
dmesg | grep "initcall.*after" \
      | sed 's/.*initcall \(.*\) returned.* after \([0-9]*\) usecs/\2 \1/' \
      | sort -rn | head -20
```

使用内核源代码树中的 `scripts/bootgraph.pl` 生成启动时间线 SVG：

```bash theme={null}
dmesg | perl scripts/bootgraph.pl > boot.svg
```

### 配置 printk.time

将 `printk.time=1 loglevel=4` 添加到内核命令行。这会为每条 printk 消息附加微秒级时间戳，同时抑制信息性输出。在低速 UART 上，这可以将串行控制台开销减少 200–500 毫秒。

### 运行 systemd-analyze

在运行 systemd 的系统上，启动后运行以下命令，以查看在内核、initrd 和用户空间各阶段所花费的时间：

```bash theme={null}
systemd-analyze
systemd-analyze blame
systemd-analyze critical-chain
```

## **启用异步探测**

默认情况下，内核按顺序探测平台设备。在 Qualcomm SoC 上，摄像头或显示等单个子系统的探测链可能涉及数十个串行运行的依赖驱动程序。异步探测允许相互独立的驱动程序在多个内核线程中并行探测。

### 启用 Kconfig

```text theme={null}
CONFIG_ASYNC_PROBE=y
```

### 按驱动程序启用

驱动程序通过在 `driver` 结构中设置 `probe_type` 来启用此功能：

```c theme={null}
static struct platform_driver my_driver = {
    .driver = {
        .name           = "my-device",
        .of_match_table = my_dt_match,
        .probe_type     = PROBE_PREFER_ASYNCHRONOUS,
    },
    .probe  = my_probe,
    .remove = my_remove,
}
```

### 通过内核命令行启用

通过使用 driver\_async\_probe 参数，可以在不修改源代码的情况下
强制任何驱动程序使用异步探测。多个驱动程序名称之间用
逗号分隔。

```bash theme={null}
driver_async_probe=qcom-smmu,qcom-cpufreq-hw,qcom-icc-bwmon
```

### 配置延迟探测超时

当驱动程序因依赖项尚不可用而返回 -EPROBE\_DEFER 时，
内核会重试探测。设置 deferred\_probe\_timeout（以秒为单位），以便在
设备始终无法就绪时发出警告并继续启动。

```bash theme={null}
deferred_probe_timeout=10
```

若要在运行时检查待处理的延迟设备，请使用以下命令：

```bash theme={null}
cat /sys/kernel/debug/devices_deferred
```

<Warning>
  不要将 `deferred_probe_timeout` 设置为低于慢速固件加载
  （例如调制解调器、DSP 和 WPSS 子系统）所需的时间。将其设置得
  过低可能导致平台启动后缺少外设。
</Warning>

## **禁用未使用的子系统**

未使用的编译进内核的驱动程序会增加 initcall 开销，即使硬件并不
存在。请针对您的目标板检查以下 Kconfig 符号，并禁用
物料清单（BOM）中未列出的所有驱动程序。

**表：需要为启动时间检查的 Kconfig 符号**

| 符号                    | 说明                                                                                                                 |
| --------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `CONFIG_USB_XHCI_HCD` | 如果 BOM 上不存在 USB 3.0 主机控制器，则禁用。                                                                                     |
| `CONFIG_SOUND`        | 如果音频仅由 DSP 固件处理，则禁用整个 ALSA（Advanced Linux Sound Architecture）树。                                                    |
| `CONFIG_DRM_*`        | 禁用未装配的显示子系统，例如 HDMI（High-Definition Multimedia Interface）、eDP（Embedded DisplayPort）、DSI（Display Serial Interface）。 |
| `CONFIG_CRYPTO_*`     | 禁用未使用的密码套件；保留硬件加密引擎驱动程序。                                                                                           |
| `CONFIG_NETFILTER`    | 如果不需要 iptables 或 nftables 支持，则禁用。                                                                                  |
| `CONFIG_BT`           | 如果 Bluetooth<sup>®</sup> 完全在 WLAN 协处理器固件内处理，则禁用。                                                                   |
| `CONFIG_NFS_FS`       | 如果不使用网络文件系统，则禁用。                                                                                                   |
| `CONFIG_DEBUG_*`      | 在生产构建中禁用所有调试 Kconfig 符号。                                                                                           |
| `CONFIG_KALLSYMS`     | 对于发布镜像可考虑禁用，以减小镜像大小并缩短启动时间。                                                                                        |
| `CONFIG_KPROBES`      | 在生产环境中禁用；它会为每个函数增加 trampoline 开销。                                                                                  |

请使用板级特定的配置片段，而不是直接编辑 `defconfig`。在 Yocto 工作流中，向内核 `bbappend` 添加一个 `.cfg` 片段：

```text theme={null}
# <layer>/recipes-kernel/linux/linux-qcom-base_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI += "file://disable-unused.cfg"
```

`disable-unused.cfg` 的示例内容：

```text theme={null}
# CONFIG_SOUND is not set
# CONFIG_USB_XHCI_HCD is not set
```

## **优化 initramfs**

initramfs 在根文件系统挂载之前被解压并执行。过大的 initramfs 会同时增加解压时间和存储 I/O 开销。

### 选择快速的压缩算法

在 Cortex-A55 和 Cortex-A78 核心上，LZ4 的解压速度远快于 gzip，但
它生成的镜像大小会略大一些：

```text theme={null}
CONFIG_RD_LZ4=y
# CONFIG_RD_GZIP is not set
# CONFIG_RD_XZ is not set
```

### 精简软件包集

编辑 `meta-qcom/recipes-kernel/images/initramfs-qcom-image.bb`，移除早期启动期间不需要的软件包。如果所有必需的驱动程序都已编译进内核（设置为 `=y` 而不是 `=m`），则移除 `initramfs-module-copy-modules`。

通过在 Yocto 配置中设置以下内容，确保所有 initramfs 二进制文件都已被剥离（strip）：

```text theme={null}
INHIBIT_PACKAGE_STRIP = "0"
```

## **优化 Qualcomm remoteproc 固件加载**

在 QCS6490、IQ-9075 及相关 SoC 上，aDSP、cDSP 和 WPSS 子系统在 `device_initcall` 期间通过 `qcom_q6v5_pas` 驱动程序加载其固件。每个镜像在子系统启动前都由 TrustZone 进行认证。所有子系统的总加载时间可能超过两秒。

如果 `/lib/firmware` 中缺少任何固件文件，`request_firmware()` 调用会在每个子系统上等待 60 秒后超时，从而完全阻塞启动。请验证固件已正确部署：

```bash theme={null}
ls /lib/firmware/qcom/qcs6490/
# Expected: adsp.mdt, cdsp.mdt, wpss.mdt (and associated .bNN segments)
```

如果早期启动期间不需要 WLAN 或音频，请在板级设备树 overlay 中禁用相应的 remoteproc，并在关键路径完成后从用户空间启动它：

```text theme={null}
/* In board DTS overlay */
&remoteproc_wpss {
    status = "disabled";
};
```

在准备就绪后从用户空间启动它：

```bash theme={null}
echo start > /sys/class/remoteproc/remoteproc2/state
```

有关 remoteproc 驱动程序配置的详细信息，请参阅[配置 RemoteProcessor（remoteproc）子系统](./configure-the-remoteprocessor-remoteproc-subsystems)。

## **内核命令行快速参考**

以下参数对启动时间有显著影响：

**表：影响启动时间的内核命令行参数**

| 参数                           | 作用                                                        |
| ---------------------------- | --------------------------------------------------------- |
| `quiet`                      | 抑制大多数内核日志消息；在低速 UART 上可将串行 I/O 减少 200–500 毫秒。             |
| `loglevel=0`                 | 静默所有低于 `KERN_EMERG` 的 printk 输出。与 `quiet` 一起使用可实现最大程度的抑制。 |
| `initcall_debug`             | 启用每个 initcall 的计时。仅用于性能剖析，不要用于生产构建。                       |
| `driver_async_probe=<list>`  | 强制列出的驱动程序进入异步探测模式。                                        |
| `deferred_probe_timeout=<s>` | 如果延迟设备在该秒数后仍未就绪，则继续启动。                                    |
| `cma=<size>`                 | 当 DSP 或摄像头内存需求低于默认值时，减少 CMA 预留。                           |
| `audit=0`                    | 禁用 Linux 审计子系统；减少系统调用开销。                                  |
