x86平台下Android系统的Linux部分的重启分析
2013-05-07 14:46
1136 查看
转自 : http://blog.csdn.net/android_huber
在Android下,我们在命令行中敲入reboot后系统的重启首先是执行的reboot这个应用程序。这是一个比较简单的小程序,其源码在 system/core/toolbox/reboot.c,主要的代码如下:
这边都是通过系统调用进入内核的,LINUX_REBOOT_MAGIC1和LINUX_REBOOT_MAGIC2是两个参数。进入kernel/sys.c中
我们通过命令行敲reboot的话进入的是LINUX_REBOOT_CMD_RESTART这个分支,可以看到接下来会调用kernel_restart(NULL);
这个函数里面会打印出我们常看到的log,Restarting system.
kernel_restart_prepare(cmd);里会去调用设备的shutdown接口,去power off设备,并且发送SYS_RESTART的广播,
接着执行machine_restart(cmd);我们会调到arch/x86/kernel/reboot.c中,这里需要知道一个ops
machine_restart就是执行这行这里的native_machine_restart
machine_shutdown();中执行一些shutdown工作,重启的工作在__machine_emergency_restart(0);
调用ops中的emergency_restart
这边就是重启的最后部分了,默认的是通过BOOT_KBD方式重启的,这种方式是通过键盘控制器去模拟按下键盘上的reset键来重启的,往0x64端口中写0xfe即可,
然后系统会在__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中找到它,
在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中找到它,
相关文章推荐
- x86平台下Android系统的Linux部分的重启分析
- x86平台下Android系统的Linux部分的重启分析
- x86平台下 Android 系统的 Linux 部分的重启分析
- 我的内核学习笔记13:x86平台linux系统重启流程跟踪
- MTK平台相关总结#########[FAQ18279]开机时间慢分析 android 系统重启关机流程分析
- 深入浅出 - Android系统移植与平台开发(十四) - Sensor HAL框架分析之四
- Android 系统自动重启Bug(高通平台)
- 深入浅出 - Android系统移植与平台开发(十) - led HAL简单设计案例分析
- Android 6.0 JNI原理分析 和 Linux系统调用(syscall)原理
- 深入浅出 - Android系统移植与平台开发(十三) - Sensor HAL框架分析之三
- 深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一
- 深入浅出 - Android系统移植与平台开发(十四) - Sensor HAL框架分析之四
- Linux 适用硬件平台/系统架构(i386 / i586 / i686 / x86_64)解释
- 深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一
- 深入浅出 - Android系统移植与平台开发(十三) - Sensor HAL框架分析之三
- 分析Linux中Spinlock在ARM及X86平台上的实现
- MTD系列 - android平台上linux启动时init进程解析init.rc文件分析
- Android系统中视频电话中camera部分数据流分析
- Android系统移植与平台开发(四) - led HAL简单设计案例分析
- Android 系统自动重启Bug(高通平台)