加入星計劃,您可以享受以下權益:

  • 創(chuàng)作內容快速變現
  • 行業(yè)影響力擴散
  • 作品版權保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 作者簡介
    • 01、背景介紹
    • 02、環(huán)境說明
    • 03、虛擬空間拓撲  
    • 04、小結
    • 05、參考文獻
  • 相關推薦
  • 電子產業(yè)圖譜
申請入駐 產業(yè)圖譜

Fixmap機制深入分析

2021/05/26
490
閱讀需 13 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

作者簡介

于浩進,linux內核愛好者,現就職于北京靈汐科技有限公司,任職BSP工程師,主要負責IP驗證、多媒體驅動開發(fā)及一些bring up等工作。

文章大綱

1.背景介紹

2.環(huán)境說明

2.1 硬件環(huán)境

2.2 Kernel 版本

2.3 kernel 相關配置介紹

3.fixmap 機制介紹

3.1 虛擬空間拓撲

3.1.1 VA=39bit 下 kernel 虛擬地址空間拓撲
3.1.2 FIXMAP 地址空間拓撲
3.1.3 FIXMAP 初始化

3.2 fixmap 在 early ioremap 應用介紹

3.2.1 early_ioremap_setup()

3.2.2 __early_ioremap()

3.3 fixmap 在 early console 應用介紹

3.4 fixmap 在 device-tree 應用介紹

3.4.1 映射過程分析

3.5 fixmap 在 paging_init 中頁表切換介紹

3.5.1 paging_init 函數簡單分析
3.5.2 paging_init 中的 fixmap
 

4.小結

5.參考文章

01、背景介紹

Fixmap機制是kernel在啟動過程中(start_kernel)臨時的映射機制,目的是在真正頁表建立之前用于完成對io設備的訪問、device-tree的解析以及paging_init中的頁表切換等。本文將對該機制做一個深入的分析。

02、環(huán)境說明

2.1硬件環(huán)境

某SOC芯片CPU為8核cortex-A53,其DDR物理地址為0x800000000,device-tree存放的物理地址為0x843000000。

2.2kernel版本

4.19.83版本。

2.3kernel相關配置介紹

相關Config配置

相關宏配置

        以下宏的值,只給出結果了:

03、虛擬空間拓撲  

3.1虛擬空間拓撲

3.1.1 VA=39bit下kernel虛擬地址空間拓撲

圖1詳細展示了VA=39bit下kernel虛擬地址空間拓撲,里面展示了FIXMAP區(qū)域在整個虛擬地址空間所處的位置。

3.1.2 FIXMAP地址空間拓撲

Kernel對Fixmap區(qū)域做了進一步的劃分,各區(qū)間是在enum fixed_addresses 枚舉類型定義的(/arch/arm64/include/asm/fixmap.h)。

其各個區(qū)間的virtual address通過fix_to_virt(const unsigned int idx)函數獲得,其定義是在/include/asm-generic/fixmap.h里面,這個函數后面會用到。

下圖2詳細展示了各個區(qū)間的base address。

Fix_to_virt的定義如下:

3.1.3 FIXMAP初始化

Bm_pte、bm_pmd、Bm_pte為三個全局數組,用于暫存pud、pmd、

pte的頁表。

early_fixmap_init()函數完成了fixmap映射的基礎框架,如下圖3所示,bm_pte數組并沒有填值,因為當前還不知道哪些物理地址需要映射,等需要映射時候再去填寫bm_pte的entry。

經過分析代碼,整理了fixmap各段虛擬地址與bm_pmd entry的關系,如下圖4所示:

需要說明的是FIX_PGD~FIX_FDT在bm_pmd是屬于同一個entry,即可以用bm_pte做pte映射。

FIX_FDT~FIX_HOLE不屬于該entry,即不可以用bm_pte做pte映射,也為后面device-tree的映射做了一個鋪墊。

3.2fixmap在early ioremap應用介紹

3.2.1 early_ioremap_setup()

該函數的比較簡單,主要是依靠__fix_to_virt()給slot_virt[i]填入虛擬地址,其布局如下圖5所示。

slot[i]是fix_map區(qū)域已經規(guī)劃好的虛擬地址范圍,任何I/O地址空間都可以向這7個slot空間做映射。

其中:slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i),__fix_to_virt()在之前已經介紹過。Slot_virt每個區(qū)間size為256K。

3.2.2 __early_ioremap()

有三個數組需要說明:

slot_virt[slot]:BTMAP區(qū)域各個區(qū)間虛擬地址;

prev_map[slot]:__early_ioremap()映射后的虛擬地址;

prev_size[slot]:__early_ioremap()要映射的size;

