Linux kernel panic代码解释
Posted 程序猿Ricky的日常干货
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux kernel panic代码解释相关的知识,希望对你有一定的参考价值。
当Linux内核发生严重错误的时候,系统无法继续运行下去,此时内核会主动触发一个panic操作,它的执行流程分析过程如下所示:
kernel/panic.c:
void panic(const char *fmt, ...)
pr_emerg("Kernel panic - not syncing: %s\\n", buf);
...
if (panic_timeout != 0)
/*
* This will not be a clean reboot, with everything
* shutting down. But if there is a chance of
* rebooting the system it will be rebooted.
*/
emergency_restart();
...
pr_emerg("---[ end Kernel panic - not syncing: %s ]---\\n", buf);
local_irq_enable();
for (i = 0; ; i += PANIC_TIMER_STEP)
touch_softlockup_watchdog();
if (i >= i_next)
i += panic_blink(state ^= 1);
i_next = i + 3600 / PANIC_BLINK_SPD;
mdelay(PANIC_TIMER_STEP);
系统发生了panic后是会跑到panic函数中来的,在我使用的高通平台上 panic_timeout=-1
,然后调用进入emergency_restart,进行restart操作。
kernel/reboot.c:
void emergency_restart(void)
kmsg_dump(KMSG_DUMP_EMERG);
machine_emergency_restart();
EXPORT_SYMBOL_GPL(emergency_restart);
include/asm-generic/emergency-restart.h:
static inline void machine_emergency_restart(void)
machine_restart(NULL);
arch/arm64/kernel/process.c:
void machine_restart(char *cmd)
/* Disable interrupts first */
local_irq_disable();
smp_send_stop();
/*
* UpdateCapsule() depends on the system being reset via
* ResetSystem().
*/
if (efi_enabled(EFI_RUNTIME_SERVICES))
efi_reboot(reboot_mode, NULL);
/* Now call the architecture specific reboot code. */
if (arm_pm_restart)
arm_pm_restart(reboot_mode, cmd);
else
do_kernel_restart(cmd);
/*
* Whoops - the architecture was unable to reboot.
*/
printk("Reboot failed -- System halted\\n");
while (1);
从函数调用栈来看最终它会执行到machine_restart,也就是重启操作。那么panic重启和正常重启一样都会调用到machine_restart函数,区别在于高通平台上的panic重启是会触发设备进入warm reset进而抓取crash dump数据用于稳定性分析,而普通重启操作并不会触发warm reset。实际上不同的restart方式是由平台相关的代码来实现的,正常情况下进入之后就不应该再返回,但是如果restart失败返回的话,那么就会导致system halt。平台相关的操作如下所示:
/* Now call the architecture specific reboot code. */
if (arm_pm_restart)
arm_pm_restart(reboot_mode, cmd);
在高通平台相关代码中会对arm_pm_restart赋值:
drivers/power/reset/msm-poweroff.c:
static int msm_restart_probe(struct platform_device *pdev)
...
pm_power_off = do_msm_poweroff;
arm_pm_restart = do_msm_restart;
...
平台相关实现主要在do_msm_restart中:
static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
pr_notice("Going down for restart now\\n");
msm_restart_prepare(cmd);
/*
* Trigger a watchdog bite here and if this fails,
* device will take the usual restart path.
*/
if (WDOG_BITE_ON_PANIC && in_panic)
msm_trigger_wdog_bite();
scm_disable_sdi();
halt_spmi_pmic_arbiter();
deassert_ps_hold();
msleep(10000);
从前面的分析可以看出,这个函数实现并不仅仅用于panic,普通reset也会调用到。那么此函数是如何处理不同情况的呢?
-
1.重启类型的配置,对于高通平台上的panic就是配置PS_HOLD的 reset type为warm reset。
这一步骤是在msm_restart_prepare函数中实现的,最终会设置到PMIC寄存器中,以保证Ram不掉电,也就是热重启。 -
2.这里针对panic做了区分的还有watchdog处理。
/*
* Trigger a watchdog bite here and if this fails,
* device will take the usual restart path.
*/
if (WDOG_BITE_ON_PANIC && in_panic)
msm_trigger_wdog_bite();
为什么要watchdog处理,watchdog能触发secure world的重启操作,高通的soc中包含了很多子系统,并不仅仅只有ap,还有modem、sensor hub、cdsp、adsp等等,只有通过secure world中的tz来执行reset,才能够保证最后重启之前由tz向各个子系统发送消息保存panic现场数据。否则我们只能保证是non secure world的reset操作。
- 3.拉高PS HOLD引脚,这个引脚是从AP输出给到PMIC的重启信号
PMIC接收该信号后,会按照配置的重启类型执行掉电,重上电操作,从而可以区分hard reset还是warm reset。
以上是关于Linux kernel panic代码解释的主要内容,如果未能解决你的问题,请参考以下文章
Linux内核升级导致无法启动,Kernel panic - not syncing Unable to mount root fs on unknown block(0,0)
linux升级后重启出现kernel panic:attempted to kill init???
redhat linux 无法启动 提示(kernel panic - not syncing:attempted to kill init!)
redhat linux 无法启动 提示(kernel panic - not syncing:attempted to kill init!)
求助!Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b 小弟正在做嵌入式linux