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

x86平台下Android系统的Linux部分的重启分析

2013-05-07 14:46 1136 查看
转自 : http://blog.csdn.net/android_huber
在Android下,我们在命令行中敲入reboot后系统的重启首先是执行的reboot这个应用程序。这是一个比较简单的小程序,其源码在 system/core/toolbox/reboot.c,主要的代码如下:

01.if(poweroff)  
02.    ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, NULL);  
03.else if(argc > optind)  
04.    ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, argv[optind]);  
05.else  
06.    ret = reboot(RB_AUTOBOOT);


这边都是通过系统调用进入内核的,LINUX_REBOOT_MAGIC1和LINUX_REBOOT_MAGIC2是两个参数。进入kernel/sys.c中

01./* 
02. * Reboot system call: for obvious reasons only root may call it, 
03. * and even root needs to set up some magic numbers in the registers 
04. * so that some mistake won't make this reboot the whole machine. 
05. * You can also set the meaning of the ctrl-alt-del-key here. 
06. * 
07. * reboot doesn't sync: do that yourself before calling this. 
08. */  
09.SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,  
10.        void __user *, arg)  
11.{  
12.    char buffer[256];  
13.    int ret = 0;  
14.  
15.    /* We only trust the superuser with rebooting the system. */  
16.    if (!capable(CAP_SYS_BOOT))  
17.        return -EPERM;  
18.  
19.    /* For safety, we require "magic" arguments. */  
20.    if (magic1 != LINUX_REBOOT_MAGIC1 ||  
21.        (magic2 != LINUX_REBOOT_MAGIC2 &&  
22.                    magic2 != LINUX_REBOOT_MAGIC2A &&  
23.            magic2 != LINUX_REBOOT_MAGIC2B &&  
24.                    magic2 != LINUX_REBOOT_MAGIC2C))  
25.        return -EINVAL;  
26.  
27.    /* Instead of trying to make the power_off code look like 
28.     * halt when pm_power_off is not set do it the easy way. 
29.     */  
30.    if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)  
31.        cmd = LINUX_REBOOT_CMD_HALT;  
32.  
33.    mutex_lock(&reboot_mutex);  
34.    switch (cmd) {  
35.    case LINUX_REBOOT_CMD_RESTART:  
36.        kernel_restart(NULL);  
37.        break;  
38.  
39.    case LINUX_REBOOT_CMD_CAD_ON:  
40.        C_A_D = 1;  
41.        break;  
42.  
43.    case LINUX_REBOOT_CMD_CAD_OFF:  
44.        C_A_D = 0;  
45.        break;  
46.  
47.    case LINUX_REBOOT_CMD_HALT:  
48.        kernel_halt();  
49.        do_exit(0);  
50.        panic("cannot halt");  
51.  
52.    case LINUX_REBOOT_CMD_POWER_OFF:  
53.        kernel_power_off();  
54.        do_exit(0);  
55.        break;  
56.  
57.    case LINUX_REBOOT_CMD_RESTART2:  
58.        if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {  
59.            ret = -EFAULT;  
60.            break;  
61.        }  
62.        buffer[sizeof(buffer) - 1] = '\0';  
63.  
64.        kernel_restart(buffer);  
65.        break;  
66.  
67.#ifdef CONFIG_KEXEC  
68.    case LINUX_REBOOT_CMD_KEXEC:  
69.        ret = kernel_kexec();  
70.        break;  
71.#endif  
72.  
73.#ifdef CONFIG_HIBERNATION  
74.    case LINUX_REBOOT_CMD_SW_SUSPEND:  
75.        ret = hibernate();  
76.        break;  
77.#endif  
78.  
79.    default:  
80.        ret = -EINVAL;  
81.        break;  
82.    }  
83.    mutex_unlock(&reboot_mutex);  
84.    return ret;  
85.}


我们通过命令行敲reboot的话进入的是LINUX_REBOOT_CMD_RESTART这个分支,可以看到接下来会调用kernel_restart(NULL);

01./** 
02. *  kernel_restart - reboot the system 
03. *  @cmd: pointer to buffer containing command to execute for restart 
04. *      or %NULL 
05. * 
06. *  Shutdown everything and perform a clean reboot. 
07. *  This is not safe to call in interrupt context. 
08. */  
09.void kernel_restart(char *cmd)  
10.{  
11.    kernel_restart_prepare(cmd);  
12.    if (!cmd)  
13.        printk(KERN_EMERG "Restarting system.\n");  
14.    else  
15.        printk(KERN_EMERG "Restarting system with command '%s'.\n", cmd);  
16.    kmsg_dump(KMSG_DUMP_RESTART);  
17.    machine_restart(cmd);  
18.}

这个函数里面会打印出我们常看到的log,Restarting system.

kernel_restart_prepare(cmd);里会去调用设备的shutdown接口,去power off设备,并且发送SYS_RESTART的广播,

