arm linux啟動過程中的記憶體布局

2021-08-03 02:43:33 字數 1494 閱讀 8920

本文摘錄於:

在arm平台下,zimage.bin壓縮映象是由bootloader載入到物理記憶體,然後跳到zimage.bin裡一段程式,它專門於將被壓縮的kernel解壓縮到kernel_ram_paddr開始的一段記憶體中,接著跳進真正的kernel去執行。該kernel的執行起點是stext函式,定義於arch/arm/kernel/head.s。

在分析stext函式前,先介紹此時記憶體的布局如下圖所示

在開發板tqs3c2440中,sdram連線到記憶體控制器的bank6中,它的開始記憶體位址是0x30000000,大小為64m,即0x20000000。 arm linux kernel將sdram的開始位址定義為phys_offset。經bootloader載入kernel並由自解壓部分**執行後,最終kernel被放置到kernel_ram_paddr(=phys_offset + text_offset,即0x30008000)位址上的一段記憶體,經此放置後,kernel**以後均不會被移動。

在進入kernel**前,即bootloader和自解壓縮階段,arm未開啟mmu功能。因此kernel啟動**乙個重要功能是設定好相應的頁表,並開啟mmu功能。為了支援mmu功能,kernel映象中的所有符號,包括**段和資料段的符號,在鏈結時都生成了它在開啟mmu時,所在物理記憶體位址對映到的虛擬記憶體位址。

以arm kernel第乙個符號(函式)stext為例,在編譯鏈結,它生成的虛擬位址是0xc0008000,而放置它的實體地址為0x30008000(還記得這是phys_offset+text_offset嗎?)。實際上這個變換可以利用簡單的公式進行表示:va = pa – phys_offset + page_offset。arm linux最終的kernel空間的頁表,就是按照這個關係來建立。

之所以較早提及arm linux 的記憶體對映,原因是在進入kernel**,裡面所有符號位址值為清一色的0xc******x位址,而此時arm未開啟mmu功能,故在執行stext函式第一條執行時,它的pc值就是stext所在的記憶體位址(即實體地址,0x30008000)。因此,下面有些**,需要使用位址無關技術。

前面提及到,kernel裡面的所有符號在鏈結時,都使用了虛擬位址值。在完成基本的初始化後,kernel**將跳到第乙個c語言函式start_kernl來執行,在哪個時候,這些虛擬位址必須能夠對它所存放在真正記憶體位置,否則執行將為出錯。為此,cpu必須開啟mmu,但在開啟mmu前,必須為虛擬位址到實體地址的對映建立相應的面表。在開啟mmu後,kernel指並不馬上將pc值指向start_kernl,而是要做一些c語言執行期的設定,如堆疊,重定義等工作後才跳到start_kernel去執行。在此過程中,pc值還是實體地址,因此還需要為這段記憶體空間建立va = pa的記憶體對映關係。當然,本函式建立的所有頁表都會在將來paging_init銷毀再重建,這是臨時過度性的對映關係和頁表。

一口氣將__create_pages_table分析完,但里涉及的**還是需要細細品讀。尤其是右移20位和18位兩個地方與頁表目錄項的位址關係比較複雜。執行完該函式後,虛擬記憶體和物理記憶體的對映關係如下圖所示:

ARM Linux啟動過程分析

5 呼叫 linux核心映像 bootloader完成的最後一項工作便是呼叫 linux核心。如果 linux 核心存放在 flash 中,並且可直接在上面執行 這裡的 flash 指 nor flash 那麼可直接跳轉到核心中去執行。但由於在 flash 中執行 會有種種限制,而且速度也遠不及 r...

ARM Linux啟動過程分析

arm linux啟動過程分析 在 bootloader將 linux 核心映像拷貝到 ram 以後,可以通過下例 啟動linux 核心 call linux 0,machine type,kernel params base 其中,machine tpye是 bootloader檢測出來的處理器型...

詳解 ARM Linux啟動過程分析 2

origin 呼叫 linux核心映像 bootloader完成的最後一項工作便是呼叫 linux核心。如果 linux 核心存放在 flash 中,並且可直接在上面執行 這裡的 flash 指 nor flash 那麼可直接跳轉到核心中去執行。但由於在 flash 中執行 會有種種限制,而且速度也...