映射流程如下圖6所示:

Figure 6 early ioremap映射流程圖

圖7展示了early ioremap頁表轉換過程,還是比較簡單的。

3.3fixmap在early console應用介紹

Early console的映射與early ioremap的映射類似,通過__fix_to_vit(FIX_EARLYCON_MEM_BASE)獲取虛擬地址,物理地址為UART在SOC的實際分配的地址(該物理地址來自于command line的earlycon=XXX),然后通過向bm_pte寫入頁表,即可以完成映射。

圖8是函數調用關系。圖9是頁表的建立和轉換過程。

3.4 fixmap在device-tree應用介紹

3.4.1 映射過程分析

Device-tree的映射和early-console、early-ioremap的映射原理有所不同,主要區(qū)別在于FIX_FDT空間對應的虛擬地址的pmd entry與FIXADDR_START對應的pmd entry是不同的。

通過分析kernel代碼可知對于device-tree的映射需要建立一個2M的block entry即可,即在bm_pmd建立一個block entry。

如下圖10所示,只需要找到pmdp,寫入block entry的頁表項即可。

那問題來了,pmdp的虛擬地址我們是知道的,對應的bm_pmd的entry的物理地址也能知道,但是兩者之間的頁表還未建立。

因此在用pmdp指針向bm_pmd寫入block entry之前,必須要先建立pmdp的頁表,這個頁表建立過程就與early console的頁表建立過程相同了。見下圖11所示。

設備樹頁表的建立會調用到init_pmd()建立block entry,也就是下圖12圈2對應的代碼,圈1的代碼就是對應上圖11給pmdp建立頁表的過程。

在寫入block entry之后,pmdp也就無用了,圈3代碼把剛才的pmdp的頁表清除了,即把bm_pte對應的表項清除了。

 

最后再簡單展示一下fixmap為設備樹建立頁表的函數調用關系,如下圖13所示。

3.5fixmap在paging_init中頁表切換介紹

3.5.1 paging_init函數簡單分析

下圖14是paging_init的代碼分析。

圈1代碼通過memblock分配器分配了一個物理頁面,該頁面暫存后面代碼建立的頁表;

圈2代碼是通過fixmp機制把這個物理頁面映射為虛擬地址;

圈3代碼把kernel的鏡像的一些代碼段、數據做等做映射,在圖1有說明;

圈4代碼把memblock.memory類型的region區(qū)域做線性映射,比如設備樹的memory節(jié)點的內存,會在此做線性映射,但是會排除代碼段和只讀數據段,具體細節(jié),還請看源碼;

圈5~圈7代碼將暫存頁表內容拷貝到swapper_pg_dir,同時切換ttbr寄存器,此后CPU發(fā)出的虛擬地址就可以通過這套新建的頁表進行虛實轉換了;

圈8清除pgdp的映射;

圈9代碼釋放剛才申請的物理頁;

3.5.2 paging_init中的fixmap

上圖 圈6代碼是把臨時頁表拷貝到swapper_pg_dir,臨時頁表的物理頁是memblock分配器獲得的物理地址。

由于mmu已經開啟,memcpy無法使用物理地址,所以必須要先用fixmap機制做該物理頁面的映射,得到其虛擬地址,即pgd_set_fixmap(addr),其定義如下:

其是借助于fixmp的“FIX_PGD”區(qū)域做的映射,頁表映射及轉換過程如下圖15所示。

04、小結

在進入start_kernel之前,head.S的“__primary_switch”已經開啟mmu了,使能mmu之后CPU發(fā)出的ldr、str指令都為虛擬地址了,因此必須要提前建立好頁表,mmu才能把虛擬地址轉為物理地址,以訪問真正的物理內存;

Fixmap用于在” earlyconsole”、” device-tree的解析”、” earlyioremap”、” paging_init的頁表切換”等過程建立臨時頁表。

Fixmap機制實際就是為mmu做了相關的虛擬和物理地址的映射;

Bm_pmd、bm_pte是兩個全局數組,用于存放pmd、pte的頁表項;

05、參考文獻

https://www.cnblogs.com/LoyenWang/p/11483948.html

https://www.cnblogs.com/LoyenWang/p/11440957.html

https://www.cnblogs.com/pengdonglin137/p/9157639.html

相關推薦

電子產業(yè)圖譜

專業(yè)的Linux技術社區(qū)和Linux操作系統(tǒng)學習平臺,內容涉及Linux內核,Linux內存管理,Linux進程管理,Linux文件系統(tǒng)和IO,Linux性能調優(yōu),Linux設備驅動以及Linux虛擬化和云計算等各方各面.