> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.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（高级 Linux 声音架构）树。                    |
| `CONFIG_DRM_*`        | 禁用未配备的显示子系统，例如 HDMI（高清多媒体接口）、eDP（嵌入式 DisplayPort）、DSI（显示串行接口）。 |
| `CONFIG_CRYPTO_*`     | 禁用未使用的加密套件；保留硬件加密引擎驱动。                                         |
| `CONFIG_NETFILTER`    | 如果不需要 iptables 或 nftables 支持，则禁用。                              |
| `CONFIG_BT`           | 如果 Bluetooth<sup>®</sup> 完全由 WLAN 协处理器固件处理，则禁用。                |
| `CONFIG_NFS_FS`       | 如果不使用网络文件系统，则禁用。                                               |
| `CONFIG_DEBUG_*`      | 在生产构建中禁用所有调试 Kconfig 符号。                                       |
| `CONFIG_KALLSYMS`     | 对于交付镜像可考虑禁用，以减小镜像大小并缩短启动时间。                                    |
| `CONFIG_KPROBES`      | 在生产环境中禁用；会为每个函数增加跳板（trampoline）开销。                             |

请使用特定于开发板的配置片段（fragment），而不是直接编辑 `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 驱动配置的详细信息，请参阅[配置远程处理器（remoteproc）子系统](./configure-the-remoteprocessor-remoteproc-subsystems)。

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

以下参数对启动时间有可测量的影响：

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

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