Linux RT 分析Linux 6.12.107

14 · 自动驾驶 SoC 落地(ARM64):干扰源、分区样板与参数集

结论:自动驾驶 SoC(Orin/Thor、TDA4、S32G、R-Car V4H、Snapdragon Ride、征程 6 等)都是「多簇 Cortex-A 应用核 + Cortex-R 安全岛 + GPU/NPU/ISP 加速器 + 高带宽传感器接入」的异构结构,Linux 只跑在 A 核上。RT 内核解决的是 A 核上的内核抢占问题;要让 100 Hz–1 kHz 的控制/规划回路拿到 < 100 µs 抖动,还必须:把传感器接入 + 感知控制/规划放到不同核簇;把 GPU/NPU/ISP 驱动的中断、DMA 缓存维护、CMA/SMMU 开销关进接入簇;用完整的参数集(Kconfig + cmdline + sysctl + 亲和 + 优先级)固化下来;并对厂商驱动做一次 RT 兼容性验证。本章给出三种核数样板与可直接套用的参数集,全部参数在 6.12.107 源码中有据可查。

第一层:数据流与抖动

先看结论:默认形态下所有传感器中断、GPU 完成中断、softirq、分配器路径都汇到同一批核的不可抢占区里,控制线程的最坏唤醒延迟由「最长的那一段」决定;分区后控制簇上只剩 arch timer、IPI 和自己触发的内核路径。

非 RT感知 / 中断 / 中间件 / 控制在同一批核上混跑
非 RT:感知 / 中断 / 中间件 / 控制在同一批核上混跑
同一场景 · 换成 PREEMPT_RT 内核
PREEMPT_RT三簇分区后的数据流与优先级
RT:三簇分区后的数据流与优先级

第二层:干扰源全景与 12 核样板

先看结论:自动驾驶 SoC 比通用 arm64 多出四类噪声——GPU/NPU/ISP 厂商驱动、非一致性 DMA 与 CMA、hypervisor、功能安全监控;RT 内核直接消除的是中断/softirq/锁那一层,其余靠分区与启动期预分配。

非 RT干扰源全景与它们在 6.12.107 里的位置
非 RT:干扰源全景与它们在 6.12.107 里的位置
同一场景 · 换成 PREEMPT_RT 内核
PREEMPT_RT12 核 A78AE 样板的分区、亲和、优先级与参数
RT:12 核 A78AE 样板的分区、亲和、优先级与参数

14.1 自动驾驶 SoC 的共性与 BSP 现状

特征 典型配置 对 RT 的意义
应用核 4–12× Cortex-A78AE/A76/A72/A53,1–3 个 DSU 簇,部分支持 Split-Lock/DCLS 锁步 分区以簇为单位;锁步模式下核数减半、频率可能降
安全岛 Cortex-R52/R5F 跑 AUTOSAR/RTOS,通过 mailbox/rpmsg 与 Linux 通信 硬实时(< 10 µs)留在 R 核;Linux 侧目标是「软硬之间」的 50–100 µs 级
加速器 GPU(NVIDIA/Mali/Adreno)、NPU/DLA、ISP、视频编解码 厂商驱动是 RT 兼容性最大的未知数
传感器接入 8–12 路 CSI-2 相机、10 GbE/2.5 GbE 雷达与激光雷达、CAN-FD ×N、TSN 以太网 高中断率与高 DMA 带宽集中在接入簇
互连/内存 非一致性或部分一致性 DMA、SMMU、LPDDR5 共享带宽、ECC 缓存维护与带宽争用是 RT 无法消除的噪声
虚拟化 QNX Hypervisor / Xen / KVM 分隔 ASIL 域与 QM 域 Linux 作为 guest 时 vGIC 注入延迟叠加
内核版本 厂商 BSP:Orin JetPack 6 = 5.15(提供 RT 内核)、TI SDK = 6.1/6.6(PROCESSOR-SDK-LINUX-RT)、NXP = 6.6(RT BSP)、Renesas = 6.1 6.12 之前需要 -rt 补丁;本文机制在 5.15+ 的 -rt 内核上基本一致,行号不同

