专栏首页Linux内核及编程语言底层相关技术研究linux内核启动流程分析 - startup_64

linux内核启动流程分析 - startup_64

在前面的第三篇文章中我们说道,efi_stub_entry最终会调用startup_64,那这篇文章我们就来看下startup_64的具体逻辑。

283行是设置startup_64函数的编译后地址为0x200,这个可以通过以下方式确认:

由上可见,startup_64的编译后地址就是0x200。

这个其实在286行的注释里也有说明,并强调这个是ABI,不能变。

296行将EFLAGS寄存器中的DF位清零,这个会影响以后的一些字符串操作指令。

297行将EFLAGS寄存器中的IF位清零,使cpu忽略中断请求。

300到305行将各种段寄存器清零。

接着看后面的行:

322行是将startup_32的运行时地址放到rbp中。

333到334行是使rbp再减去image_offset的值,最终得出kernel被加载到内存中的起始地址,这个我们在前面文章说过,就不再讲。

337到341行是让rbp中的地址按kernel_alignment对齐。

由之前的文章 linux内核启动流程分析 - efi_stub_entry 可知,rsi中存放的是boot_params的地址,而BP_kernel_alignment又是boot_params中的kernel_alignment字段的偏移量,该常量在下面的文件中定义:

所以BP_kernel_alignment(%rsi)指向的就是boot_params中kernel_alignment的值。

342到345行是确保rbp中的值不小于LOAD_PHYSICAL_ADDR。

这里再提下343行中的1f,它是GNU Assembler中的一种语法,表示的是汇编语言的local label,1f表示向下找第一个名为1的label,还有其他写法比如1b,表示向上找第一个名为1的label,想了解相关语法,可以看下面的链接:

https://sourceware.org/binutils/docs/as/Symbol-Names.html#Symbol-Names

再来继续看剩余的行。

349行表示将boot_params中的init_size放到ebx里。

之前我们说过,init_size表示的是,在bzImage以uefi application形式加载到内存时,我们要求uefi为其分配的内存大小。

init_size值是大于bzImage文件的大小的,因为bzImage是一个压缩过的内核,如果我们想要执行到真正的内核,还要在内存中对bzImage解压缩,init_size指定的多余的空间就是为了解压缩用的。

当bzImage被加载到内存中时,它占用的是init_size内存空间的起始部分,为了后续的解压缩需要,我们要将bzImage移动到init_size的结尾部分,349到351行就是为了计算,当把bzImage移动到init_size的结尾部分时,它的起始地址是多少。

bzImage其实包含两部分,分别是setup部分,对应为arch/x86/boot里的代码,和compressed部分,对应为arch/x86/boot/compressed里的代码。

当我们要把bzImage移动到init_size的结尾部分时,其实只要移动bzImage里的compressed部分就好,因为这里有我们真正需要解压缩的内核及其相关代码。

350行中的$_end表示的就是compressed部分的大小,所以用init_size减去_end,再加上整个init_size的起始地址rbp,得出的就是compressed部分移动到init_size的结尾时,它的起始地址。

该地址保存在了rbx中,后面会使用到。

限于篇幅原因,startup_64函数的内容就先讲这么多,有关其更多内容,我们在后面的文章再讲。

本文分享自微信公众号 - Linux内核及JVM底层相关技术研究(ytcode),作者:wangyuntao

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-10-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • linux内核启动流程分析 - efi_pe_entry

    接上一篇文章 linux内核启动流程分析 - efistub的入口函数,我们继续看efi_pe_entry这个函数。

    KINGYT
  • linux内核启动流程分析 - efi_stub_entry

    接上一篇文章 linux内核启动流程分析 - efi_pe_entry,我们继续看efi_stub_entry函数。

    KINGYT
  • linux内核启动流程分析 - efi_main

    上一篇文章 linux内核启动流程分析 - efi_stub_entry 中,为了叙述方便,我们只是粗略的讲了下efi_main函数,这里我们再具体看下。

    KINGYT
  • 06.内核启动流程分析之内核启动

    嵌入式与Linux那些事
  • linux内核启动过程分析

    start_kernel是内核启动阶段的入口,通过单步调试,可以发现它是linux内核执行的第一个init,我们单步进入看看它做了哪些操作:

    De4dCr0w
  • linux内核启动流程分析 - efistub的入口函数

    网上类似标题的文章很多,但大都是从start_kernel讲起,我觉得这是远远不够的。

    KINGYT
  • 05.内核启动流程分析之makefile

      分析makefile从顶层开始,顺藤摸瓜的分析下去,会涉及到所有的makefile文件。各级子目下的makefile完成的动作obj -y += obj -...

    嵌入式与Linux那些事
  • Linux 启动流程分析

    这个部分比较有意思。因为在BIOS阶段,计算机的行为基本上被写死了,程序员可以做的事情并不多;但是,一旦进入操作系统,程序员几乎可以定制所有方面。所以,这个部分...

    用户5807183
  • Linux 启动流程分析

    这个部分比较有意思。因为在BIOS阶段,计算机的行为基本上被写死了,程序员可以做的事情并不多;但是,一旦进入操作系统,程序员几乎可以定制所有方面。所以,这个部分...

    良月柒
  • Linux 启动流程分析

    这个部分比较有意思。因为在BIOS阶段,计算机的行为基本上被写死了,程序员可以做的事情并不多;但是,一旦进入操作系统,程序员几乎可以定制所有方面。所以,这个部分...

    用户6543014
  • 第3阶段——内核启动分析之创建si工程和分析stext启动内核函数(4)

    目标: (1)创建Source Insight 工程,方便后面分析如何启动内核的 (2)分析uboot传递参数,链接脚本如何进入stext的  (3) 分析st...

    张诺谦
  • 第3阶段——内核启动分析之创建si工程和分析stext启动内核函数(4)

    目标: (1)创建Source Insight 工程,方便后面分析如何启动内核的 (2)分析uboot传递参数,链接脚本如何进入stext的  (3) 分析st...

    张诺谦
  • Spark内核详解 (3) | Spark集群启动流程的简单分析

    本片博文主要分析的是Standalone 模式下 Spark 集群(Master, work)启动流程

    不温卜火
  • Influxdb启动流程分析

    我们启动的话通常是 influxd run -config [config file path]

    扫帚的影子
  • kubelet 启动流程分析

    本来这篇文章会继续讲述 kubelet 中的主要模块,但由于网友反馈能不能先从 kubelet 的启动流程开始,kubelet 的启动流程在很久之前基于 v1....

    田飞雨
  • kubelet 启动流程分析

    上篇文章(kubelet 架构浅析 )已经介绍过 kubelet 在整个集群架构中的功能以及自身各模块的用途,本篇文章主要介绍 kubelet 的启动流程。

    田飞雨
  • kubelet 启动流程分析

    上篇文章(kubelet 架构浅析 )已经介绍过 kubelet 在整个集群架构中的功能以及自身各模块的用途,本篇文章主要介绍 kubelet 的启动流程。

    田飞雨
  • 04.uboot分析之uboot启动内核

    首先要明确:uboot目标是从flash读出内核(nand read.jffs2 0x30007FC0 kernel;),启动它(bootm 0x30007FC...

    嵌入式与Linux那些事
  • 超详细分析Bootloader(Uboot)到内核的启动流程(万字长文!)

      Bootloader的启动过程可以分为单阶段、多阶段两种。通常多阶段的 Bootloader能提供更为复杂的功能以及更好的可移植性。从固态存储设备上启动的 ...

    嵌入式与Linux那些事

扫码关注云+社区

领取腾讯云代金券