kernel crash 发生后的那些事(四)

2024-06-03 16:32
文章标签 发生 kernel crash

本文主要是介绍kernel crash 发生后的那些事(四),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Oops信息打印后,后面还有一个 crash dump 和系统重启的过程,本例为系统重启,在UBoot中保存core dump.

die-> crash_kexec

kernel/kexec.c:
void crash_kexec(struct pt_regs *regs)
{
    /* Take the kexec_mutex here to prevent sys_kexec_load
     * running on one cpu from replacing the crash kernel
     * we are using after a panic on a different cpu.
     *
     * If the crash kernel was not located in a fixed area
     * of memory the xchg(&kexec_crash_image) would be
     * sufficient.  But since I reuse the memory...
     */
    if (mutex_trylock(&kexec_mutex)) {
        if (kexec_crash_image) {
            struct pt_regs fixed_regs;

            crash_setup_regs(&fixed_regs, regs);
            crash_save_vmcoreinfo();
            machine_crash_shutdown(&fixed_regs);
            machine_kexec(kexec_crash_image);
        }
        else{
            printk(KERN_ERR "Enter crash kexec !!\n");
            struct pt_regs fixed_regs;
            extern void machine_crash_swreset(void);
            crash_setup_regs(&fixed_regs, regs);
            crash_save_vmcoreinfo();
            machine_crash_shutdown(&fixed_regs);
            machine_crash_swreset();
        }
        mutex_unlock(&kexec_mutex);
    }
}

die-> crash_kexec->machine_crash_shutdown

如果是使用Uboot做为crash kernel,代码运行 else分支。
arch/arm/kenerl/machine_kexec.c
void machine_crash_shutdown(struct pt_regs *regs)
{
    unsigned long msecs;

    local_irq_disable();

    atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
    smp_call_function(machine_crash_nonpanic_core, NULL, false);
    msecs = 1000; /* Wait at most a second for the other cpus to stop */
    while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
        mdelay(1);
        msecs--;
    }
    if (atomic_read(&waiting_for_crash_ipi) > 0)
        printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n");

    crash_save_cpu(regs, smp_processor_id());
    machine_kexec_mask_interrupts();

    printk(KERN_INFO "Loading crashdump kernel...\n");
}

这里有个SMP相关的操作:smp_call_function

kernel/smp.c
/**
 * smp_call_function(): Run a function on all other CPUs.
 * @func: The function to run. This must be fast and non-blocking.
 * @info: An arbitrary pointer to pass to the function.
 * @wait: If true, wait (atomically) until function has completed
 *        on other CPUs.
 *
 * Returns 0.
 *
 * If @wait is true, then returns once @func has returned; otherwise
 * it returns just before the target cpu calls @func.
 *
 * You must not call this function with disabled interrupts or from a
 * hardware interrupt handler or from a bottom half handler.
 */
int smp_call_function(smp_call_func_t func, void *info, int wait)
{
    preempt_disable();
    smp_call_function_many(cpu_online_mask, func, info, wait);
    preempt_enable();

    return 0;
}


void machine_crash_nonpanic_core(void *unused)
{
    struct pt_regs regs;

    crash_setup_regs(&regs, NULL);
    printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n",
           smp_processor_id());
    crash_save_cpu(&regs, smp_processor_id());
    flush_cache_all();

    atomic_dec(&waiting_for_crash_ipi);
    while (1)
        cpu_relax();
}

其它的CPU保存寄存器和flush cache 后,进入死循环cpu_relax。

软件复位

machime_kexec.c文件中实现machine_crash_swreset,其中有个定义在 arch/arm/include/asm/system_misc.h
中的全局变量:extern void (*arm_pm_restart)(char str, const char *cmd);
void machine_crash_swreset(void)
{
    printk(KERN_INFO "Software reset on panic!\n");

    flush_cache_all();
    outer_flush_all();
    outer_disable();
    arm_pm_restart(0, NULL);
}
在mach相关的代码中进行赋值
Core.c (arch\arm\mach-xxx):    arm_pm_restart = xxx_restart;

static void xxx_restart(char mode, const char *cmd)
{
    prcm_glb_soft_reset();

}

至此,kernel crash 发生后的所有事情分析完毕。后面会介绍怎样保存有效的kernel dump文件。

