匯編啟動流程
先從整體分析匯編做的事情,有個大體框架。
路徑: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文章
11292瀏覽量
209326 -
指針
+關注
關注
1文章
480瀏覽量
70551 -
匯編
+關注
關注
2文章
214瀏覽量
25927
發布評論請先 登錄
相關推薦
Linux文件系統啟動流程
與 Linux 命令的結合使用Linux 文件系統啟動流程sysvinit服務的管理與裁剪systemd服務的管理與裁剪了解 qt4、qt5 的移植了解 yocto構建文件系統常規
發表于 12-17 06:00
linux內核啟動流程
Linux的啟動代碼真的挺大,從匯編到C,從Makefile到LDS文件,需要理解的東西很多。畢竟Linux內核是由很多人,花費了巨大的時間和精力寫出來的。而且直到現在,這個世界上仍然
發表于 11-14 16:19
?4352次閱讀
嵌入式 Linux 啟動流程和 bootloader 介紹
目錄嵌入式 Linux 啟動流程簡介啟動流程Bootloader 簡介市面上可見的 bootloader入式
發表于 11-01 16:32
?11次下載
嵌入式Linux專題(一)——嵌入式Linux系統構成及啟動流程
本文簡單的介紹了什么是嵌入式系統,以及嵌入式Linux的系統結構,并且簡單的介紹了Linux的啟動流程
發表于 11-02 12:36
?15次下載
Linux內核啟動流程(上)
本文先講解上篇,大家看到匯編不用擔心看不懂,在內核啟動階段,沒有特別復雜的流程,都是順序執行,只需一句一句閱讀代碼即可。
發表于 06-23 14:07
?1651次閱讀
Linux啟動流程中console_init分析
console_init 分析 Linux 啟動函數 start_kernel 會調用 console_init 函數。 linux4.14/kernel/printk/printk.
評論