14.2 自动驾驶特有的干扰源(按严重程度)

干扰源 机制 典型量级 对策 位置
非一致性 DMA 缓存维护 相机/雷达缓冲 dma_syncdcache_clean/inval_poc() 逐行遍历 每 MB 约 0.1–0.4 ms(A53 更慢),在 irq 线程或 ioctl 调用线程里执行 DT dma-coherent(若互连支持);用持久映射(DMA_ATTR_SKIP_CPU_SYNC + 显式局部同步);缓冲区在接入簇处理 arch/arm64/mm/dma-mapping.c:15-31drivers/of/address.c:1000-1010
CMA / 大块分配 GPU/ISP 缓冲、V4L2 REQBUFS 从 CMA 迁移页面 ms 级尖峰,随内存碎片增长 启动期一次性分配并长期持有;cma= 预留足够;避免运行期 REQBUFS/cudaMalloc mm/cma.c:406kernel/dma/contiguous.c:91
SMMU TLB 失效 每次 unmap 严格同步失效,cmdq sync 等待 几 µs–几十 µs/次,高频 map/unmap 叠加 iommu.strict=0 惰性失效;映射长期持有;必要时 iommu.passthrough=1(失去隔离) drivers/iommu/iommu.c:44, 207-208drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c:36-37
GPU/NPU/ISP 驱动 厂商驱动常依赖 spin_lock_irqsave 关中断、hardirq 内分配、忙等 fence RT 下 lockdep 告警、死锁或延迟放大 PROVE_RAW_LOCK_NESTING + RT 内核过一遍驱动;把驱动中断线程锁定在接入簇;不让控制线程调用它们 第 02/06 章规则
相机/ISP 中断 每帧 1–3 个中断 × 8–12 路 = 500–1000 IRQ/s,每个后面跟 DMA 与 V4L2 队列操作 线程化后每中断 +3–6 µs(A78) irq 线程 FIFO 70、亲和接入簇;帧级批处理 第 03 章
激光雷达 / 雷达 UDP 50k–200k pps 小包 NET_RX 线程化 + backlog 线程:pps 上限下降 10%–30% 网卡中断硬件合并;busy_poll;接收线程 FIFO 60 绑接入簇;大包/GRO 第 04 章;net/core/dev.c:11202-11210
TSN 门控 taprio 软件模式 hrtimer 在 RT 下进 softirq 门控抖动几十 µs 硬件 offload(flags 0x2)、etf 硬件 SO_TXTIME net/sched/sch_taprio.c:1953, 2077
安全岛 IPC mailbox 中断线程化 通知延迟 = irq 线程调度延迟 mailbox irq 线程 FIFO ≥ 控制线程 drivers/mailbox/tegra-hsp.c:711, 858drivers/mailbox/omap-mailbox.c:233
热降频 / DVFS thermal governor 降频、SCMI 调频 频率跳变引起周期性能变化 固定频率于热稳定点之下;cpufreq.default_governor=performance + scaling_max_freq 上限 drivers/cpufreq/cpufreq.c:3084
PSCI 深度 idle cluster 级 idle 退出 100–300 µs 控制簇尤其致命 cpuidle.off=1 或逐态 disable;RT 下分层布局本就拿不到 cluster 态 drivers/cpuidle/Kconfig.arm:27-33drivers/firmware/psci/psci.c:469-480
Hypervisor vGIC 注入、WFI/WFE trap、vCPU 被抢占 每次中断 +5–30 µs KVM:kvm-arm.vgic_v4_enable=1 直通 LPI、vCPU 钉物理核、kvm-arm.wfi_trap_policy=notrap;Xen:sched=nullvwfi=native arch/arm64/kvm/vgic/vgic-v3.c:614arch/arm64/kvm/arm.c:2888-2918kernel-parameters.txt:2751-2797
功能安全监控 softlockup/hardlockup、EDAC 轮询、RAS/SDEI 周期性小噪声;nowatchdog 与 FuSa 监控冲突 内核看门狗交给外部 WDT/安全岛;保留 softlockup_panic 语义由安全岛复位 arch/arm64/kernel/watchdog_hld.c:15-35drivers/firmware/Kconfig:31-38
安全缓解 KPTI(A75)、Spectre-BHB(A72–A78) 每次 syscall/中断 +几十–几百 ns 评审后 mitigations=off 或保留 第 01 章
内存带宽争用 GPU/NPU 满载时 CPU 访存延迟翻倍 无 MPAM,内核无法分区 SoC QoS 寄存器 / 固件配置;控制线程数据放 SRAM/L2 常驻 6.12.107 无 MPAM

14.3 CPU 分区样板

样板 A:12 核 A78AE,三簇(Orin 类)

簇 / CPU 角色 内核线程与中断 用户态
簇 0:CPU 0-3 housekeeping 所有非关键中断、内核线程、中间件 irq/*(默认 50)、ksoftirqdrcuc/rcuokworkerpr/legacy;网络/存储/USB/显示中断亲和于此 DDS 发现、日志、诊断、OTA、shell
簇 1:CPU 4-7 接入 + 感知 传感器接入与 GPU/NPU 提交 CSI/ISP、雷达网卡、GPU/NPU 中断亲和于此;rcu_nocbs 覆盖 感知推理线程(FIFO 55)、雷达接收(FIFO 60)
簇 2:CPU 8-11 控制 / 规划(隔离) 硬约束回路 isolcpus=domain,managed_irq + nohz_full + rcu_nocbs;只剩 arch timer / IPI;控制用 CAN/EtherCAT 中断可专门亲和到 CPU 8 控制 100 Hz(FIFO 90,CPU 8)、规划 10 Hz(FIFO 80,CPU 9)、定位/融合(FIFO 75,CPU 10-11)

启动参数:

isolcpus=domain,managed_irq,8-11 nohz_full=8-11 rcu_nocbs=4-11 irqaffinity=0-3 skew_tick=1
cpuidle.off=1 cpufreq.default_governor=performance rcutree.kthread_prio=3
iommu.strict=0 cma=512M nosoftlockup

nowatchdog 视功能安全方案而定;KPTI/mitigations 见 14.5。)

样板 B:8 核 A72 同构(TDA4 类)

CPU 角色
0-1 housekeeping 全部非关键中断与内核线程、中间件、日志
2-5 接入 + 感知 相机/雷达/以太网中断、DSP/NPU(C7x/MMA)完成中断、感知线程
6-7 控制隔离 isolcpus=domain,managed_irq,6-7 nohz_full=6-7 rcu_nocbs=2-7 irqaffinity=0-1;控制 FIFO 90 绑 CPU 6,规划 FIFO 80 绑 CPU 7

A72 无 LSE,rt_mutex 快路径走 LL/SC;KPTI 关闭(kpti_safe_list)但 Spectre-BHB 缓解生效。

样板 C:4 核 A53(S32G / 网关类)

CPU 角色
0 housekeeping 所有中断与内核线程、诊断
1 接入 CAN/以太网中断线程(FIFO 60-70)、路由/网关线程
2-3 控制隔离 isolcpus=domain,managed_irq,2-3 nohz_full=2-3 rcu_nocbs=1-3 irqaffinity=0;控制线程 FIFO 90

A53 频率低、无 LSE、线程切换 3–5 µs,目标放宽到 < 100 µs;硬实时留给 M7 锁步核。

14.4 优先级栅格(三种样板通用)

优先级 对象 依据
99 migration/Nwatchdog/N 内核固定(kernel/sched/core.c:3566
92 控制回路依赖设备的 irq/*(CAN、EtherCAT、安全岛 mailbox) 必须先于控制线程被处理
90 控制线程(100 Hz–1 kHz) 最高业务优先级
80 规划(10 Hz)
75 定位 / 融合
70 CSI/ISP、雷达网卡 irq/* 接入簇最高
65 GPU/NPU 驱动 irq/*
60 napi/*、雷达 UDP 接收线程
55 感知推理线程 被 GPU 提交/等待主导
50 其余 irq/*(默认) kernel/sched/syscalls.c:856-861
3 rcuc/Nrcub/N rcutree.kthread_prio=3
OTHER nice 0 DDS/ROS 2 非关键线程、ksoftirqdkworker
OTHER nice 10 日志、上传、诊断

规则:同一条数据流上游的中断线程优先级 ≥ 下游消费线程;控制簇里除控制设备中断外不允许任何 irq 线程;感知簇的 irq 线程优先级低于控制簇所有线程(它们不在同一簇,但 IPI/迁移场景下仍需保证)。

14.5 参数集(可直接套用后按平台裁剪)

Kconfig(arm64,在厂商 defconfig 上叠加)

CONFIG_EXPERT=y            CONFIG_PREEMPT_RT=y         CONFIG_HZ_1000=y
CONFIG_NO_HZ_FULL=y        CONFIG_RCU_NOCB_CPU=y       CONFIG_HIGH_RES_TIMERS=y
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y            CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
CONFIG_CMA=y  CONFIG_DMA_CMA=y  CONFIG_CMA_SIZE_MBYTES=512(按需)
CONFIG_ARM64_64K_PAGES=y(仅当全部驱动/用户态验证通过;否则 4K)
CONFIG_ARM64_PSEUDO_NMI=y(需要 NMI 看门狗或 perf 精确采样时)
# 关闭
CONFIG_DEBUG_PREEMPT / LOCKDEP / PROVE_LOCKING / KASAN / KCSAN / DEBUG_RT_MUTEXES / ARM64_DEBUG_PRIORITY_MASKING
CONFIG_SLUB_CPU_PARTIAL=n   CONFIG_ARM64_SVE=n(无 SVE 用户时)  CONFIG_ARM64_MTE=n
CONFIG_TRANSPARENT_HUGEPAGE / NUMA_BALANCING(RT 下自动不可选)

启动参数(样板 A)

isolcpus=domain,managed_irq,8-11 nohz_full=8-11 rcu_nocbs=4-11 irqaffinity=0-3 skew_tick=1
cpuidle.off=1 cpufreq.default_governor=performance rcutree.kthread_prio=3
iommu.strict=0 cma=512M nosoftlockup
# 按安全评审决定:
mitigations=auto | mitigations=off | nospectre_bhb
# 仅 A75 等 CSV3=0 的核:kpti=off
# 需要 NMI 看门狗 / perf 时:irqchip.gicv3_pseudo_nmi=1
# 无 SVE 用户:arm64.nosve
# KVM host(Linux 作为 hypervisor):kvm-arm.vgic_v4_enable=1 kvm-arm.wfi_trap_policy=notrap

sysctl(/etc/sysctl.d/90-rt.conf

kernel.sched_rt_runtime_us = -1
kernel.sched_energy_aware = 0
kernel.timer_migration = 0
kernel.hung_task_timeout_secs = 0
kernel.printk = 3 4 1 3
vm.stat_interval = 120
vm.swappiness = 0
vm.compact_unevictable_allowed = 0
net.core.busy_poll = 50
net.core.busy_read = 50
net.core.rmem_max = 67108864
net.core.netdev_max_backlog = 250000

中断亲和与线程优先级(启动脚本)

systemctl disable --now irqbalance
echo 0-3 > /proc/irq/default_smp_affinity
for i in /proc/irq/*/smp_affinity_list; do echo 0-3 > $i 2>/dev/null; done
# 接入设备 → 簇 1
for irq in $(grep -E 'csi|isp|vi|nvcsi|eqos|dwmac|gpu|nvgpu|dla|pva' /proc/interrupts | cut -d: -f1); do echo 4-7 > /proc/irq/$irq/smp_affinity_list; done
# 控制设备 → CPU 8
for irq in $(grep -E 'can|mttcan|flexcan|ecat' /proc/interrupts | cut -d: -f1); do echo 8 > /proc/irq/$irq/smp_affinity_list; done
# 优先级
chrt -f -p 92 $(pgrep -f 'irq/.*-(can|mttcan|flexcan)')
chrt -f -p 70 $(pgrep -f 'irq/.*-(csi|isp|vi)')
chrt -f -p 65 $(pgrep -f 'irq/.*-(gpu|nvgpu|dla|pva)')
chrt -f -p 60 $(pgrep -f 'napi/')
for s in /sys/devices/system/cpu/cpu[4-9]*/cpuidle/state[1-9]*/disable /sys/devices/system/cpu/cpu1[01]/cpuidle/state[1-9]*/disable; do echo 1 > $s 2>/dev/null; done

