// 使能hard lockup探测
// 调用路径:watchdog_enable->watchdog_nmi_enable
// 函数任务:
// 1.初始化hard lockup检测事件
// 2.hard lockup阈值为10s
// 2.向performance monitoring子系统注册hard lockup检测事件
// 3.使能hard lockup检测事件
// 注:
// performance monitoring,x86中的硬件设备,当cpu clock经过了指定个周期后发出一个NMI中断。
1.1 static int watchdog_nmi_enable(unsigned int cpu)
{
//hard lockup事件
struct perf_event_attr *wd_attr;
struct perf_event *event = per_cpu(watchdog_ev, cpu);
....
wd_attr = &wd_hw_attr;
//hard lockup检测周期,10s
wd_attr->sample_period = hw_nmi_get_sample_period(watchdog_thresh);
//向performance monitoring注册hard lockup检测事件
event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL);
....
//使能hard lockup的检测
per_cpu(watchdog_ev, cpu) = event;
perf_event_enable(per_cpu(watchdog_ev, cpu));
return 0;
}
// 换算hard lockup检测周期到cpu频率
1.2 u64 hw_nmi_get_sample_period(int watchdog_thresh)
{
return (u64)(cpu_khz) * 1000 * watchdog_thresh;
}
// hard lockup检测事件发生时的nmi回调函数
// 函数任务:
// 1.判断是否发生了hard lockup
// 1.1 dump hard lockup信息
1.3 static void watchdog_overflow_callback(struct perf_event *event,
struct perf_sample_data *data,
struct pt_regs *regs)
{
//判断是否发生hard lockup
if (is_hardlockup()) {
int this_cpu = smp_processor_id();
//打印hard lockup信息
if (hardlockup_panic)
panic("Watchdog detected hard LOCKUP on cpu %d", this_cpu);
else
WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu);
return;
}
return;
}
// 判断是否发生hard lockup
// 注:
// 如果时钟中断在指定阈值范围内为运行,核心认为可屏蔽中断被屏蔽时间过长
1.4 static int is_hardlockup(void)
{
//获取watchdog timer的运行次数
unsigned long hrint = __this_cpu_read(hrtimer_interrupts);
//在一个hard lockup检测时间阈值内,如果watchdog timer未运行,说明cpu中断被屏蔽时间超过阈值
if (__this_cpu_read(hrtimer_interrupts_saved) == hrint)
return 1;
//记录watchdog timer运行的次数
__this_cpu_write(hrtimer_interrupts_saved, hrint);
return 0;
}
// 关闭hard lockup检测机制
// 函数任务:
// 1.向performance monitoring子系统注销hard lockup检测控制块
// 2.清空per-cpu hard lockup检测控制块
// 3.释放hard lock检测控制块
2.1 static void watchdog_nmi_disable(unsigned int cpu)
{
struct perf_event *event = per_cpu(watchdog_ev, cpu);
if (event) {
//向performance monitoring子系统注销hard lockup检测控制块
perf_event_disable(event);
//清空per-cpu hard lockup检测控制块
per_cpu(watchdog_ev, cpu) = NULL;
//释放hard lock检测控制块
perf_event_release_kernel(event);
}
return;
}