linux 核心移植(五) head S檔案分析

2021-09-20 14:10:03 字數 2543 閱讀 3389

這裡的核心源**是根據九鼎科技為s5pvx210開發板移植好的核心來分析的

1:核心執行的實體地址與虛擬位址

(1)kernel_ram_vaddr(vaddr就是virtual address),這個巨集定義了核心執行時的虛擬位址。值為0xc0008000

(2)kernel_ram_paddr(paddr就是physical address),這個巨集定義核心執行時的物   理位址。值為0x30008000

(3)總結:核心執行的實體地址是0x30008000,對應的虛擬位址是0xc0008000。而實體地址為什麼是30008000是因為在移植uboot的時候為了得到連續的512m的記憶體,將記憶體位址的開頭設定為30000000

2:核心的真正入口

(1)核心的真正入口就是entry(stext)處

(2)前面的__head定義了後面的**屬於段名為.head.text的段

3:核心執行的硬體條件

(1) 核心的起始部分**是被解壓**呼叫的。回憶之前講zimage的時候,uboot啟動核心後實際呼叫執行的是zimage前面的那段未經壓縮的解壓**,解壓**執行時先將zimage後段的核心解壓開,然後再去呼叫執行真正的核心入口。

(2) 核心啟動不是無條件的,而是有一定的先決條件,這個條件由啟動核心的bootloader(我們這裡就是uboot)來構建保證。

(3) arm體系中,函式呼叫時實際是通過暫存器傳參的(函式呼叫時傳參有兩種設計:一種是暫存器傳參,另一種是棧記憶體傳參)。所以uboot中最後thekernel (0, machid, bd->bi_boot_params);執行核心時,執行時實際把0放入r0中,machid放入到了r1中,bd->bi_boot_params放入到了r2中。arm的這種處理技巧剛好滿足了kernel啟動的條件和要求。

(4) kernel啟動時mmu是關閉的,因此硬體上需要的是實體地址。但是核心是乙個整體(zimage)只能被連線到乙個位址(不能分散載入),這個連線位址肯定是虛擬位址。因此核心執行時前段head.s中尚未開啟mmu之前的這段**就很難受。所以這段**必須是位置無關碼,而且其中涉及到操作硬體暫存器等時必須使用實體地址。

4:核心啟動的彙編階段

__lookup_processor_type

(1) 我們從cp15協處理器的c0暫存器中讀取出硬體的cpu id號,然後呼叫這個函式來進行合法性檢驗。如果合法則繼續啟動,如果不合法則停止啟動,轉向__error_p啟動失敗。

(2) 該函式檢驗cpu id的合法性方法是:核心會維護乙個本核心支援的cpu id號碼的陣列,然後該函式所做的就是將從硬體中讀取的cpu id號碼和陣列中儲存的各個id號碼依次對比,如果沒有乙個相等則不合法,如果有乙個相等的則合法。

(3) 核心啟動時設計這個校驗,也是為了核心啟動的安全性著想。                                     

__lookup_machine_type

該函式的設計理念和思路和上面校驗cpu id的函式一樣的。不同之處是本函式校驗的是機器碼。

__vet_atags

(1) 該函式的設計理念和思路和上面2個一樣,不同之處是用來校驗uboot給核心的傳參atags格式是否正確。這裡說的傳参指的是uboot通過tag給核心傳的引數(主要是板子的記憶體分布memtag、uboot的bootargs)

(2) 核心認為如果uboot給我的傳參格式不正確,那麼我就不啟動。

(3) uboot給核心傳參的部分如果不對,是會導致核心不啟動的。譬如uboot的bootargs設定不正確核心可能就會不啟動。

__create_page_tables

(1) 顧名思義,這個函式用來建立頁表。

(2) linux核心本身被連線在虛擬位址處,因此kernel希望盡快建立頁表並且啟動mmu進入虛擬位址工作狀態。但是kernel本身工作起來後頁表體系是非常複雜的,建立起來也不是那麼容易的。kernel想了乙個好辦法

(3) kernel建立頁表其實分為2步。第一步,kernel先建立了乙個段式頁表(和uboot中之前建立的頁表一樣,頁表以1mb為單位來區分的),這裡的函式就是建立段式頁表的。段式頁表本身比較好建立(段式頁表1mb乙個對映,4gb空間需要4096個頁表項,每個頁表項4位元組,因此一共需要16kb記憶體來做頁表),壞處是比較粗不能精細管理記憶體;第二步,再去建立乙個細頁表(4kb為單位的細頁表),然後啟用新的細頁表廢除第一步建立的段式對映頁表。

(4) 核心啟動的早期建立段式頁表,並在核心啟動前期使用;核心啟動後期就會再次建立細頁表並啟用。等核心工作起來之後就只有細頁表了。

__switch_data

(1) 建立了段式頁表後進入了__switch_data部分,這東西是個函式指標陣列。

(2) 分析得知下一步要執行__mmap_switched函式

(3) 複製資料段、清除bss段(目的是構建c語言執行環境)

(4) 儲存起來cpu id號、機器碼、tag傳參的首位址。

(5) b start_kernel跳轉到c語言執行階段。

總結:彙編階段其實也沒幹啥,主要原因是uboot幹了大部分活。彙編階段主要就是校驗啟動合法性、建立段式對映的頁表並開啟mmu以方便使用記憶體、跳入c階段。

來自:朱老師物聯網大講堂筆記

linux核心head S檔案分析

1 kernel ram vaddr vaddr就是virtual address 這個巨集定義了核心執行時的虛擬位址。值為0xc0008000 2 kernel ram paddr paddr就是physical address 這個巨集定義核心執行時的物 理位址。值為0x30008000 3 總...

linux核心移植

1.基本開發環境 u boot版本 u boot 2012.04.01 假設u boot已經移植好 linux平台 虛擬機器下ubuntu 14.04 交叉編譯工具 gcc 4.4.3 arm開發板 mini2440 cpu s3c2440 sdram 64m,nor flash 2m,nand f...

Linux核心移植

實驗步驟 1 準備工作 2 修改頂層makefile 3 修改falsh 分割槽 4 配置編譯核心 下面以linux2.6.30.4核心移植到gec2440為例 cd linux 2.6.30.4 解壓後會在當前目錄下生成乙個linux 2.6.30.4 的核心原始碼目錄 安裝交叉工具鏈,然後修改環...