Linux 核心高-低端記憶體設定程式碼跟蹤(ARM構架)

發表於2016-11-13

對於ARM中核心如何在啟動的時候設定高低端記憶體的分界線(也是邏輯地址與虛擬地址分界線(虛擬地址)減去那個固定的偏移),這裡我稍微引導下(核心分析使用Linux-3.0):

首先定位設定核心虛擬地址起始位置(也就是核心邏輯地址末端+1的地址)的檔案:init.c (arch\arm\mm),在這個檔案中的void __init bootmem_init(void)函式如下

這個high_memory = __va(((phys_addr_t)max_low << PAGE_SHIFT) – 1) + 1;語句就是關鍵。從這裡可以知道max_low就是高階記憶體的起始地址(實體地址)。那麼這個max_low是如何得到的?其實看上面的程式碼可以推測出,他其實是在find_limits(&min, &max_low, &max_high);中(在同一個檔案中)被設定的:

這個函式的意思很明顯:通過掃描struct meminfo *mi = &meminfo;(結構體meminfo的陣列)中的所有資訊,設定三個指標所指的變數:

min :記憶體實體地址起始
max_low :低端記憶體區實體地址末端
max_high :高階記憶體區實體地址末端

從上面可以看出,max_low和max_high所儲存的地址不同就是由於bank->highmem造成的,它是記憶體bank被設為高階記憶體的依據:

“如果這個記憶體bank是高階記憶體(bank->highmem != 0),跳過max_low = end;語句,max_low和max_high將不同(結果實際上是max_high > max_low);
否則假設沒有一個記憶體bank是高階記憶體(所有bank->highmem == 0)max_low和max_high必然一致(高階記憶體大小為0)”

當然要實現這個函式的功能,必須保證meminfo所指陣列中的所有bank是按照地址資料從小到大排序好的哦~~。但是這個大家不用擔心,後面會看到的:)

經過上面的跟蹤,焦點集中到了全域性變數(同一個檔案中):

/*
* This keeps memory configuration data used by a couple memory
* initialization functions, as well as show_mem() for the skipping
* of holes in the memory map. It is populated by arm_add_memory().
*/
struct meminfo meminfo;

這個結構體的定義(setup.h (arch\arm\include\asm)):

只要找到初始化這個全域性變數並完成排序的地方,就可以知道高階記憶體是如何配置的了!!OK,明確目標,go on~~~

通過查詢程式碼,我們可以在setup.c (arch\arm\kernel)這個檔案中找到相關的程式碼。在系統啟動早期會執行的函式(具體的順序你可以自行分析下ARM核心的啟動流程,以後我也會寫下)中有這樣一個函式:

在上面的註釋中,我已經表明了重點和解析,下面我細化下:

(1)獲取引數部分

通過parse_early_param();函式可以解析核心啟動引數中的許多字串,但是對於我們這次分析記憶體的話主要是分析以下兩個引數:
mem=size@start引數,她為初始化struct meminfo meminfo;(我們一直關注的記憶體資訊哦~)提供資訊。具體的獲取資訊的函式(同樣位於setup.c (arch\arm\kernel))

vmalloc=size引數,她為初始化vmalloc_min(需要保留的核心虛擬地址空間大小,也就是這個核心虛擬地址空間中除去邏輯地址空間和必要的防止越界的保護空洞後最少要預留的地址空間)提供資訊。具體的實現函式(位於mmu.c (arch\arm\mm)):

(2)在獲得了必要的資訊(初始化好struct meminfo meminfo和vmalloc_min)後,核心通過sanity_check_meminfo函式自動去通過vmalloc_min資訊來初始化每個meminfo.bank[?]中的highmem成員。此過程中如果有必要,將可能會改變meminfo中的bank陣列。處理函式位於mmu.c (arch\arm\mm)

(3)最後必須做的就是排序了,完成了這個工作就可以完全被我們上面提到的find_limits函式使用了,而這個工作就放在了接下來的arm_memblock_init(&meminfo, mdesc);中的一開頭:

通過上面的分析,整個高低端記憶體是如何確定的基本就清晰了,這裡總結一下:

ARM構架中,高-低段記憶體是核心通過核心啟動引數( mem=size@start和vmalloc=size)來自動配置的,如果沒有特殊去配置他,那麼在普通的ARM系統中是不會有高階記憶體存在的。除非你係統的RAM很大或vmalloc配置得很大,就很可能出現高階記憶體。

以上是我對高-低端記憶體學習時跟蹤程式碼的備忘,如果大家在其中發現什麼不對的地方,歡迎拍磚、糾正~~謝謝~

相關文章