使用 Coresight 进行内核崩溃和看门狗复位¶
简介¶
本文档介绍了如何使用 Linux coresight 跟踪支持来调试内核崩溃和看门狗复位场景。
内核崩溃期间的 Coresight 跟踪¶
从 coresight 驱动程序的角度来看,处理内核崩溃情况有四个主要要求。
支持从保留内存区域分配跟踪缓冲区页面。平台可以使用添加到相关 coresight 节点的新设备树属性来公布此功能。
支持在崩溃时停止 coresight 块
以指定格式保存所需的元数据
支持读取崩溃时捕获的跟踪数据
从保留 RAM 分配跟踪缓冲区页面¶
一个新的可选设备树属性“memory-region”已添加到 Coresight TMC 设备节点,该属性将提供跟踪缓冲区的基地址和大小。
跟踪缓冲区的静态分配将确保同时处理 IOMMU 启用和禁用情况。此外,支持持久 RAM 的平台将允许用户在后续启动中无需启动 crashdump 内核即可读取跟踪数据。
注意:对于 ETR 接收设备,此保留区域将用于跟踪捕获和跟踪数据检索。对于 ETF 接收设备,内部 SRAM 将用于跟踪捕获,它们将被同步到保留区域进行检索。
在崩溃时禁用 Coresight 块¶
为了避免内核崩溃后丢失相关跟踪数据的情况,最好在崩溃时停止 coresight 块。
这可以通过如下配置比较器、CTI 和接收设备来实现
Trigger on panic
Comparator --->External out --->CTI -->External In---->ETR/ETF stop
在内核崩溃时保存元数据¶
Coresight 元数据除了跟踪数据之外,还包含成功解码跟踪所需的所有附加数据。这包括 ETR/ETF/ETB 寄存器快照等。
一个新的可选设备属性“memory-region”已添加到 ETR/ETF/ETB 设备节点中,用于此目的。
读取崩溃时捕获的跟踪数据¶
在崩溃时捕获的跟踪数据,可以从重启的内核或 crashdump 内核中通过特殊的设备文件 /dev/crash_tmc_xxx 读取。此设备文件仅在有有效的崩溃数据可用时创建。
内核崩溃时跟踪捕获和解码的一般流程¶
使用 sysfs 接口在所有核心上启用源和接收器。ETR 接收器应通过从 sysfs 中选择“resrv”缓冲区模式,从保留内存中分配跟踪缓冲区。
运行相关测试。
在内核崩溃时,所有 coresight 块都被禁用,必要的元数据由内核崩溃处理程序同步。
系统最终将重新启动或启动 crashdump 内核。
对于支持 crashdump 内核的平台,可以使用 coresight sysfs 接口从 crashdump 内核本身转储原始跟踪数据。在这种情况下,不需要持久 RAM。
对于支持持久 RAM 的平台,可以在随后的 Linux 启动中,使用 coresight sysfs 接口转储跟踪数据。在这种情况下,不需要 crashdump 内核。持久 RAM 确保跟踪数据在重启后保持完整。
看门狗复位期间的 Coresight 跟踪¶
处理看门狗复位和内核崩溃情况的主要区别如下:
Coresight 元数据的保存需要由 SCP(系统控制处理器)固件以指定格式处理,而不是内核。
固件为跟踪缓冲区和元数据提供的保留内存区域必须在持久 RAM 中。注意:这是看门狗复位情况的要求,但在内核崩溃情况下是可选的。
看门狗复位只能在满足上述两个要求的平台上支持。
使用 ETR 接收器测试内核崩溃情况的示例命令¶
启动 Linux 内核,并在内核启动参数中添加“crash_kexec_post_notifiers”。如果用户想从 crashdump 内核中读取跟踪数据,这是强制性的。
启用预加载的 ETM 配置
#echo 1 > /sys/kernel/config/cs-syscfg/configurations/panicstop/enable
使用 sysfs 接口配置 CTI
#./cti_setup.sh #cat cti_setup.sh cd /sys/bus/coresight/devices/ ap_cti_config () { #ETM trig out[0] trigger to Channel 0 echo 0 4 > channels/trigin_attach } etf_cti_config () { #ETF Flush in trigger from Channel 0 echo 0 1 > channels/trigout_attach echo 1 > channels/trig_filter_enable } etr_cti_config () { #ETR Flush in from Channel 0 echo 0 1 > channels/trigout_attach echo 1 > channels/trig_filter_enable } ctidevs=`find . -name "cti*"` for i in $ctidevs do cd $i connection=`find . -name "ete*"` if [ ! -z "$connection" ] then echo "AP CTI config for $i" ap_cti_config fi connection=`find . -name "tmc_etf*"` if [ ! -z "$connection" ] then echo "ETF CTI config for $i" etf_cti_config fi connection=`find . -name "tmc_etr*"` if [ ! -z "$connection" ] then echo "ETR CTI config for $i" etr_cti_config fi cd .. done
注意:CTI 连接是 SOC 特定的,因此上述脚本仅供参考。
为 ETR 缓冲区选择保留缓冲区模式
#echo "resrv" > /sys/bus/coresight/devices/tmc_etr0/buf_mode_preferred
启用刷新触发器停止配置
#echo 1 > /sys/bus/coresight/devices/tmc_etr0/stop_on_flush
使用 sysfs 接口在核心 1 和 2 上启动 Coresight 跟踪
在核心 1 上运行一些应用程序
#taskset -c 1 dd if=/dev/urandom of=/dev/null &
在核心 2 上调用内核崩溃
#echo 1 > /proc/sys/kernel/panic #taskset -c 2 echo c > /proc/sysrq-trigger
从重启的内核或 crashdump 内核中读取崩溃数据
#dd if=/dev/crash_tmc_etr0 of=/trace/cstrace.bin
运行 opencsd 解码器工具/脚本以生成指令跟踪。
指令跟踪转储示例¶
核心 1 转储
A etm4_enable_hw: ffff800008ae1dd4
CONTEXT EL2 etm4_enable_hw: ffff800008ae1dd4
I etm4_enable_hw: ffff800008ae1dd4:
d503201f nop
I etm4_enable_hw: ffff800008ae1dd8:
d503201f nop
I etm4_enable_hw: ffff800008ae1ddc:
d503201f nop
I etm4_enable_hw: ffff800008ae1de0:
d503201f nop
I etm4_enable_hw: ffff800008ae1de4:
d503201f nop
I etm4_enable_hw: ffff800008ae1de8:
d503233f paciasp
I etm4_enable_hw: ffff800008ae1dec:
a9be7bfd stp x29, x30, [sp, #-32]!
I etm4_enable_hw: ffff800008ae1df0:
910003fd mov x29, sp
I etm4_enable_hw: ffff800008ae1df4:
a90153f3 stp x19, x20, [sp, #16]
I etm4_enable_hw: ffff800008ae1df8:
2a0003f4 mov w20, w0
I etm4_enable_hw: ffff800008ae1dfc:
900085b3 adrp x19, ffff800009b95000 <reserved_mem+0xc48>
I etm4_enable_hw: ffff800008ae1e00:
910f4273 add x19, x19, #0x3d0
I etm4_enable_hw: ffff800008ae1e04:
f8747a60 ldr x0, [x19, x20, lsl #3]
E etm4_enable_hw: ffff800008ae1e08:
b4000140 cbz x0, ffff800008ae1e30 <etm4_starting_cpu+0x50>
I 149.039572921 etm4_enable_hw: ffff800008ae1e30:
a94153f3 ldp x19, x20, [sp, #16]
I 149.039572921 etm4_enable_hw: ffff800008ae1e34:
52800000 mov w0, #0x0 // #0
I 149.039572921 etm4_enable_hw: ffff800008ae1e38:
a8c27bfd ldp x29, x30, [sp], #32
..snip
149.052324811 chacha_block_generic: ffff800008642d80:
9100a3e0 add x0,
I 149.052324811 chacha_block_generic: ffff800008642d84:
b86178a2 ldr w2, [x5, x1, lsl #2]
I 149.052324811 chacha_block_generic: ffff800008642d88:
8b010803 add x3, x0, x1, lsl #2
I 149.052324811 chacha_block_generic: ffff800008642d8c:
b85fc063 ldur w3, [x3, #-4]
I 149.052324811 chacha_block_generic: ffff800008642d90:
0b030042 add w2, w2, w3
I 149.052324811 chacha_block_generic: ffff800008642d94:
b8217882 str w2, [x4, x1, lsl #2]
I 149.052324811 chacha_block_generic: ffff800008642d98:
91000421 add x1, x1, #0x1
I 149.052324811 chacha_block_generic: ffff800008642d9c:
f100443f cmp x1, #0x11
核心 2 转储
A etm4_enable_hw: ffff800008ae1dd4
CONTEXT EL2 etm4_enable_hw: ffff800008ae1dd4
I etm4_enable_hw: ffff800008ae1dd4:
d503201f nop
I etm4_enable_hw: ffff800008ae1dd8:
d503201f nop
I etm4_enable_hw: ffff800008ae1ddc:
d503201f nop
I etm4_enable_hw: ffff800008ae1de0:
d503201f nop
I etm4_enable_hw: ffff800008ae1de4:
d503201f nop
I etm4_enable_hw: ffff800008ae1de8:
d503233f paciasp
I etm4_enable_hw: ffff800008ae1dec:
a9be7bfd stp x29, x30, [sp, #-32]!
I etm4_enable_hw: ffff800008ae1df0:
910003fd mov x29, sp
I etm4_enable_hw: ffff800008ae1df4:
a90153f3 stp x19, x20, [sp, #16]
I etm4_enable_hw: ffff800008ae1df8:
2a0003f4 mov w20, w0
I etm4_enable_hw: ffff800008ae1dfc:
900085b3 adrp x19, ffff800009b95000 <reserved_mem+0xc48>
I etm4_enable_hw: ffff800008ae1e00:
910f4273 add x19, x19, #0x3d0
I etm4_enable_hw: ffff800008ae1e04:
f8747a60 ldr x0, [x19, x20, lsl #3]
E etm4_enable_hw: ffff800008ae1e08:
b4000140 cbz x0, ffff800008ae1e30 <etm4_starting_cpu+0x50>
I 149.046243445 etm4_enable_hw: ffff800008ae1e30:
a94153f3 ldp x19, x20, [sp, #16]
I 149.046243445 etm4_enable_hw: ffff800008ae1e34:
52800000 mov w0, #0x0 // #0
I 149.046243445 etm4_enable_hw: ffff800008ae1e38:
a8c27bfd ldp x29, x30, [sp], #32
I 149.046243445 etm4_enable_hw: ffff800008ae1e3c:
d50323bf autiasp
E 149.046243445 etm4_enable_hw: ffff800008ae1e40:
d65f03c0 ret
A ete_sysreg_write: ffff800008adfa18
..snip
I 149.05422547 panic: ffff800008096300:
a90363f7 stp x23, x24, [sp, #48]
I 149.05422547 panic: ffff800008096304:
6b00003f cmp w1, w0
I 149.05422547 panic: ffff800008096308:
3a411804 ccmn w0, #0x1, #0x4, ne // ne = any
N 149.05422547 panic: ffff80000809630c:
540001e0 b.eq ffff800008096348 <panic+0xe0> // b.none
I 149.05422547 panic: ffff800008096310:
f90023f9 str x25, [sp, #64]
E 149.05422547 panic: ffff800008096314:
97fe44ef bl ffff8000080276d0 <panic_smp_self_stop>
A panic: ffff80000809634c
I 149.05422547 panic: ffff80000809634c:
910102d5 add x21, x22, #0x40
I 149.05422547 panic: ffff800008096350:
52800020 mov w0, #0x1 // #1
E 149.05422547 panic: ffff800008096354:
94166b8b bl ffff800008631180 <bust_spinlocks>
N 149.054225518 bust_spinlocks: ffff800008631180:
340000c0 cbz w0, ffff800008631198 <bust_spinlocks+0x18>
I 149.054225518 bust_spinlocks: ffff800008631184:
f000a321 adrp x1, ffff800009a98000 <pbufs.0+0xbb8>
I 149.054225518 bust_spinlocks: ffff800008631188:
b9405c20 ldr w0, [x1, #92]
I 149.054225518 bust_spinlocks: ffff80000863118c:
11000400 add w0, w0, #0x1
I 149.054225518 bust_spinlocks: ffff800008631190:
b9005c20 str w0, [x1, #92]
E 149.054225518 bust_spinlocks: ffff800008631194:
d65f03c0 ret
A panic: ffff800008096358
基于 Perf 的测试¶
启动 perf 会话¶
ETF
perf record -e cs_etm/panicstop,@tmc_etf1/ -C 1
perf record -e cs_etm/panicstop,@tmc_etf2/ -C 2
ETR
perf record -e cs_etm/panicstop,@tmc_etr0/ -C 1,2
崩溃后读取跟踪数据¶
上述解释的基于 sysfs 的方法可用于在内核崩溃重启后检索和解码跟踪数据。