1.概述
征程 6X SoC 中有 2 路 watchdog,使用 wdt0(监控 linux irq),wdt1(监控 linux 优先级为 50 的 rt kthread):
- wdt0 超时是 linux 下有核上的 irq 响应不及时。
- wdt1 超时是 linux 下有核上对优先级为 50 的 rt kthread 调度不及时。
2. 通用方法
watchdog 问题是 wdt 硬件检测触发再由 MCU 域完成重启,对 Main 域软件是无感的,属于非安全下电,此时的文件系统&flash 及 ddr&cache 都存在一致性问题,导致拿到的 ramdump 和转储的 log 文件都是不可靠的,只有 pstore 申请的是 UNCACHE 的地址空间,不存在一致性问题,所以在当前的软件系统中,我们只能依赖 pstore 存储的信息进行分析。
2.1. wdt0
- wdt0 的逻辑是在中断(NO_THREAD)中触发喂狗,通过 IPI 中断在所有核上调用喂狗的软件逻辑,在确认所有 core 都正常执行完 IPI 的回调后,完成喂狗,进入到下一个喂狗周期。
- 当前系统软件中 wdt0 的喂狗周期为 161ms。
- wdt0 的所有检测是基于中断的,任何一个核出现长时间关闭中断的情况就会出现此类问题,除此之外中断风暴也可能会导致 wdt 中断无法被及时响应。
- 在 wdt0 超时时,会触发一个 gic 中断,gic 中断会使用 NMI 将所有 cpu 的调用栈打印,但存在可能性打栈中断发送给了关中断的 CPU,导致无法收到打栈中断,进而无法获取有效调试信息。
2.2. wdt1
- wdt1 的逻辑是在优先级为 50 的 rt kthread 喂狗线程中触发喂狗,通过 IPI 中断在所有核上调用喂狗的软件逻辑,在确认所有 core 都正常执行完 IPI 的回调,调用自己核上的喂狗线程后,完成喂狗,进入到下一个喂狗周期。
- 当前系统软件中 wdt1 的喂狗周期为 5162ms。
- 当优先级大于等于 50 的 rt kthread 无法被及时调度时就会出现此类问题。
- 在 wdt1 超时时,会触发一个 gic 中断,gic 中断会使用 NMI 将所有 cpu 的调用栈打印。
3. 典型问题
3.1. wdt0 示例
193.115079\] irq hang test. \[ 193.386089\] watchdog watchdog0: cpu11 watchdog0 comes to the second timeout \[ 193.386096\] NMI backtrace for cpu 11 \[ 193.386098\] CPU: 11 PID: 0 Comm: swapper/11 Tainted: P O 6.1.134-rt51-04836-g0b3e5cbe5431 #13 \[ 193.386101\] Hardware name: Horizon AI Technologies, Inc. HOBOT Sigi-P Matrix (DT) \[ 193.386103\] Call trace: ... ... \[ 193.386603\] NMI backtrace for cpu 6 \[ 193.386604\] CPU: 6 PID: 2499 Comm: insmod Tainted: P O 6.1.134-rt51-04836-g0b3e5cbe5431 #13 \[ 193.386607\] Hardware name: Horizon AI Technologies, Inc. HOBOT Sigi-P Matrix (DT) \[ 193.386608\] pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) \[ 193.386610\] pc : __delay+0x70/0x110 \[ 193.386614\] lr : __delay+0x78/0x110 \[ 193.386615\] sp : ffff80004546fab0 \[ 193.386616\] pmr_save: 000000a0 \[ 193.386617\] x29: ffff80004546fab0 x28: ffff80004546fce0 x27: ffff80004546fc90 \[ 193.386620\] x26: ffff800009d96340 x25: ffff800005340058 x24: 0000000000000000 \[ 193.386622\] x23: ffff80004546fdb8 x22: fffffffe1a585daa x21: 00000001e5a7b1f6 \[ 193.386624\] x20: ffff80000900cb50 x19: 0000000000009c40 x18: 0000000000000000 \[ 193.386625\] x17: 0000000000000000 x16: 0000000000000000 x15: 0000aaaad8cd02a0 \[ 193.386627\] x14: 5400160b13131717 x13: 0a2e747365742067 x12: 6e61682071726936 \[ 193.386629\] x11: ffffffffffe00000 x10: ffff0047fb2c0500 x9 : ffff800008b593cc \[ 193.386631\] x8 : ffff80004546faf0 x7 : 2e7473657420676e x6 : 00000000ffff1181 \[ 193.386633\] x5 : ffff0047fb232a98 x4 : ffff80004546f910 x3 : 0000000000000000 \[ 193.386635\] x2 : 0000000000000006 x1 : ffff80004546fab0 x0 : 0000000000001e88 \[ 193.386637\] Call trace: \[ 193.386637\] __delay+0x70/0x110 \[ 193.386639\] __const_udelay+0x2c/0x40 \[ 193.386640\] lock_irq_test_init+0x78/0xffec \[lock_irq_test\] \[ 193.386647\] do_one_initcall+0x60/0x2f0 \[ 193.386649\] do_init_module+0x50/0x1f4 \[ 193.386652\] load_module+0x1b80/0x2044 \[ 193.386654\] __do_sys_finit_module+0xac/0x130 \[ 193.386655\] __arm64_sys_finit_module+0x28/0x34 \[ 193.386657\] invoke_syscall+0x50/0x120 \[ 193.386660\] el0_svc_common.constprop.0+0x58/0x190 \[ 193.386662\] do_el0_svc+0x2c/0xa0 \[ 193.386665\] el0_svc+0x28/0xb0 \[ 193.386666\] el0t_64_sync_handler+0xf4/0x120 \[ 193.386668\] el0t_64_sync+0x19c/0x1a0 这是一个触发 wdt0 超时的的测试程序,log 可以看到在系统在 wdt0 超时后输出了打栈信息,从 calltrace 可以看到 core6 的栈非常可疑,通过检查代码可以在 udelay 前是有关闭中断的。 ```Plain static int lock_irq_test_init(void) { while(loop--) { local_irq_disable(); mdelay(timer_expire); local_irq_enable(); msleep(get_random_u32()%timer_expire+ 1); } return 0; } ``` ### 3.2. wdt1 示例 \[ 187.172029\] kthread hang test. \[ 189.056672\] sched: RT throttling activated \[ 194.749281\] watchdog watchdog1: watchdog1 in kick kthread find not empty, cpu map of not feeding dog in hex: 00001 \[ 194.749306\] watchdog watchdog1: cpu12 watchdog1 comes to the second timeout ... ... \[ 194.749412\] NMI backtrace for cpu 0 \[ 194.749416\] CPU: 0 PID: 1876 Comm: hang-test Tainted: P O 6.1.134-rt51-04836-g0b3e5cbe5431 #13 \[ 194.749419\] Hardware name: Horizon AI Technologies, Inc. HOBOT Sigi-P Matrix (DT) \[ 194.749420\] pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) \[ 194.749423\] pc : __delay+0x70/0x110 \[ 194.749429\] lr : __delay+0x78/0x110 \[ 194.749430\] sp : ffff8000448efdf0 \[ 194.749431\] pmr_save: 000000e0 \[ 194.749432\] x29: ffff8000448efdf0 x28: 0000000000000000 x27: 0000000000000000 \[ 194.749435\] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000 \[ 194.749438\] x23: ffff800000c90014 x22: fffffffe171551bb x21: 00000001e8eabde5 \[ 194.749440\] x20: ffff80000900cb50 x19: 0000000000009c40 x18: 0000000000000014 \[ 194.749442\] x17: ffff800008147f68 x16: ffff0042d1252080 x15: 0000000000000040 \[ 194.749444\] x14: ffff800009687648 x13: 0000000078780000 x12: 0000002b94537653 \[ 194.749446\] x11: 0000005200000754 x10: 07519710306882f6 x9 : ffff800008b593cc \[ 194.749449\] x8 : 0000000000000000 x7 : ffff004282223480 x6 : 00000000ffffffff \[ 194.749451\] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 \[ 194.749453\] x2 : 0000000000000000 x1 : ffff8000448efdf0 x0 : 0000000000007c7e \[ 194.749455\] Call trace: \[ 194.749456\] __delay+0x70/0x110 \[ 194.749457\] __const_udelay+0x2c/0x40 \[ 194.749459\] kthread_fn+0xb4/0xe8 \[lock_kthread_test\] \[ 194.749467\] kthread+0x138/0x140 \[ 194.749469\] ret_from_fork+0x10/0x20 这是一个触发 wdt1 超时的的测试程序,log 可以看到在系统在 WDT1 超时后输出了打栈信息,从 calltrace 可以看到 core0 的栈非常可疑,通过检查代码可以在 udelay 前是有关闭中断的。 ```Plain static int kthread_fn(void *data) { struct sched_param param = {.sched_priority = MAX_RT_PRIO-50}; (void)sched_setscheduler(current, SCHED_FIFO, ¶m); while(!kthread_should_stop()) { while(loop) { mdelay(timer_expire); pr_info("kthread hang test. %ld\n", --loop); } } ```