匯編啟動(dòng)流程
先從整體分析匯編做的事情,有個(gè)大體框架。
路徑:arch/riscv/kernel/head.S
,入口是ENTRY(_start_kernel)
從ENTRY(_start_kernel)
開(kāi)始進(jìn)行啟動(dòng)前的一些初始化,建立頁(yè)表前的主要工作:
- 關(guān)閉所有中斷
/* 關(guān)閉所有中斷 */
csrw CSR_IE, zero
csrw CSR_IP, zero
- 加載全局指針gp
/* 加載全局指針gp */
.option push
.option norelax
la gp, __global_pointer$
.option pop
- disable FPU
/* 禁用 FPU 以檢測(cè)內(nèi)核空間中浮點(diǎn)的非法使用*/
li t0, SR_FS
csrc CSR_STATUS, t0
- 選擇一個(gè)核啟動(dòng)
/* 選擇一個(gè)核啟動(dòng) */
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
- 設(shè)置sp指針
la sp, init_thread_union + THREAD_SIZE
- 上述工作完成,會(huì)開(kāi)始臨時(shí)頁(yè)表的創(chuàng)建,跳轉(zhuǎn)到C函數(shù)setup_vm建立臨時(shí)頁(yè)表
mv a0, s1
call setup_vm // 跳轉(zhuǎn)到C函數(shù)setup_vm,setup_vm會(huì)創(chuàng)建臨時(shí)頁(yè)表
- 重定向
#ifdef CONFIG_MMU
la a0, early_pg_dir
call relocate //重定向,實(shí)際就是開(kāi)啟MMU
#endif
- 設(shè)置異常向量地址,重載C環(huán)境
call setup_trap_vector
/* 重載C環(huán)境 */
la tp, init_task
sw zero, TASK_TI_CPU(tp)
la sp, init_thread_union + THREAD_SIZE
- 最后跳轉(zhuǎn)到C函數(shù)start_kernel,開(kāi)始C語(yǔ)言部分初始化,匯編部分執(zhí)行完畢
tail start_kernel
完整_start_kernel匯編代碼:
ENTRY(_start_kernel)
/* 關(guān)閉所有中斷 */
csrw CSR_IE, zero
csrw CSR_IP, zero
/* 在源碼中,這里有一個(gè)M模式處理的宏,這里沒(méi)有用到,直接跳過(guò)*/
/* 加載全局指針gp */
.option push
.option norelax
la gp, __global_pointer$
.option pop
/* 禁用 FPU 以檢測(cè)內(nèi)核空間中浮點(diǎn)的非法使用*/
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
/* 選擇一個(gè)核啟動(dòng) */
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)
/* 初始化頁(yè)表,然后重定向到虛擬地址 */
la sp, init_thread_union + THREAD_SIZE
mv a0, s1
call setup_vm // 跳轉(zhuǎn)到C函數(shù)setup_vm,setup_vm會(huì)創(chuàng)建臨時(shí)頁(yè)表
#ifdef CONFIG_MMU
la a0, early_pg_dir
call relocate //重定向,實(shí)際就是開(kāi)啟MMU
#endif /* CONFIG_MMU */
call setup_trap_vector
/* 重載C環(huán)境 */
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 //跳轉(zhuǎn)到C函數(shù)start_kernel,開(kāi)始C語(yǔ)言部分初始化
匯編中非常重要的一個(gè)部分就是頁(yè)表的創(chuàng)建,關(guān)乎著后面的程序能不能繼續(xù)往下跑。setup_vm創(chuàng)建頁(yè)表后就會(huì)開(kāi)始執(zhí)行relocate重定向,這個(gè)重定向主要開(kāi)啟mmu,下面分析relocate的匯編。
-
Linux
+關(guān)注
關(guān)注
87文章
11430瀏覽量
212444 -
指針
+關(guān)注
關(guān)注
1文章
484瀏覽量
70936 -
匯編
+關(guān)注
關(guān)注
2文章
214瀏覽量
26371
發(fā)布評(píng)論請(qǐng)先 登錄
嵌入式Linux的啟動(dòng)流程簡(jiǎn)介
Linux的啟動(dòng)流程是怎樣的
詳細(xì)分析嵌入式Linux系統(tǒng)啟動(dòng)流程
Linux文件系統(tǒng)啟動(dòng)流程
linux內(nèi)核啟動(dòng)流程

詳解bootloader的執(zhí)行流程與ARM Linux啟動(dòng)過(guò)程分析

嵌入式 Linux 啟動(dòng)流程和 bootloader 介紹

嵌入式Linux專(zhuān)題(一)——嵌入式Linux系統(tǒng)構(gòu)成及啟動(dòng)流程

【IAR下的匯編】IAR下的匯編/單片機(jī)啟動(dòng)代碼匯編

Linux內(nèi)核啟動(dòng)流程(上)

Linux啟動(dòng)流程中console_init分析

評(píng)論