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

# 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` 调度策略,并必须使用 `taskset` 或 `cpuset` 绑定到隔离的 CPU 核心。在共享 CPU 上以 `SCHED_OTHER`(默认)运行的用户空间进程不会从 RT 内核中受益。

**热限频**

当 SoC 温度升高时,Qualcomm 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 配置中,通过在
`conf/machine/include/qcom-common.inc` 的 `RT_KERNEL_CMDLINE` 中追加以下参数,在内核命令行上传递 `efi=runtime` 来启用 EFI 运行时服务:

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

<Caution>
  请评估你的生产配置是否确实需要 EFI 运行时服务;如果确定性最坏情况延迟是首要需求,请禁用它们(即默认状态)。
</Caution>