这篇关于kernel crash 发生后的那些事(四)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1027515

相关文章

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

笔记整理—内核!启动!—kernel部分(2)从汇编阶段到start_kernel

kernel起始与ENTRY(stext),和uboot一样,都是从汇编阶段开始的,因为对于kernel而言,还没进行栈的维护,所以无法使用c语言。_HEAD定义了后面代码属于段名为.head .text的段。         内核起始部分代码被解压代码调用,前面关于uboot的文章中有提到过(eg:zImage)。uboot启动是无条件的,只要代码的位置对,上电就工作,kern

当你输入一个网址后都发生什么

原文:http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/  作为一个软件开发者,你一定会对网络应用如何工作有一个完整的层次化的认知,同样这里也包括这些应用所用到的技术:像浏览器,HTTP,HTML,网络服务器,需求处理等等。 本文将更深入的研究当你输入一个网址的时候,后台到底发生了一件件什么样的事~

欧拉系统 kernel 升级、降级

系统版本  cat  /etc/os-release  NAME="openEuler"VERSION="22.03 (LTS-SP1)"ID="openEuler"VERSION_ID="22.03"PRETTY_NAME="openEuler 22.03 (LTS-SP1)"ANSI_COLOR="0;31" 系统初始 kernel 版本 5.10.0-136.12.0.

[Linux Kernel Block Layer第一篇] block layer架构设计

目录 1. single queue架构 2. multi-queue架构(blk-mq)  3. 问题 随着SSD快速存储设备的发展,内核社区越发发现,存储的性能瓶颈从硬件存储设备转移到了内核block layer,主要因为当时的内核block layer是single hw queue的架构,导致cpu锁竞争问题严重,本文先提纲挈领的介绍内核block layer的架构演进,然

Kernel 中MakeFile 使用if条件编译

有时需要通过if  else来选择编译哪个驱动,单纯的obj-$(CONFIG_)就不是很方便,下面提供两种参考案例: 案例一: 来源:drivers/char/tpm/Makefileifdef CONFIG_ACPItpm-y += tpm_eventlog.o tpm_acpi.oelseifdef CONFIG_TCG_IBMVTPMtpm-y += tpm_eventlog.o

日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个 嫌疑犯的一个。以下为4个嫌疑犯的供词。

日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个 嫌疑犯的一个。以下为4个嫌疑犯的供词。 A说:不是我。 B说:是C。 C说:是D。 D说:C在胡说 已知3个人说了真话,1个人说的是假话。 现在请根据这些信息,写一个程序来确定到底谁是凶手。  static void Main()         {             int killer = 0;             fo

笔记整理—内核!启动!—kernel部分(1)驱动与内核的关系

首先,恭喜完成了uboot部分的内容整理,其次补充一点,uboot第一部分和第二部分的工作不是一定的,在不同的版本中,可能这个初始化早一点,那个的又放在了第二部分,版本不同,造成的工作顺序不同,但终归是要完成基本内容初始化并传参给kernel的。         那么至于驱动与内核的关系,用一张图来说明最适合不过:         驱动位于OS层的中下层与硬件相接。驱动是内

一个瑞典游戏工作室决定离开索尼,之前和之后都发生了什么?

我们在前两篇中探究了国家政策、硬件基础与黑客文化如何让瑞典成为了游戏热土,而它充满地域特色的开发者社区与教育体系的构建,又是如何聚拢了游戏人才,让体系持续生长扩张。 除了大学、科技园和开发者之家外,我们此行从斯德哥尔摩到舍夫德到马尔默,还采访了三家知名工作室的创始人。它们一家产出如今罕见的双人合作游戏,还有一位特立独行的作者型开发者屡屡占据头条;一家贡献了现象级网红作品,当前在朝“正经向”大

关于Qt在子线程中使用通讯时发生无法接收数据的情况

在多线程应用中,串口通讯或TCP通讯的场景常常涉及到持续的读写操作,如果子线程处理不当,可能会导致信号阻塞问题。本文将通过串口通讯或TCP通讯为例,详细解释如何在多线程环境中避免信号阻塞,并提供代码示例。 1. 问题背景 假设我们在一个应用程序中使用多线程处理串口或TCP通讯,通常会在子线程中实现持续的数据读取。为了确保实时处理数据,常见的做法是在子线程的 run() 方法中使用 while