> ## 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.

# RT 验证与已知限制

要在 Qualcomm<sup>®</sup> Linux 上实现确定性延迟，既需要 RT 内核，也需要正确的系统配置。本页介绍运行延迟测试前所需的调优步骤、`cyclictest` 的用法，以及 Qualcomm Linux RT 内核的已知限制。

## 测试前系统调优

在运行任何 RT 验证测试之前，请在目标设备上应用以下配置步骤。除非通过 systemd 服务实现自动化（参见
[OTA 与升级注意事项](./rt-ota-upgrade#persist-rt-tuning-across-reboots)），否则每次重启后必须重新应用调优。

### QCS6490 · IQ-9075 · IQ-615

这些平台将 CPU 7 隔离为 RT 核心。CPU 0–6 为常规维护（housekeeping）CPU。

**1. 禁用定时器迁移**

```bash theme={null}
echo 0 > /proc/sys/kernel/timer_migration
```

**2. 将工作队列绑定到维护 CPU（掩码 0x7F = CPU 0–6）**

```bash theme={null}
for wq in /sys/devices/virtual/workqueue/*; do
    [ -w "$wq/cpumask" ] && echo 7F > "$wq/cpumask"
done
```

**3. 将所有 CPU 频率调节器设置为 performance**

```bash theme={null}
for policy in /sys/devices/system/cpu/cpufreq/policy*; do
    [ -w "$policy/scaling_governor" ] && echo performance > "$policy/scaling_governor"
done
```

**4. 禁用 RT 记账/限流**

```bash theme={null}
echo -1 > /proc/sys/kernel/sched_rt_runtime_us
```

**5. 将 IRQ 亲和性设置为维护 CPU（0–6）**

```bash theme={null}
ALLOW_CPUS="0,1,2,3,4,5,6"
cpu_list_to_mask() {
    MASK=0
    for cpu in $(echo $1 | tr ',' ' '); do
        MASK=$((MASK | (1 << cpu)))
    done
    printf "%x\n" "$MASK"
}
MASK=$(cpu_list_to_mask "$ALLOW_CPUS")
echo "Setting IRQ affinity to CPUs: $ALLOW_CPUS (mask=0x$MASK)"
for irq in /proc/irq/[0-9]*; do
    smp_file="$irq/smp_affinity"
    [ -w "$smp_file" ] && echo "$MASK" > "$smp_file" 2>/dev/null
done
```

### IQ-8275

该平台将 CPU 3 隔离为 RT 核心。CPU 0–2 和 4–7 为维护 CPU（掩码 `0xF7`）。

**1. 禁用定时器迁移**

```bash theme={null}
echo 0 > /proc/sys/kernel/timer_migration
```

**2. 将工作队列绑定到维护 CPU（掩码 0xF7 = CPU 0–2、4–7）**

```bash theme={null}
for wq in /sys/devices/virtual/workqueue/*; do
    [ -w "$wq/cpumask" ] && echo F7 > "$wq/cpumask"
done
```

**3. 将所有 CPU 频率调节器设置为 performance**

```bash theme={null}
for policy in /sys/devices/system/cpu/cpufreq/policy*; do
    [ -w "$policy/scaling_governor" ] && echo performance > "$policy/scaling_governor"
done
```

**4. 禁用 RT 记账/限流**

```bash theme={null}
echo -1 > /proc/sys/kernel/sched_rt_runtime_us
```

**5. 将 IRQ 亲和性设置为维护 CPU（0–2、4–7）**

```bash theme={null}
ALLOW_CPUS="0,1,2,4,5,6,7"
cpu_list_to_mask() {
    MASK=0
    for cpu in $(echo $1 | tr ',' ' '); do
        MASK=$((MASK | (1 << cpu)))
    done
    printf "%x\n" "$MASK"
}
MASK=$(cpu_list_to_mask "$ALLOW_CPUS")
echo "Setting IRQ affinity to CPUs: $ALLOW_CPUS (mask=0x$MASK)"
for irq in /proc/irq/[0-9]*; do
    smp_file="$irq/smp_affinity"
    [ -w "$smp_file" ] && echo "$MASK" > "$smp_file" 2>/dev/null
done
```

## 通过 Yocto 安装 rt-tests

`cyclictest` 工具是上游
[rt-tests](https://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git/) 套件的一部分。在您的层配置中向 `IMAGE_INSTALL` 追加以下内容，将其包含到 Yocto 镜像中：

```text theme={null}
IMAGE_INSTALL:append = " rt-tests numactl"
```

重新构建并重新刷写镜像。启动后，`cyclictest` 位于 `/usr/bin/cyclictest`。

## 运行 cyclictest

`cyclictest` 通过调度一个周期性线程，并记录每次唤醒相对于请求间隔的延迟程度，来测量定时器延迟。

### QCS6490 · IQ-9075 · IQ-615（RT 核心：CPU 7）

```bash theme={null}
cyclictest -a 7 -t 1 -m -l 100000000 -i 1000 -p 99 -h 100
```

### IQ-8275（RT 核心：CPU 3）

```bash theme={null}
cyclictest -a 3 -t 1 -m -l 100000000 -i 1000 -p 99 -h 100
```

**表：cyclictest 参数参考**

| **标志** |    **值**    | **含义**                         |
| :----: | :---------: | :----------------------------- |
|  `-a`  |  `7` 或 `3`  | 将测试线程绑定到隔离的 RT CPU             |
|  `-t`  |     `1`     | 运行 1 个测量线程                     |
|  `-m`  |      —      | 锁定所有内存页（防止缺页抖动）                |
|  `-l`  | `100000000` | 测量循环次数（长时测试）                   |
|  `-i`  |    `1000`   | 定时器间隔，单位微秒（1 ms）               |
|  `-p`  |     `99`    | 线程 RT 优先级（`SCHED_FIFO`，优先级 99） |
|  `-h`  |    `100`    | 构建最高到 100 µs 的延迟直方图            |

示例输出：

```text theme={null}
# /dev/cpu_dma_latency set to 0us
policy: fifo: loadavg: 0.00 0.00 0.00

T: 0 ( 1234) P:99 I:1000 C:100000000 Min:      3 Act:    4 Avg:    5 Max:     42
```

`Max` 字段是以微秒为单位的最坏情况延迟。在经过正确调优的系统上，QCS6490、IQ-9075 和 IQ-615 上该值应保持在 100 µs 以下；应用调优后的 IQ-8275 也应低于相同阈值。

有关完整文档和其他测试工具（`hackbench`、`oslat`、`pi_stress`），请参阅
[RT-Tests 文档](https://wiki.linuxfoundation.org/realtime/documentation/howto/tools/rt-tests)。

## 已知限制

**仅限内核空间**

`PREEMPT_RT` 为内核线程和中断处理程序提供确定性调度。用户空间应用必须通过 `sched_setscheduler` 显式选择使用 `SCHED_FIFO` 或 `SCHED_RR` RT 调度策略，并且必须使用 `taskset` 或 `cpuset` 绑定到隔离的 CPU 核心。在共享 CPU 上以 `SCHED_OTHER`（默认）运行的用户空间进程无法从 RT 内核中受益。

**热限频**

Qualcomm SoC 在 SoC 温度升高时会执行热缓解措施来降低 CPU 频率。即使设置了 `performance` 调节器，热事件也可能临时降低 RT 核心的 CPU 频率，从而引入延迟尖峰。在长时生产测试中，请监控热状态：

```bash theme={null}
cat /sys/devices/virtual/thermal/thermal_zone*/temp
```

如果结温经常超过限频阈值，请考虑降低系统负载或改善散热。

**Remoteproc 固件认证**

首次启动时，aDSP、cDSP 和 WPSS 子系统会通过 TrustZone 加载并认证固件。该过程在 `device_initcall` 期间运行，可能耗时数秒，短暂加重内存总线负担，并在早期启动阶段的 RT 测量中引入延迟尖峰。请仅在所有 remoteproc 子系统完全启动后再进行 RT 验证：

```bash theme={null}
# Confirm all subsystems are running before testing
cat /sys/class/remoteproc/remoteproc*/state
# Expected: running (for each enabled subsystem)
```

**SMT / 超线程**

Qualcomm ARM64 SoC 不实现同时多线程（SMT）。因此其 CPU 隔离模型（`isolcpus`、`nohz_full`、`rcu_nocbs`）比 x86 更简单，因为不存在与 RT 核心共享执行资源的同级线程。

**`sched_rt_runtime_us` 与看门狗**

将 `sched_rt_runtime_us` 设置为 `-1`（无限制）会禁用防止 RT 任务饿死 CFS 任务的 RT 限流。这对确定性延迟是必需的，但意味着失控的 RT 任务可能锁死系统。请在生产配置中启用 RT 内核看门狗（`CONFIG_DETECT_HUNG_TASK=y`、`hung_task_timeout_secs`）以缓解此风险。

**EFI 运行时服务**

启用 `PREEMPT_RT` 后，内核的 `EFI_DISABLE_RUNTIME` Kconfig 选项默认为 `y`（参见 `drivers/firmware/efi/Kconfig`）。这有意禁用 EFI 运行时服务，以消除 UEFI 固件调用可能给 RT 调度路径带来的巨大且不可预测的延迟。

在 Qualcomm 平台上，这会带来实际影响：允许用户配置启动时 DTB 叠加层（写入 `VendorDtbOverlays` EFI 变量）需要 EFI 运行时服务。目前 Yocto 配置中通过在内核命令行传入 `efi=runtime` 来启用 EFI 运行时服务，方法是在 `conf/machine/include/qcom-common.inc` 中向 `RT_KERNEL_CMDLINE` 追加如下参数：

```text theme={null}
RT_KERNEL_CMDLINE:append = " efi=runtime"
```

<Caution>
  请评估您的生产配置是否真正需要 EFI 运行时服务；如果确定性最坏情况延迟是首要需求，请禁用它们（即默认配置）。
</Caution>
