Board logo

标题: x86平台linux系统重启流程跟踪更新 [打印本页]

作者: look_w    时间: 2017-10-24 23:11     标题: x86平台linux系统重启流程跟踪更新

从函数实现上看,使用死循环,根据不同的重启类型做转变:
BOOT_ACPI->BOOT_KBD->BOOT_ACPI->BOOT_EFI->BOOT_BIOS->BOOT_CF9_SAFE->BOOT_TRIPLE...首先是ACPI复位,调用acpi_reboot函数(driver/acpi/reboot.c),在该函数中通过写PCI寄存器方式复位。这涉及ACPI相关知识,笔者未做深入研究。笔者在一台安装BIOS的机器上测试发现是使用ACPI复位的。
如果ACPI被禁止(即无法复位成功),则使用keyboad复位,主要是写0xfe到端口0x64,关于它的作用,直接引述网络资料:
“0x64端口是i8042键盘控制器的控制端口,0xfe命令字的意思是将P32-P21三个针脚拉为低电平,持续6usec。这段代码的实际效果就相当于你按下机箱上的 RESET键。”
值得一提的是BOOT_CF9_SAFE分支,当port_cf9_safe为true时,会通过写0xcf9寄存器的方式复位。
其余的暂略过不提。

(注:上面分析顺序根据笔者测试结果来描述,理论上并不严谨)
下面看看系统重启过程的调试信息(注:此时机器无法使用reset重启):






四、u-boot环境reset作为扩展,本文顺便也看看u-boot源码下重启的流程。reset命令位于cmd/boot.c文件:





do_reset函数实现在arch/x86/cpu/cpu.c文件:





上面列出2个复位的函数:reset_cpu、x86_full_reset。它们只有细微区别,但都是往IO_PORT_RESET这个端口上写数值。接着看看这些宏定义是什么。它们的定义位于文件arch/x86/include/asm/processor.h:





从注释上看,0xcf9是Intel Atom的E3800系列SOC的RST_CNT寄存器(在内核中亦出现此寄存器)。复位类型有3种:SYS_RST、RST_CPU、FULL_RST。
本着打破沙锅问到底的钻研精神,找到E3800的datasheet,查看关于复位的说明章节(7.4章节),截图如下:



三种复位类型组合即为0x0e,亦即表格第一行所述操作。而RST_CNT寄存器的说明位于30.7章节,其寄存器地址正是CF9h。


这样,终于和u-boot源码对应起来了,对源码的复位函数也能解释得通了。网络上有资料表明可以在ICH手册中找到CF9寄存器,有兴趣的可以自行查阅。
五、所遇问题及解决细心的读者可能会发现在native_machine_emergency_restart函数中,笔者在BOOT_KBD分支中写0xcf9寄存器,而不是使用BOOT_CF9_SAFE分支。因为笔者在使用u-boot引导启动(非BIOS)的x86机器上遇到无法复位的问题,当执行到BOOT_BIOS时机器死了,但没有复位——应该是板子上并没有BIOS,无法执行对应的指令吧,这方面没有深入研究。选择在BOOT_KBD中实现是因为同一份内核镜像文件需要在有BIOS的机器和有u-boot的机器上运行。——无论是设计还是维护角度,笔者希望能尽量兼容。

六、小结要使系统重启,直接调用reboot即可,但由于系统重启还需要进行其它清理操作,一般不建议直接使用。在内核空间中实现的重启机制,首先使用ACPI,其次使用keyboad,再次使用BIOS,最后使用CF9。从u-boot源码分析看到,x86机器的重启是通过将0x0e写到0xcf9寄存器来实现的,在内核内核也有此方式,但差不多是在最后才执行,优先级较低。另外关于ACPI的研究,待日后有空闲再议。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0