Linux内核启动流程-第一阶段汇编流程简介

一.  Linux启动流程

看完 Linux 内核的顶层 Makefile 以后再来看 Linux 内核的大致启动流程, Linux 内核的启 动流程要比 uboot 复杂的多,涉及到的内容也更多。
本文中,我们就大致的了解一下 Linux 核的启动流程。
要分析 Linux 启动流程,同样需要先编译一下 Linux 源码,因为有很多文件是需要编译才会生成的。

二.  汇编流程简介

1.  链接脚本 vmlinux.lds

首先,分析 Linux 内核的链接脚本文件 arch/arm/kernel/vmlinux.lds ,通过链接脚本可以 找到
Linux 内核的第一行程序是从哪里执行的。 vmlinux.lds 中有如下代码:
492 OUTPUT_ARCH(arm)
493 ENTRY(stext)
494 jiffies = jiffies_64;
495 SECTIONS
496 {
497 /*
498 * XXX: The linker does not define how output sections are
499 * assigned to input sections when there are multiple statements
500 * matching the same input section name. There is no documented
501 * order of matching.
502 *
503 * unwind exit sections must be discarded before the rest of the
504 * unwind sections get included.
505 */
506 /DISCARD/ : {
507 *(.ARM.exidx.exit.text)
508 *(.ARM.extab.exit.text)
509 
......
645 }

493 行的 ENTRY 指明了了 Linux 内核入口,入口为 stext stext 定义在文件 arch/arm/kernel/head.S 中 , 因 此 要 分 析 Linux 内核的启动流程,就得先从文件  arch/arm/kernel/head.S  stext 处开始分析。

2.  Linux 内核入口 stext

stext Linux 内核的入口地址,在文件 arch/arm/kernel/head.S 中有如下所示提示内容:

/*
* Kernel startup entry point.
* ---------------------------
*
* This is normally called from the decompressor code. The requirements
* are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
* r1 = machine nr, r2 = atags or dtb pointer.
.....
*/

根据上面 的注释, Linux 内核启动之前要求如下:
①、关闭 MMU
②、关闭 D-cache
③、 I-Cache 无所谓。
④、 r0=0
⑤、 r1=machine nr( 也就是机器 ID)
⑥、 r2=atags 或者设备树 (dtb) 首地址。
Linux 内核的入口点 stext 其实相当于内核的入口函数, stext 函数内容如下:
80 ENTRY(stext)
......
91 @ ensure svc mode and all interrupts masked
92 safe_svcmode_maskall r9
93 
94 mrc p15, 0, r9, c0, c0 @ get processor id
95 bl __lookup_processor_type @ r5=procinfo r9=cpuid
96 movs r10, r5 @ invalid processor (r5=0)?
97 THUMB( it eq ) @ force fixup-able long branch encoding
98 beq __error_p @ yes, error 'p'
99 
......
107
108 #ifndef CONFIG_XIP_KERNEL
......
113 #else
114 ldr r8, =PLAT_PHYS_OFFSET @ always constant in this case
115 #endif
116
117 /*
118 * r1 = machine no, r2 = atags or dtb,
119 * r8 = phys_offset, r9 = cpuid, r10 = procinfo
120 */
121 bl __vet_atags
......
128 bl __create_page_tables
129
130 /*
131 * The following calls CPU specific code in a position independent
132 * manner. See arch/arm/mm/proc-*.S for details. r10 = base of
133 * xxx_proc_info structure selected by __lookup_processor_type
134 * above. On return, the CPU will be ready for the MMU to be
135 * turned on, and r0 will hold the CPU control register value.原子哥在线教学:www.yuanzige.com 论坛:www.openedv.com
942
I.MX6U 嵌入式 Linux 驱动开发指南
136 */
137 ldr r13, =__mmap_switched @ address to jump to after
138 @ mmu has been enabled
139 adr lr, BSYM(1f) @ return (PIC) address
140 mov r8, r4 @ set TTBR1 to swapper_pg_dir
141 ldr r12, [r10, #PROCINFO_INITFUNC]
142 add r12, r12, r10
143 ret r12
144 1: b __enable_mmu
145 ENDPROC(stext)

92 行,调用函数 safe_svcmode_maskall 确保 CPU 处于 SVC 模式,并且关闭了所有的中断。 safe_svcmode_maskall 定义在文件 arch/arm/include/asm/assembler.h 中。
94 行,读处理器 ID ID 值保存在 r9 寄存器中。
95 行,调用函数 __lookup_processor_type 检查当前系统是否支持此 CPU ,如果支持就获取 procinfo 信息。 procinfo proc_info_list 类 型 的 结 构 体 , proc_info_list 在文件 arch/arm/include/asm/procinfo.h 中。

Linux 内核将每种处理器都抽象为一个 proc_info_list 结构体,每种处理器都对应一个 procinfo。因此,可以通过处理器 ID 来找到对应的 procinfo 结构,__lookup_processor_type 函数找 到对应处器的 procinfo 以后会将其保存到 r5 寄存器中。

128 行,调用函数 __create_page_tables 创建页表。
137 行,将函数 __mmap_switched 的地址保存到 r13 寄存器中。 __mmap_switched 定义在文件 arch/arm/kernel/head-common.S __mmap_switched 最终会调用 start_kernel 函数。

144 行 , 调 用 __enable_mmu 函 数 使 能 MMU __enable_mmu 定 义 在 文 件 arch/arm/kernel/head.S 中。 __enable_mmu 最终会通过调用 __turn_mmu_on 来打开 MMU __turn_mmu_on 最后会执行 r13 里面保存的 __mmap_switched 函数。

3.   __mmap_switched 函数

__mmap_switched 函数定义在文件 arch/arm/kernel/head-common.S 中,函数代码如下:
81 __mmap_switched:
82 adr r3, __mmap_switched_data
83 
84 ldmia r3!, {r4, r5, r6, r7}
85 cmp r4, r5 @ Copy data segment if needed
86 1: cmpne r5, r6
87 ldrne fp, [r4], #4
88 strne fp, [r5], #4
89 bne 1b
90 
91 mov fp, #0 @ Clear BSS (and zero fp)
92 1: cmp r6, r7
93 strcc fp, [r6],#4
94 bcc 1b
95 
96 ARM( ldmia r3, {r4, r5, r6, r7, sp})
97 THUMB( ldmia r3, {r4, r5, r6, r7} )
98 THUMB( ldr sp, [r3, #16] )
99 str r9, [r4] @ Save processor ID
100 str r1, [r5] @ Save machine type
101 str r2, [r6] @ Save atags pointer
102 cmp r7, #0
103 strne r0, [r7] @ Save control register values
104 b start_kernel
105 ENDPROC(__mmap_switched)

104 行最终调用 start_kernel 来启动 Linux 内核, start_kernel 函数定义在文件 init/main.c 中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/146604.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Centos7配置firewalld防火墙规则

这里写自定义目录标题 欢迎使用Markdown编辑器一、简单介绍二、特点和功能2.1、区域(Zone)2.2、运行时和永久配置2.3、服务和端口2.4、动态更新2.5、连接跟踪2.6、D-Bus接口 三、设置规则3.1、启动防火墙服务3.2、新建防火墙规则的服务,添加端…

objective-c 基础学习

目录 第一节:OC 介绍 ​​第二节:Fundation 框架 ​第三节:NSLog 相对于print 的增强 ​第四节:NSString ​第五节:oc新增数据类型 第六节: 类和对象 ​类的方法的声明与实现 ​第七节:类…

多叉树+图实现简单业务流程

文章目录 场景整体架构流程业务界面技术细节小结 场景 这次遇到一个需求,大致就是任务组织成方案,方案组织成预案,预案可裁剪调整.预案关联事件等级配置,告警触发预案产生事件.然后任务执行是有先后的,也就是有流程概念. 整体架构流程 方案管理、预案管理构成任务流程的基础条…

28 drf-Vue个人向总结-1

文章目录 前后端分离开发展示项目项补充知识开发问题浏览器解决跨域问题 drf 小tips设置资源root目录使用自定义的user表设置资源路径media数据库补充删除表中数据单页面与多页面模式过滤多层自关联后端提交的数据到底是什么jwt token登录设置普通的 token 原理使用流程解析 jw…

Day_17> 动态内存管理

目录 1.为什么存在动态内存分配? 2.动态内存函数的介绍 malloc calloc realloc 3.常见的动态内存错误 1.对NULL指针的解引用操作 2.对动态开辟空间的越界访问 3.对非动态开辟内存使用free释放 4.使用free释放一块动态开辟内存的一部分 5.对同一块动态内…

QCefView 简介

什么是QCefView QCefView 是为 Qt 开发的一个封装集成了CEF(Chromium Embedded Framework)库的Wdiget UI组件。使用QCefView可以充分发挥CEF丰富强大的Web能力,快速开发混合架构的应用程序。它不需要开发者理解CEF的细节,能够在Qt中更容易的使用CEF&…

深入了解 Linux 中的 AWK 命令:文本处理的瑞士军刀

简介 在Linux和Unix操作系统中,文本处理是一个常见的任务。AWK命令是一个强大的文本处理工具,专门进行文本截取和分析,它允许你在文本文件中查找、过滤、处理和格式化数据。本文将深入介绍Linux中的AWK命令,让你了解其基本用法和…

uboot启动流程-涉及lowlevel_init汇编函数

一. uboot启动流程涉及函数 之前文章简单分析了 uboot启动流程的开始,从链接脚本文件 u-boot.lds 中,我们已经知道了入口点是 arch/arm/lib/vectors.S 文件中的 _start函数。 _start函数:调用了 reset 函数,reset 函数内部&…

Armv8/Armv9 Cache知识大纲分享--思维导图

关键词:cache学习、mmu学习、cache资料、mmu资料、arm资料、armv8资料、armv9资料、 trustzone视频、tee视频、ATF视频、secureboot视频、安全启动视频、selinux视频,cache视频、mmu视频,armv8视频、armv9视频、FF-A视频、密码学视频、RME/CC…

ssm+vue的图书馆书库管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频: ssmvue的图书馆书库管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构…

Cesium实现动态旋转四棱锥(2023.9.11)

Cesium实现动态悬浮旋转四棱锥效果 2023.9.11 1、引言2、两种实现思路介绍2.1 思路一:添加已有的四棱锥(金字塔)模型实现(简单但受限)2.2 思路二:自定义四棱锥几何模型实现(复杂且灵活&#xff…

Leetcode 69.x的平方根

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。 注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。 示例 1&#xff1…

深度学习 二:COVID 19 Cases Prediction (Regression)

Deep Learning 1. 回归算法思路2. 代码2.1 基础操作2.2 定义相关函数2.3.1 定义图像绘制函数2.3.2 数据集加载及预处理2.3.3 构造数据加载器2.3.4 构建前馈神经网络(Feedforward Neural Network)模型2.3.5 神经网络的训练过程2.3.6 模型评估2.3.7 模型测…

ECharts多个数据视图进行自适应大小的解决方案

项目场景: 在制作数据视图时经常会遇到多个数据视图的情况,在多个数据视图的情况下做自适应是比较麻烦的,这里就详细的分析一下该如何去制作,分享一下我的解决办法及思路。 定义 DOM 容器 这里需要注意一个地方,在定…

mac openssl 版本到底怎么回事 已解决

在mac 安装node多版本的时候,有可能把原有的 openssl1.1 版本 直接要再一次升级了,无奈的 php环境 编译器是 openssl 1.1 还是 3.0 ,今天来个底朝天的找问题。 brew search openssl 有安装 三个版本。 但是错误提示 是第二个版本。 brew …

B058-SpringBoot

目录 springboot概念与作用入门案例springboot运行方式热部署配置文件Profile多环境支持整合测试-springboot-testSpringboot-web1.返回json数据2.返回页面(模板技术)thymeleaf1.导入thymeleaf依赖2.模板文件3.controller4.启动类 SSM整合1.导包2.项目目…

【动态规划】动态规划经典例题 力扣牛客

文章目录 跳台阶 BM63 简单跳台阶扩展 JZ71 简单打家结舍 LC198 中等打家劫舍2 LC213中等最长连续递增序列 LC674 简单乘积最大子数组LC152 中等最长递增子序列LC300 中等最长重复子数组LC718最长公共子串NC BM66最长公共子序列LC1143 中等完全平方数LC279零钱兑换 LC322 中等单…

QT的ui设计中改变样式表的用法

在QT的ui设计中,我们右键会弹出一个改变样式表的选项,很多人不知道这个是干什么的。 首先我们来看下具体的界面 首先我们说一下这个功能具体是干嘛的, 我们在设置很多控件在界面上之后,常常都是使用系统默认的样式,但是当有些时候为了美化界面我们需要对一些控件进行美化…

【数据结构】链表与LinkedList

作者主页:paper jie 的博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文录入于《JAVA数据结构》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精…

小程序编译器性能优化之路

作者 | 马可 导读 小程序编译器是百度开发者工具中的编译构建模块,用来将小程序代码转换成运行时代码。旧版编译器由于业务发展,存在编译慢、内存占用高的问题,我们对编译器做了一次大规模的重构,采用自研架构,做了多线…