您的位置:首页 > 运维架构 > Linux

linux reboot flow

2015-12-15 10:43 543 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: