使用 Coresight 进行内核崩溃和看门狗复位

简介

本文档介绍了如何使用 Linux coresight 跟踪支持来调试内核崩溃和看门狗复位场景。

内核崩溃期间的 Coresight 跟踪

从 coresight 驱动程序的角度来看,处理内核崩溃情况有四个主要要求。

  1. 支持从保留内存区域分配跟踪缓冲区页面。平台可以使用添加到相关 coresight 节点的新设备树属性来公布此功能。

  2. 支持在崩溃时停止 coresight 块

  3. 以指定格式保存所需的元数据

  4. 支持读取崩溃时捕获的跟踪数据

从保留 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 读取。此设备文件仅在有有效的崩溃数据可用时创建。

内核崩溃时跟踪捕获和解码的一般流程

  1. 使用 sysfs 接口在所有核心上启用源和接收器。ETR 接收器应通过从 sysfs 中选择“resrv”缓冲区模式,从保留内存中分配跟踪缓冲区。

  2. 运行相关测试。

  3. 在内核崩溃时,所有 coresight 块都被禁用,必要的元数据由内核崩溃处理程序同步。

    系统最终将重新启动或启动 crashdump 内核。

  4. 对于支持 crashdump 内核的平台,可以使用 coresight sysfs 接口从 crashdump 内核本身转储原始跟踪数据。在这种情况下,不需要持久 RAM。

  5. 对于支持持久 RAM 的平台,可以在随后的 Linux 启动中,使用 coresight sysfs 接口转储跟踪数据。在这种情况下,不需要 crashdump 内核。持久 RAM 确保跟踪数据在重启后保持完整。

看门狗复位期间的 Coresight 跟踪

处理看门狗复位和内核崩溃情况的主要区别如下:

  1. Coresight 元数据的保存需要由 SCP(系统控制处理器)固件以指定格式处理,而不是内核。

  2. 固件为跟踪缓冲区和元数据提供的保留内存区域必须在持久 RAM 中。注意:这是看门狗复位情况的要求,但在内核崩溃情况下是可选的。

看门狗复位只能在满足上述两个要求的平台上支持。

使用 ETR 接收器测试内核崩溃情况的示例命令

  1. 启动 Linux 内核,并在内核启动参数中添加“crash_kexec_post_notifiers”。如果用户想从 crashdump 内核中读取跟踪数据,这是强制性的。

  2. 启用预加载的 ETM 配置

    #echo 1 > /sys/kernel/config/cs-syscfg/configurations/panicstop/enable
    
  3. 使用 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 特定的,因此上述脚本仅供参考。

  1. 为 ETR 缓冲区选择保留缓冲区模式

    #echo "resrv" > /sys/bus/coresight/devices/tmc_etr0/buf_mode_preferred
    
  2. 启用刷新触发器停止配置

    #echo 1 > /sys/bus/coresight/devices/tmc_etr0/stop_on_flush
    
  3. 使用 sysfs 接口在核心 1 和 2 上启动 Coresight 跟踪

  4. 在核心 1 上运行一些应用程序

    #taskset -c 1 dd if=/dev/urandom of=/dev/null &
    
  5. 在核心 2 上调用内核崩溃

    #echo 1 > /proc/sys/kernel/panic
    #taskset -c 2 echo c > /proc/sysrq-trigger
    
  6. 从重启的内核或 crashdump 内核中读取崩溃数据

    #dd if=/dev/crash_tmc_etr0 of=/trace/cstrace.bin
    
  7. 运行 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 的方法可用于在内核崩溃重启后检索和解码跟踪数据。