汇编启动流程
先从整体分析汇编做的事情,有个大体框架。
路径:arch/riscv/kernel/head.S
,入口是ENTRY(_start_kernel)
从ENTRY(_start_kernel)
开始进行启动前的一些初始化,建立页表前的主要工作:
- 关闭所有中断
/* 关闭所有中断 */
csrw CSR_IE, zero
csrw CSR_IP, zero
- 加载全局指针gp
/* 加载全局指针gp */
.option push
.option norelax
la gp, __global_pointer$
.option pop
- disable FPU
/* 禁用 FPU 以检测内核空间中浮点的非法使用*/
li t0, SR_FS
csrc CSR_STATUS, t0
- 选择一个核启动
/* 选择一个核启动 */
la a3, hart_lottery
li a2, 1
amoadd.w a3, a2, (a3)
bnez a3, .Lsecondary_start
- 清楚bss段
/* 清除bss */
la a3, __bss_start
la a4, __bss_stop
ble a4, a3, clear_bss_done
- 保存hart id和dtb地址
/* 保存hatr id和dtb地址,hart id保存到a0,dtb地址保存到a1 */
mv s0, a0
mv s1, a1
la a2, boot_cpu_hartid
- 设置sp指针
la sp, init_thread_union + THREAD_SIZE
- 上述工作完成,会开始临时页表的创建,跳转到C函数setup_vm建立临时页表
mv a0, s1
call setup_vm // 跳转到C函数setup_vm,setup_vm会创建临时页表
- 重定向
#ifdef CONFIG_MMU
la a0, early_pg_dir
call relocate //重定向,实际就是开启MMU
#endif
- 设置异常向量地址,重载C环境
call setup_trap_vector
/* 重载C环境 */
la tp, init_task
sw zero, TASK_TI_CPU(tp)
la sp, init_thread_union + THREAD_SIZE
- 最后跳转到C函数start_kernel,开始C语言部分初始化,汇编部分执行完毕
tail start_kernel
完整_start_kernel汇编代码:
ENTRY(_start_kernel)
/* 关闭所有中断 */
csrw CSR_IE, zero
csrw CSR_IP, zero
/* 在源码中,这里有一个M模式处理的宏,这里没有用到,直接跳过*/
/* 加载全局指针gp */
.option push
.option norelax
la gp, __global_pointer$
.option pop
/* 禁用 FPU 以检测内核空间中浮点的非法使用*/
li t0, SR_FS
csrc CSR_STATUS, t0
#ifdef CONFIG_SMP
li t0, CONFIG_NR_CPUS
blt a0, t0, .Lgood_cores
tail .Lsecondary_park
.Lgood_cores:
#endif
/* 选择一个核启动 */
la a3, hart_lottery
li a2, 1
amoadd.w a3, a2, (a3)
bnez a3, .Lsecondary_start
/* 清除bss */
la a3, __bss_start
la a4, __bss_stop
ble a4, a3, clear_bss_done
clear_bss:
REG_S zero, (a3)
add a3, a3, RISCV_SZPTR
blt a3, a4, clear_bss
clear_bss_done:
/* 保存hatr id和dtb地址,hart id保存到a0,dtb地址保存到a1 */
mv s0, a0
mv s1, a1
la a2, boot_cpu_hartid
REG_S a0, (a2)
/* 初始化页表,然后重定向到虚拟地址 */
la sp, init_thread_union + THREAD_SIZE
mv a0, s1
call setup_vm // 跳转到C函数setup_vm,setup_vm会创建临时页表
#ifdef CONFIG_MMU
la a0, early_pg_dir
call relocate //重定向,实际就是开启MMU
#endif /* CONFIG_MMU */
call setup_trap_vector
/* 重载C环境 */
la tp, init_task
sw zero, TASK_TI_CPU(tp)
la sp, init_thread_union + THREAD_SIZE
#ifdef CONFIG_KASAN
call kasan_early_init
#endif
/* Start the kernel */
call soc_early_init
tail start_kernel //跳转到C函数start_kernel,开始C语言部分初始化
汇编中非常重要的一个部分就是页表的创建,关乎着后面的程序能不能继续往下跑。setup_vm创建页表后就会开始执行relocate重定向,这个重定向主要开启mmu,下面分析relocate的汇编。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
-
Linux
+关注
关注
87文章
11236浏览量
209024 -
指针
+关注
关注
1文章
480浏览量
70519 -
汇编
+关注
关注
2文章
214浏览量
25912
发布评论请先 登录
相关推荐
Linux文件系统启动流程
与 Linux 命令的结合使用Linux 文件系统启动流程sysvinit服务的管理与裁剪systemd服务的管理与裁剪了解 qt4、qt5 的移植了解 yocto构建文件系统常规
发表于 12-17 06:00
linux内核启动流程
Linux的启动代码真的挺大,从汇编到C,从Makefile到LDS文件,需要理解的东西很多。毕竟Linux内核是由很多人,花费了巨大的时间和精力写出来的。而且直到现在,这个世界上仍然
发表于 11-14 16:19
•4342次阅读
嵌入式 Linux 启动流程和 bootloader 介绍
目录嵌入式 Linux 启动流程简介启动流程Bootloader 简介市面上可见的 bootloader入式
发表于 11-01 16:32
•11次下载
嵌入式Linux专题(一)——嵌入式Linux系统构成及启动流程
本文简单的介绍了什么是嵌入式系统,以及嵌入式Linux的系统结构,并且简单的介绍了Linux的启动流程
发表于 11-02 12:36
•15次下载
Linux内核启动流程(上)
本文先讲解上篇,大家看到汇编不用担心看不懂,在内核启动阶段,没有特别复杂的流程,都是顺序执行,只需一句一句阅读代码即可。
发表于 06-23 14:07
•1612次阅读
Linux启动流程中console_init分析
console_init 分析 Linux 启动函数 start_kernel 会调用 console_init 函数。 linux4.14/kernel/printk/printk.
评论