当前位置:   article > 正文

请记住内核中这个勤劳的监测卫士---Watchdog(Hard lockup篇)_watchdog detected hard lockup on cpu 21

watchdog detected hard lockup on cpu 21

​更多内核安全、eBPF分析和实践文章,请关注博客和公众号:

CSDN博客:内核功守道
公众号: 内核功守道

背景

接上篇文章:请记住内核中这个勤劳的监测卫士—Watchdog(Soft lockup篇),本篇详细分析Hard lockup流程和原理,并给出此类问题分析经验,供大家参考。

我们知道,hardware watchdog是Soc内的一个内部外设,是一个硬件模块,常说的watchdog driver指的就是该硬件。Hard lockup比soft lockup更加严重,CPU不仅无法调度其它进程,而且不能响应中断。在开启soft lockup时,已经给每个CPU启动了一个hrtimer定时器,在定时器中断处理函数watchdog_timer_fn中更新hrtimer_interrupts变量。

检测hard lockup的原理是:

  • 在CPU0的watchdog_timer_fn函数中检测CPU1的hrtimer_interrupts变量是否更新过;
  • 若没更新,意味着CPU1不能响应中断,出现了hard lockup(CPU1检测CPU2、CPU2检测CPU3、CPU3检测CPU0);
  • 在驱动中加入以下代码可触发hard lockup
static spinlock_t spinlock;
unsigned long flags;
spin_lock_init(&spinlock);

spin_lock_irqsave(&spinlock, flags);
while (1);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 在上述代码中,本地抢占和本地中断被关闭,该CPU的普通中断无法被响应(包括hrtimer定时器中断),线程也无法调度。在这种情况下,[watchdog/x]线程无法工作,hrtimer中断也无法被响应,就会出现hard lockup。

Hard lockup源码分析

1、hrtimer中断处理函数

watchdog_timer_fn()
{
/* hrtimer_interrupts++ */
	watchdog_interrupt_count();
	/* test for hardlockups on the next cpu */
	watchdog_check_hardlockup_other_cpu();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2、Hard lockup检测函数

void watchdog_check_hardlockup_other_cpu(void)
{
	unsigned int next_cpu;

	/* hrtimer的中断4s触发一次,“%3”表示经过3个周期*,即每隔12s检测一下是否 */
	/* hard lockup*/
	if (__this_cpu_read(hrtimer_interrupts) % 3 != 0)
		return;
		/* 得到下一颗CPU */
	next_cpu = watchdog_next_cpu(smp_processor_id());
	if (is_hardlockup_other_cpu(next_cpu)) {
		if (hardlockup_panic)//是否panic
			panic("Watchdog detected hard LOCKUP on cpu %u", next_cpu);
		else
			WARN(1, "Watchdog detected hard LOCKUP on cpu %u", next_cpu);
       per_cpu(hard_watchdog_warn, next_cpu) = true;
	} else {
		per_cpu(hard_watchdog_warn, next_cpu) = false;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

3、Hard lockup判断函数

static int is_hardlockup_other_cpu(unsigned int cpu)
{
	unsigned long hrint = per_cpu(hrtimer_interrupts, cpu);
	/* 如果相等,说明hrtimer中断函数没有执行,出现hard lockup */
	if (per_cpu(hrtimer_interrupts_saved, cpu) == hrint)
		return 1;
	/* 保存最新的hrtimer_interrupts变量值 */
	per_cpu(hrtimer_interrupts_saved, cpu) = hrint;
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

内核配置

  • 开启hard lockup(默认为y)
HARDLOCKUP_DETECTOR_OTHER_CPU
  • 1
  • 是否需要panic(默认为n)
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC
  • 1
  • 在应用层做以下设置也可以触发:
echo 1 > /proc/sys/kernel/hardlockup_panic
  • 1

问题分析思路

Soft lockup用于检测CPU调度是否正常,而Hard lockup主要用于检测CPU中断响应是否正常。内核调度以及中断响应的正常与否,和死锁有很深入的关系,也可以是说是检测系统死锁的一种机制。

  • 某个中断服务函数长时间运行;
  • 关中断时间过长,譬如使用spin_lock_irqsave()函数关闭中断之后,太久没释放;

遇到此类问题,最有效的方法就是使用Trace32或者ARM DS5这类的在线调试器,查看出现异常卡死的位置或者哪个模块最近一次关了中断没有释放,进一步分析可疑点。

总结

以上两篇详细分析了Soft lockup和Hard lockup流程,并介绍了问题解决思路。可以看到不管是Soft lockup还是Hard lockup,都是从内核态的角度来分析死锁的情况,这也是很多内核工程师经常会遇到的问题。

尽管内核watchdog能检测softlockup 和 hardlockup 并采取相应的措施,但并非所有的系统宕机都是因为内核线程lockup引起的。用户线程/进程一样有可能引发系统宕机的情况。比如,用户程序有可能占着临界资源无法释放或系统太忙(疲于响应各种中断),导致无法调度其他用户进程(此时watchdog内核线程不受影响),这也可能导致系统无法正常使用。

后续会详细分析Android场景下的用户态Watchdog以及具体案例,敬请期待。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/316184
推荐阅读
相关标签
  

闽ICP备14008679号