linux reboot flow

来源:互联网 发布:破解qq悄悄话的软件 编辑:程序博客网 时间:2024/06/03 23:39

1,  little machine_desc struture

1-1, first eye on arch/arm/include/asm/mach/arch.h

/*
 * Machine type table - also only accessible during boot
 */
extern const struct machine_desc __arch_info_begin[], __arch_info_end[];
#define for_each_machine_desc(p)                        \
        for (p = __arch_info_begin; p < __arch_info_end; p++)

#define DT_MACHINE_START(_name, _namestr)               \
static const struct machine_desc __mach_desc_##_name    \
 __used                                                 \
 __attribute__((__section__(".arch.info.init"))) = {    \
        .nr             = ~0,                           \
        .name           = _namestr,

#endif

1-2, put machine_desc variable in arch.info.init section, whose begining is __arch_info_begin and ending is __arch_info_end. they defined at file arch/arm/kernel/vmlinux.lds.S

.init.arch.info : {
                __arch_info_begin = .;
                *(.arch.info.init)
                __arch_info_end = .;
        }
1-3,  grep "DT_MACHINE_START"  will help you find your board's related machine_desc, which will stored at section: arch.info.init, something like:

static const char *xxx_dt_match[] __initconst = {
        "xxx,yyyy",
        NULL
};

DT_MACHINE_START(xxx_DT, "Generic xxx (Flattened Device Tree)")
        .smp            = smp_ops(xxx_smp_ops),
        .map_io         = xxx_map_io,
        .init_machine   = xxx_init_mach,
        .init_late      = xxx_init_late,
        .dt_compat      = xxx_dt_match,
        .restart = xxxx_xxx_restart,
MACHINE_END

2,  who use the machine_desc variable

arch/arm/kernel/setup.c

start_kernel -> setup_arch -> setup_machine_fdt -> of_flat_dt_match_machine(mdesc_best, arch_get_next_mach) 

static const void * __init arch_get_next_mach(const char *const **match)
{
        static const struct machine_desc *mdesc = __arch_info_begin;
        const struct machine_desc *m = mdesc;

        if (m >= __arch_info_end)
                return NULL;

        mdesc++;
        *match = m->dt_compat;
        return m;
}

at last setup_machine_fdt will return a machine_desc variable at last which is your board used and assign arm_pm_restart at last by the follow statement:

if (mdesc->restart)
                arm_pm_restart = mdesc->restart;


3, what flow reboot will go?

in kernel/reboot.c there is a function:

SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
                void __user *, arg)
there is switch case:
switch (cmd) {
        case LINUX_REBOOT_CMD_RESTART:
                kernel_restart(NULL);
                break;

void kernel_restart(char *cmd)
{
        kernel_restart_prepare(cmd);
        migrate_to_reboot_cpu();
        syscore_shutdown();
        if (!cmd)
                pr_emerg("Restarting system\n");
        else
                pr_emerg("Restarting system with command '%s'\n", cmd);
        kmsg_dump(KMSG_DUMP_RESTART);
        machine_restart(cmd);
}

void kernel_restart_prepare(char *cmd)
{
        blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); //notify event of SYS_RESTART, others like "systemd" will capture it do some process.
        system_state = SYSTEM_RESTART;
        usermodehelper_disable();
        pr_info("%s will call device shutdown\n", __func__);
        device_shutdown();// device's shut down will be called
}

/**
 * syscore_shutdown - Execute all the registered system core shutdown callbacks.
 */
void syscore_shutdown(void)
{
        struct syscore_ops *ops;

        mutex_lock(&syscore_ops_lock);

        list_for_each_entry_reverse(ops, &syscore_ops_list, node)
                if (ops->shutdown) {
                        if (initcall_debug)
                                pr_info("PM: Calling %pF\n", ops->shutdown);
                        ops->shutdown();// registered by register_syscore_ops
                        pr_info("%s\n", __func__);
                }

        mutex_unlock(&syscore_ops_lock);
}

/*
 * Restart requires that the secondary CPUs stop performing any activity
 * while the primary CPU resets the system. Systems with a single CPU can
 * use soft_restart() as their machine descriptor's .restart hook, since that
 * will cause the only available CPU to reset. Systems with multiple CPUs must
 * provide a HW restart implementation, to ensure that all CPUs reset at once.
 * This is required so that any code running after reset on the primary CPU
 * doesn't have to co-ordinate with other CPUs to ensure they aren't still
 * executing pre-reset code, and using RAM that the primary CPU's code wishes
 * to use. Implementing such co-ordination would be essentially impossible.
 */
void machine_restart(char *cmd)
{
        local_irq_disable();
        smp_send_stop();


        /* Flush the console to make sure all the relevant messages make it
         * out to the console drivers */
        arm_machine_flush_console();

        if (arm_pm_restart) {
                pr_info("%s arm_pm_restart\n", __func__);
                arm_pm_restart(reboot_mode, cmd);
        } else {
                pr_info("%s do_kernel_restart\n", __func__);
                do_kernel_restart(cmd);
        }
        /* Give a grace period for failure to restart of 1s */
        mdelay(1000);

        /* Whoops - the platform was unable to reboot. Tell the user! */
        printk("Reboot failed -- System halted\n");
        local_irq_disable();
        while (1);
}


4, test result flow

[  148.550000] systemd-shutdown[1]: All DM devices detached.
[  148.560000] systemd-shutdown[1]: Rebooting.
[  148.560000] reboot: SYSC_reboot LINUX_REBOOT_CMD_RESTART //SYSCALL_DEFINE4(reboot
[  148.570000] reboot: kernel_restart_prepare will call device shutdown //kernel_restart_prepare
[  148.580000] mmc mmc3:0001: shutdown //device_shutdown
[  148.580000] mmcblk mmc1:1234: shutdown
[  148.580000] xxx_tsc 10d80000.adc:tsc: shutdown
[  148.710000] i2c i2c-2: shutdown
[  148.710000] i2c i2c-1: shutdown
[  148.710000] xxx_vdss sirfsoc_vdss.0: shutdown
[  148.710000] pca954x 0-0070: shutdown
[  148.720000] i2c 0-0045: shutdown
[  148.720000] i2c 0-0049: shutdown
[  148.720000] i2c 0-004b: shutdown
[  148.730000] i2c 0-0038: shutdown
[  148.730000] sx150x 0-0020: shutdown
[  148.730000] i2c i2c-0: shutdown
[  148.740000] pwm-backlight sirf-backlight: shutdown
[  148.740000] pvrsrvkm 12000000.graphics: shutdown
[  148.750000] xxx-wdt 10dc0000.timer: shutdown //device_shutdown
[  148.750000] syscore_shutdown //syscore_shutdown
[  148.750000] reboot: Restarting system
[  148.760000] machine_restart arm_pm_restart // machine_restart

0 0
原创粉丝点击