应用侧

14.6 hypervisor 场景

场景 参数 / 做法 位置
Linux 作 KVM host,RT guest kvm-arm.mode=nvhe|protected 按安全需求;kvm-arm.vgic_v4_enable=1 让 LPI 直接注入 vCPU;kvm-arm.wfi_trap_policy=notrapwfe_trap_policy=notrap 避免 idle 陷入;vCPU 线程 FIFO 并钉在专用物理核;直通传感器设备(VFIO) arch/arm64/kvm/arm.c:2888-2918arch/arm64/kvm/vgic/vgic-v3.c:596-614kernel-parameters.txt:2751-2797
Linux 作 guest(QNX Hypervisor / Xen) guest 内参数同 13.5;宿主侧:vCPU 1:1 钉物理核、sched=null(Xen)、vwfi=native、中断直通、避免 host 侧 vCPU 抢占 宿主文档
安全域与 QM 域分离 控制簇物理核只给 ASIL 域 guest;接入/感知簇给 QM 域

guest 内看到的「hardirq 停留时间」包含 host 的注入延迟,cyclictest 要在 guest 内和 host 内各测一次分辨来源。

14.7 功能安全与看门狗

14.8 验收清单(自动驾驶版)

  1. cyclictest -m -Sp90 -i1000 -h200 -D24h -a8:控制核 24 小时最大值 < 50 µs(A78)/ < 100 µs(A53),且在满负载感知 + 满带宽传感器回放下重复。
  2. 控制回路端到端:从 CAN 帧到达时间戳到指令发出,P99.99 抖动 < 100 µs(用硬件时间戳或 gPTP 对齐)。
  3. 传感器时间戳抖动:相机 frame done → 用户态可见 < 200 µs;雷达 UDP 包到用户态 < 100 µs,丢包 0。
  4. osnoise/timerlat 在控制簇:无 IRQ/softirq/线程噪声;hwlatdetect 24 小时无 > 20 µs 固件停顿。
  5. GPU/NPU 提交延迟分布不因 RT 恶化超过 20%;驱动在 PROVE_RAW_LOCK_NESTING 下无告警。
  6. 热稳定:满负载 30 分钟后频率不降、延迟不漂。

