NMI에 의한 커널 패닉 현상에 대하여
글쓴이: sohn9086 / 작성시간: 화, 2010/07/06 - 4:30오후
커널 디버깅에 대해서 고수님들께 좀 여쭤보려고 합니다.
디버깅 환경
- CPU : Core 2 Duo E 6400
- Chipset : Q965 + ICH8DO
- Distribution : CentOS 5.4
- Kernel version : 2.6.30.10 (vanilla)
머신에서 특정 조작을 수행하면 커널 패닉이 일어나는 현상이 있어서 현재 디버깅중입니다.(재현율 100%는 아니고, 세번중 한번꼴로 발생합니다.)
디버깅을 위해 커널 crash dump를 떠 보았더니 아래와 같은 메세지를 보여주는군요.
crash 4.1.2-4.el5.centos Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Red Hat, Inc. Copyright (C) 2004, 2005, 2006 IBM Corporation Copyright (C) 1999-2006 Hewlett-Packard Co Copyright (C) 2005, 2006 Fujitsu Limited Copyright (C) 2006, 2007 VA Linux Systems Japan K.K. Copyright (C) 2005 NEC Corporation Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc. Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. This program is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Enter "help copying" to see the conditions. This program has absolutely no warranty. Enter "help warranty" for details. GNU gdb 6.1 Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu"... KERNEL: vmlinux DUMPFILE: vmcore CPUS: 2 DATE: Mon Jul 5 17:36:16 2010 UPTIME: 00:06:57 LOAD AVERAGE: 0.43, 1.36, 0.79 TASKS: 270 NODENAME: localhost.localdomain RELEASE: 2.6.30.10-debug VERSION: #1 SMP Fri Jun 18 17:01:36 JST 2010 MACHINE: i686 (2128 Mhz) MEMORY: 2 GB PANIC: "" PID: 0 COMMAND: "swapper" TASK: c07b3300 (1 of 2) [THREAD_INFO: c080e000] CPU: 0 STATE: TASK_RUNNING (ACTIVE) WARNING: panic task not found crash> bt PID: 0 TASK: c07b3300 CPU: 0 COMMAND: "swapper" #0 [c080eee0] crash_nmi_callback at c0410dcb #1 [c080eee4] notifier_call_chain at c06a02b1 #2 [c080ef04] __atomic_notifier_call_chain at c06a02de #3 [c080ef14] atomic_notifier_call_chain at c06a02ec #4 [c080ef24] notify_die at c0441cb3 #5 [c080ef40] do_nmi at c069e8f1 #6 [c080ef64] nmi at c069e6a0 EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000000 EBP: c080efc0 DS: 007b ESI: 00000000 ES: 007b EDI: c080bedc GS: 0000 CS: 0060 EIP: c0408c41 ERR: 00000000 EFLAGS: 00000246 #7 [c080ef98] mwait_idle at c0408c41 #8 [c080efc4] cpu_idle at c0401ce7
대충 보아하니 CPU idle중에 NMI가 발생해서 죽어버린 듯한 것 같아, 처음에는 watchdog을 의심했습니다.
그러나, BIOS의 watchdog옵션은 disable로 되어있기 때문에 아마 아닌 것 같습니다.
그래도 혹시나 해서 조금 구글링을 해보니 APIC에서 특정 주기로 발생시키는 NMI를 이용하는 nmi watchdog이라는 게 있다고 하네요. 그런데 그 기능이 제대로 동작하려면 /proc/interrupts에서 NMI로 표시되는 인터럽트가 발생해야 한다는데 제 환경에서는 발생하지 않는걸로 보아 역시 그것도 아닌 것 같습니다.
할 수 없이 소스를 따라 가 보았습니다. do_nmi함수안에서 불리워지는 default_do_nmi를 보니 아래와 같이 되어있더군요.
static notrace __kprobes void default_do_nmi(struct pt_regs *regs) { unsigned char reason = 0; int cpu; cpu = smp_processor_id(); /* Only the BSP gets external NMIs from the system. */ if (!cpu) reason = get_nmi_reason(); if (!(reason & 0xc0)) { if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT) == NOTIFY_STOP) return; #ifdef CONFIG_X86_LOCAL_APIC /* * Ok, so this is none of the documented NMI sources, * so it must be the NMI watchdog. */ if (nmi_watchdog_tick(regs, reason)) return; if (!do_nmi_callback(regs, cpu)) unknown_nmi_error(reason, regs); #else unknown_nmi_error(reason, regs); #endif return; } if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP) return; /* AK: following checks seem to be broken on modern chipsets. FIXME */ if (reason & 0x80) mem_parity_error(reason, regs); if (reason & 0x40) io_check_error(reason, regs); #ifdef CONFIG_X86_32 /* * Reassert NMI in case it became active meanwhile * as it's edge-triggered: */ reassert_nmi(); #endif }
crash의 백트레이스 결과로 보아
if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
아마도 이 부분이 불리워진게 아닌가 하는데, 혹시 이런 이유로 커널이 죽을 때, 그것이 무엇을 뜻하는 것인지 경험해 보신 분이 계신가요?
Forums:
댓글 달기