? ? ? ? 通過 Linux 的構建系統,即 Linux 源代碼的根目錄下的 Makefile,能夠找到 vmlinux 的鏈接文件,從而能夠查看其入口代碼 head.S:_start, 如下:
? ? ? ? Linux 構建系統主Makefile:
?? ? ? ? vmlinux.lds:
? ? ? ? head.S:
? ? ? ? 找到該入口后,就可以開始讀匯編代碼了。
????????head.S 的代碼解析有很多相關文章,感興趣的讀者可以自行搜索,這里就不一一細說了,因為本系列的文章主要關注在虛擬內存的機制,head.S 是一個鋪墊。
? ? ? ? 推薦:
????????RISCVlinuxkernel啟動代碼分析之一:啟動匯編部分代碼
????????Linux內核riscv head.S分析
????????即,在 relocate_enable_mmu中的?csrw CSR_SATP, a0 前,linux 都是使用物理地址的,之后全使用虛擬地址。
? ? ? ? 簡單來說,從 _start 開始,linux kernel 做了以下動作:
1. 跳入 _start_kernel:
2. 屏蔽所有中斷:
3. 使能 S mode 下的 time CSR。
4.? 加載 global pointer
5. 失效浮點和向量操作
6. 零化(zero initialize) BSS:
7. 保存 啟動核 id:
8. 初始化頁表:其中,
????????tp 為 (task_struct *) init_task,即第一個進程描述結構, PID = 0。
? ? ? ? sp 為其棧地址,為了調用 c 函數 setup_vm。
? ? ? ? a0 為 dtb地址 。
? ? ? ? setup_vm 的函數原型為?asmlinkage void __init setup_vm(uintptr_t dtb_pa); 。
? ? ? ? setup_vm 主要是初始化了:
? ? ? ? 1.?struct kernel_mapping kernel_map __ro_after_init;
? ? ? ? 2.?pgd_t early_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
? ? ? ? 3.?pgd_t trampoline_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
9.??啟動虛擬地址訪問:
10. 設置中斷異常入口,準備C環境,調用 soc 初始化,最終進入 start_kernel (Linux 的 main 函數)。
????????至此,head.S 的功能大致如此,下一篇文章就開始詳細地描述 setup_vm 函數,以及?trampoline_pg_dir 、early_pg_dir 的作用。