源码定位

主题 位置
DMA 缓存维护 / dma-coherent arch/arm64/mm/dma-mapping.c:15-31drivers/of/address.c:1000-1010
CMA / swiotlb mm/cma.c:406kernel/dma/contiguous.c:91kernel/dma/swiotlb.c:206
SMMU drivers/iommu/iommu.c:44, 207-208drivers/iommu/Kconfig:110-135drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c:36-37
KVM / vGIC arch/arm64/kvm/arm.c:2888-2918arch/arm64/kvm/vgic/vgic-v3.c:596-614
TSN net/sched/sch_taprio.c:1289, 1953, 2077
mailbox drivers/mailbox/tegra-hsp.c:711, 858drivers/mailbox/omap-mailbox.c:233
PSCI / cpuidle / cpufreq drivers/firmware/psci/psci.c:469-480, 736-740drivers/cpuidle/Kconfig.arm:17-44drivers/cpuidle/cpuidle.c:811-818drivers/cpufreq/cpufreq.c:3084
安全缓解 arch/arm64/kernel/cpufeature.c:1737, 1982arch/arm64/kernel/proton-pack.c:90, 413, 829-1034kernel/cpu.c:3230
看门狗 arch/arm64/kernel/watchdog_hld.c:15-35arch/arm64/Kconfig:224-232
MPAM 6.12.107 无

小结