01.void kernel_restart_prepare(char *cmd)  
02.{  
03.    blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);  
04.    system_state = SYSTEM_RESTART;  
05.    device_shutdown();  
06.    sysdev_shutdown();  
07.}

接着执行machine_restart(cmd);我们会调到arch/x86/kernel/reboot.c中,这里需要知道一个ops

01.struct machine_ops machine_ops = {  
02.    .power_off = native_machine_power_off,  
03.    .shutdown = native_machine_shutdown,  
04.    .emergency_restart = native_machine_emergency_restart,  
05.    .restart = native_machine_restart,  
06.    .halt = native_machine_halt,  
07.#ifdef CONFIG_KEXEC  
08.    .crash_shutdown = native_machine_crash_shutdown,  
09.#endif  
10.};


machine_restart就是执行这行这里的native_machine_restart

01.static void native_machine_restart(char *__unused)  
02.{  
03.    printk("machine restart\n");  
04.  
05.    if (!reboot_force) {  
06.        printk("native_machine_restart reboot_force:%d\n", reboot_force);  
07.        machine_shutdown();  
08.    }  
09.    __machine_emergency_restart(0);  
10.}


machine_shutdown();中执行一些shutdown工作,重启的工作在__machine_emergency_restart(0);

01.static void __machine_emergency_restart(int emergency)  
02.{  
03.    reboot_emergency = emergency;  
04.    machine_ops.emergency_restart();  
05.}


调用ops中的emergency_restart

01.static void native_machine_emergency_restart(void)  
02.{  
03.    int i;  
04.  
05.    if (reboot_emergency)  
06.        emergency_vmx_disable_all();  
07.  
08.    tboot_shutdown(TB_SHUTDOWN_REBOOT);  
09.      
10.    /* Tell the BIOS if we want cold or warm reboot */  
11.    *((unsigned short *)__va(0x472)) = reboot_mode;  
12.  
13.    for (;;) {  
14.        /* Could also try the reset bit in the Hammer NB */  
15.        switch (reboot_type) {  
16.        case BOOT_KBD:            
17.            mach_reboot_fixups(); /* for board specific fixups */  
18.  
19.            for (i = 0; i < 10; i++) {  
20.                printk("%d\n", i);  
21.                kb_wait();  
22.                udelay(50);  
23.                outb(0xfe, 0x64); /* pulse reset low */  
24.                udelay(50);  
25.            }  
26.  
27.        case BOOT_TRIPLE:  
28.              
29.            load_idt(&no_idt);  
30.              
31.            __asm__ __volatile__("int3");  
32.              
33.            reboot_type = BOOT_KBD;  
34.            break;  
35.  
36.#ifdef CONFIG_X86_32  
37.        case BOOT_BIOS:  
38.                        machine_real_restart(jump_to_bios, sizeof(jump_to_bios));  
39.                        reboot_type = BOOT_KBD;  
40.            break;  
41.#endif  
42.  
43.        case BOOT_ACPI:  
44.              
45.            acpi_reboot();  
46.            reboot_type = BOOT_KBD;  
47.            break;  
48.  
49.        case BOOT_EFI:  
50.              
51.            if (efi_enabled)  
52.                efi.reset_system(reboot_mode ?  
53.                         EFI_RESET_WARM :  
54.                         EFI_RESET_COLD,  
55.                         EFI_SUCCESS, 0, NULL);  
56.            reboot_type = BOOT_KBD;  
57.            break;  
58.  
59.        case BOOT_CF9:  
60.              
61.            port_cf9_safe = true;  
62.            /* fall through */  
63.  
64.        case BOOT_CF9_COND:  
65.              
66.            if (port_cf9_safe) {  
67.                u8 cf9 = inb(0xcf9) & ~6;  
68.                            
69.                outb(cf9|2, 0xcf9); /* Request hard reset */  
70.                udelay(50);  
71.                outb(cf9|6, 0xcf9); /* Actually do the reset */  
72.                udelay(50);  
73.            }  
74.            reboot_type = BOOT_KBD;  
75.            break;  
76.        }  
77.    }  
78.}


这边就是重启的最后部分了,默认的是通过BOOT_KBD方式重启的,这种方式是通过键盘控制器去模拟按下键盘上的reset键来重启的,往0x64端口中写0xfe即可

/* tell the BIOS to do a warm start */
*((unsigned short *)0x472) = 0x1234;
outb(0xfe,0x64);


然后系统会在__asm__ __volatile__("int3");中中断。int3是一个breakpoint,用来使程序停止在这,等待重启。

这里再说下,通过0xcf9来重启,用注释来解释Use the so-called "PCI reset register", CF9,通过这个寄存器可以使系统hard reset

outb(0x06,0xCF9);

0xCF9 是IO Mapping 中的地址,所以可以用outb直接访问. 可以在ICH的datasheet中找到它,

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