內核啓動前需要滿足的條件(寄存器,CPU,Cache、MMU):
1. CPU寄存器的設置:
①R0 = 0
②R1爲機器碼
③R2爲啓動參數,標記列表在RAM中的起始地址
2.CPU工作模式
①必須禁止中斷(IRQ和FIQ)
②CPU必須設置爲SVC模式
3.Cache和MMU的設置
①MMU必須關閉
②指令Cache可以打開或關閉
③數據Cache必須關閉
Linux 內核啓動過程
Linux的啓動過程分爲兩部分:
1.架構、開發板相關的引導過程。
2.後續的通用啓動過程。
ARM架構處理器上Linux內核vmlinux的啓動過程,之所以說是vmlinux,是因爲其他格式的內核在進行與vmlinux相同的流程之前會有一些獨特的操作。比如:對於壓縮格式的內核zImage,首先進行自解壓得到vmlinux,然後執行vmlinux開始的“正常”啓動流程。
引導階段通常使用匯編語言編寫,步驟:
1. 它首先檢查內核是否支持當前的處理器架構
2. 然後檢查是否支持當前開發板,通過檢查後
3. 就爲調用下一階段的start_kernel函數做準備了
①連接內核時使用的是虛擬地址,所以要設置頁表、使能MMU
②調用C函數start_kernel之前的常規工作,包括複製數據段,清楚BSS段,調用start_kernel函數
第二階段的關鍵代碼主要使用C語言編寫。它進行內核初始化的全部工作,最後調用rest_init函數啓動init過程,創建系統第一個進程:init進程。在第二階段,仍有部分架構/開發板相關的代碼,比如setup_arch函數用於進行架構/開發板相關的設置(比如重新設置頁表,設置系統時鐘,初始化串口等)。
head.s文件中:
ENTRY(stext)
__lookup_processor_type --->arch/arm/kernel/head.S
__lookup_machine_type ---> arch/arm/kernel/head-common.S
__create_page_tables ---> arch/arm/kernel/head.S
__cpu_flush ---> arch/arm/kernel/head.S
__enable_mmu ---> arch/arm/kernel/head.S
__switch_data --->arch/arm/kernel/head-common.S
start_kernel --->/init/main.c
start_kernel --->/init/main.c
rest_init --->/init/main.c
kernel_init --->/init/main.c
init_post --->/init/main.c
__lookup_processor_type: 確定內核是否支持該架構
__lookup_machine_type:確定內核是否支持該單板
__create_page_tables:建立一級頁表
__arm920_setup:禁止ICache、Dcache
__enable_mmu:使能MMU
__mmap_switched:複製數據段,清楚BSS段,設置棧指針,保存CPU ID到processor_id變量,保存機器類型ID到__machine_arch_type變量,調用start_kernel
init/main.c的start_kernel函數
printk(linux_version):輸出Linux版本信息
setup_arch:設置與體系結構相關的環境
...
console_init:初始化控制檯
...
rest_init:啓動init過程