免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 10161 | 回复: 9
打印 上一主题 下一主题

[内核入门] 求教育,关于NMI watchdog [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-01-22 19:29 |只看该作者 |倒序浏览
6可用积分
NMI watchdog到底是称为硬狗还是软狗?

如果是软狗,那么什么时候喂狗呢? 即touch_nmi_watchdog()被调用的时机是怎样的?

如果是硬狗,可是喂硬狗通常都是给一个一定长度的脉冲,不涉及nmi_touch这个percpu变量啊。

请了解的同学不吝赐教,谢谢

论坛徽章:
0
2 [报告]
发表于 2013-01-23 00:49 |只看该作者
nmi watchdog应该是软狗,应该是每次nmi中断的时候喂狗

论坛徽章:
0
3 [报告]
发表于 2013-01-23 08:48 |只看该作者
每次NMI中断来的时候调用nmi_watchdog_tick()是去检测是否喂狗吧,而不是去喂狗,检测到没喂狗就die_nmi()了。回复 2# luoyan_xy


   

论坛徽章:
4
酉鸡
日期:2014-03-21 23:19:50狮子座
日期:2014-08-01 22:11:40酉鸡
日期:2015-01-10 21:31:442015年辞旧岁徽章
日期:2015-03-03 16:54:15
4 [报告]
发表于 2013-01-23 09:24 |只看该作者
有2种:
I/O APIC watchdog开销大
Local APIC watchdog开销小
通过nmi_watchdog变量控制.

原理都是do_nmi()中递增计数器.而在被监控的地方重置计数器.

我的理解,如果不正,请指点,谢谢!

论坛徽章:
0
5 [报告]
发表于 2013-01-24 18:06 |只看该作者
来个大侠回答一下哇

论坛徽章:
0
6 [报告]
发表于 2013-04-13 20:46 |只看该作者
回复 1# nevastill
1. 在hung_task模块初始化时会启动一个内核线程khungtaskd执行watchdog函数
  1. static int __init hung_task_init(void)
  2. {
  3.         atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
  4.         watchdog_task = kthread_run(watchdog, NULL, "khungtaskd");

  5.         return 0;
  6. }

  7. module_init(hung_task_init);
复制代码
2. 在线程khungtaskd中执行check_hung_uninterruptible_tasks
  1. static int watchdog(void *dummy)
  2. {
  3.         set_user_nice(current, 0);

  4.         for ( ; ; ) {
  5.                 unsigned long timeout = sysctl_hung_task_timeout_secs;

  6.                 while (schedule_timeout_interruptible(timeout_jiffies(timeout)))
  7.                         timeout = sysctl_hung_task_timeout_secs;

  8.                 check_hung_uninterruptible_tasks(timeout);
  9.         }

  10.         return 0;
  11. }
复制代码
3. check_hung_uninterruptible_tasks->check_hung_task->touch_nmi_watchdog

  1. static void check_hung_task(struct task_struct *t, unsigned long timeout)
  2. {
  3.         ... ...
  4.         touch_nmi_watchdog();

  5.         if (sysctl_hung_task_panic)
  6.                 panic("hung_task: blocked tasks");
  7. }
复制代码
4. 在touch_nmi_watchdog设置pcpu变量nmi_touch
  1. void touch_nmi_watchdog(void)
  2. {
  3.         if (nmi_watchdog_active()) {
  4.                 unsigned cpu;

  5.                 /*
  6.                  * Tell other CPUs to reset their alert counters. We cannot
  7.                  * do it ourselves because the alert count increase is not
  8.                  * atomic.
  9.                  */
  10.                 for_each_present_cpu(cpu) {
  11.                         if (per_cpu(nmi_touch, cpu) != 1)
  12.                                 per_cpu(nmi_touch, cpu) = 1;
  13.                 }
  14.         }

  15.         /*
  16.          * Tickle the softlockup detector too:
  17.          */
  18.         touch_softlockup_watchdog();
  19. }
复制代码
5. 在nmi中断处理do_nmi进行nmi_touch变量的检查,如果不为1,则计数加1,计数超过预设值,则调用die_nmi
代码流程:entry_32.s->call do_nmi->default_do_nmi->nmi_watchdog_tick

  1. notrace __kprobes int
  2. nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
  3. {
  4.         ... ...
  5.         if (__get_cpu_var(nmi_touch)) { /*进行pcpu变量touched的检查,如果为1,则置touched标志*/
  6.                 __get_cpu_var(nmi_touch) = 0;
  7.                 touched = 1;
  8.         }

  9.         ... ...
  10.         /* 下面对touch标志进行判断,如果为0且nmi中断处理没有多次进入,则将altert_counter加1 */

  11.         /* if the none of the timers isn't firing, this cpu isn't doing much */
  12.         if (!touched && __get_cpu_var(last_irq_sum) == sum) {
  13.                 /*
  14.                  * Ayiee, looks like this CPU is stuck ...
  15.                  * wait a few IRQs (5 seconds) before doing the oops ...
  16.                  */
  17.                 __this_cpu_inc(alert_counter);
  18.                 if (__this_cpu_read(alert_counter) == 5 * nmi_hz)
  19.                         /*
  20.                          * die_nmi will return ONLY if NOTIFY_STOP happens..
  21.                          */
  22.                         die_nmi("BUG: NMI Watchdog detected LOCKUP",
  23.                                 regs, panic_on_timeout);
  24.         } else {
  25.                 /* 不然就更新中断计数,对alert_counter进行清零操作 */
  26.                 __get_cpu_var(last_irq_sum) = sum;
  27.                 __this_cpu_write(alert_counter, 0);
  28.         }

  29.         /* see if the nmi watchdog went off */
  30.         if (!__get_cpu_var(wd_enabled))
  31.                 return rc;
  32.         switch (nmi_watchdog) {
  33.         case NMI_LOCAL_APIC:
  34.                 /* 如果是APIC类型的watch_dog,调如下函数进行喂狗 */
  35.                 rc |= lapic_wd_event(nmi_hz);
  36.                 break;
  37.         case NMI_IO_APIC:
  38.                 /*
  39.                  * don't know how to accurately check for this.
  40.                  * just assume it was a watchdog timer interrupt
  41.                  * This matches the old behaviour.
  42.                  */
  43.                 rc = 1;
  44.                 break;
  45.         }
  46.         return rc;
  47. }
复制代码
6. APIC类型的watch_dog喂狗函数
  1. int __kprobes lapic_wd_event(unsigned nmi_hz)
  2. {
  3.         struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
  4.         u64 ctr;

  5.         rdmsrl(wd->perfctr_msr, ctr);
  6.         if (ctr & wd_ops->checkbit) /* perfctr still running? */
  7.                 return 0;

  8.         wd_ops->rearm(wd, nmi_hz);
  9.         return 1;
  10. }
  11. static struct wd_ops intel_arch_wd_ops __read_mostly = {
  12.         .reserve        = single_msr_reserve,
  13.         .unreserve        = single_msr_unreserve,
  14.         .setup                = setup_intel_arch_watchdog,
  15.         .rearm                = p6_rearm,
  16.         .stop                = single_msr_stop_watchdog,
  17.         .perfctr        = MSR_ARCH_PERFMON_PERFCTR1,
  18.         .evntsel        = MSR_ARCH_PERFMON_EVENTSEL1,
  19. };
  20. static void __kprobes p6_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
  21. {
  22.         /*
  23.          * P6 based Pentium M need to re-unmask
  24.          * the apic vector but it doesn't hurt
  25.          * other P6 variant.
  26.          * ArchPerfom/Core Duo also needs this
  27.          */
  28.         apic_write(APIC_LVTPC, APIC_DM_NMI);

  29.         /* P6/ARCH_PERFMON has 32 bit counter write */
  30.         write_watchdog_counter32(wd->perfctr_msr, NULL, nmi_hz);
  31. }
复制代码

论坛徽章:
0
7 [报告]
发表于 2013-08-22 18:55 |只看该作者

RE: 求教育,关于NMI watchdog

junnyg 发表于 2013-04-13 20:46
回复 1# nevastill
1. 在hung_task模块初始化时会启动一个内核线程khungtaskd执行watchdog函数2. 在线程k ...

ls讲的很好很详细,我有一些疑问,想进一步问一下:
1,ls的前5步,我试概括为内核线程软喂狗部分与do_nmi中对喂狗结果的检查;(因我的内核版本为3.6.11,很多函数已经变化,可能理解有误)
——能否请ls将第6步apic详细再讲一下?
2,ULK3中对nmi_watchdog的讲解我有两处想请教:
a,每个cpu上周期性的nmi中断,是固定会产生?还是与nmi_watchdog配置相关呢?若固定产生又与中断一章中对于nmi的描述相冲突:用于危机事件时才引起非屏蔽中断。
b,do_nmi中是对cpu的apic_timer_irqs字段进行检查用以判断cpu是否被锁死;我理解的话,也就是将在特定cpu时钟周期内此数值的是否增加,作为是否已喂狗的判断。这样,是否与ls所说的线程喂狗依据重合了呢?
3,另,查看内核文档,lockup_watchdog.txt中的描述,提到了“The soft and hard lockup detectors are built on top of the hrtimer and perf subsystems”,此处提到nmi狗是基于高精度和性能子系统的,不太明白。。

论坛徽章:
0
8 [报告]
发表于 2013-08-23 15:02 |只看该作者
nmi_watchdog与nmi中断的一些源码与文档分析总结,并请大牛点拨疑问
http://bbs.chinaunix.net/forum.p ... mp;fromuid=28788494

LZ可以看看答得对不对。

论坛徽章:
0
9 [报告]
发表于 2013-08-23 20:59 |只看该作者
软狗喂狗不仅限于上中断等情况,狗的作用是检查长时间没有调度,中断,软中断,关中断的进程上下文都可以喂狗,前提是你的关中断进程上下文是一个你预期的合理的关中断长时间占用cpu的动作,否则狗不喂就是问题



硬狗也是要喂的,他的作用是检查处理器是否在正常运行,否则狗叫重启
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP