Fix-Mapped Addresses

來源:互聯網
上載者:User

標籤:section   begin   檢查   參考   描述   編譯   指定   loader   不能   

一、前言

某天,wowo同學突然來了一句:如果要在start_kernel中點LED,ioremap在什麼時間點才能調用呢?我想他應該是想通過點LED燈來調試start_kernel之後的初始化的代碼(例如DTB解析部分的代碼)。那天,我們兩個花了二十分鐘的時間,討論相關的問題,我覺得很有意思,因此決定寫fix mapped address這樣的一份文檔。

在彙編代碼中,由於沒有開啟MMU,想怎麼訪問外設都很簡單,直接使用物理地址即可,然而,進入start kernel之後(開啟了MMU),想要訪問硬體都是那麼的不方便,至少需要通過ioremap擷取了虛擬位址之後才可以訪問。但是,實際上,在核心的啟動的初始階段,記憶體管理子系統還沒有ready,ioremap還不能調用(在mm_init之後可以正常使用)。

實際上,這個需求是和early ioremap模組相關,此外,還有一些其他的需求,核心合并了這些需求並提出了fix mapped address的概念。本文就是描述關於fix mapped address的方方面面,BTW,本文的代碼來自4.4.6核心,體繫結構相關的代碼依然選擇的是ARM64。

 

二、什麼是fixmap?

Fix map中的fix指的是固定的意思,那麼固定什麼東西呢?其實就是虛擬位址是固定的,也就是說,有些虛擬位址在編譯(compile-time)的時候就固定下來了,而這些虛擬位址對應的物理地址不是固定的,是在kernel啟動過程中被確定的。為了方便大家理解fixmap,我們提供一個具體的例子:DTB image的處理。

實際上DTB的處理一開始並沒有使用fixmap,而是放在了kernel image附近。更具體的要求是必須放在kernel image起始地址的512M內,8位元組對齊,dtb image不能越過2M section size的邊界。之所以這麼要求,主要是想借用kernel image頁表的“東風”,反正建立kernel image所需要的PGD/PUD/PMD頁表都已經靜態分配了,對dtb image的要求可以不需要建立新的頁表,只是在原有的頁表中增加一個entry而已,不過這樣的設計存在下面的問題:

(1)對dtb image的位置有限制,不是很靈活(誰不想自由自在呢?bootload copy dtb img的時候當然想了無牽掛啊)。

(2)對dtb image的位置檢查在head.S中,需要彙編實現(誰想寫彙編啊,用c實現多買易懂啊,可維護性,可移植性多麼好啊)。

現在,既然核心有了early fixmap的支援,那麼上面的限制都可以放寬了。整個dtb image的處理過程如下:

(1)bootloader copy dtb image到memory的某個位置上。具體的位置隨便,當然還是要滿足8位元組對齊,dtb image不能越過2M section size的邊界的要求,畢竟我們也想一條section mapping就搞定dtb image。

(2)bootload通過寄存器x0傳遞dtb image的物理地址,dtb image的虛擬位址在編譯kernel image的時候就確定了。

(3)彙編初始化階段不對dtb image做任何處理

(4)在start kernel之後的初始化代碼中(具體在setup_arch--->setup_machine_fdt中),建立dtb image的相關Translation tables,之後就可以自由的訪問dtb image了。

 

三、為何有fixmap這個概念?

動態分配虛擬位址以及建立地址映射是一個複雜的過程,在核心完全啟動之後,記憶體管理可以提供各種豐富的API讓核心的其他模組可以完成虛擬位址分配和建立地址映射的功能,但是,在核心的啟動過程中,有些模組需要使用虛擬記憶體並mapping到指定的物理地址上,而且,這些模組也沒有辦法等待完整的記憶體管理模組初始化之後再進行地址映射。因此,linux kernel固定分配了一些fixmap的虛擬位址,這些地址有固定的用途,使用該地址的模組在初始化的時候,講這些固定分配的地址mapping到指定的物理地址上去。

最直觀的需求來自初始化代碼的調試,想一想當我們來到start_kernel的時候我們面臨的處境:

(1)我們不能訪問全部的記憶體,只能訪問kernel image附近的memory。

(2)我們不能訪問任何的硬體,所有的io memory還沒有mapping

想要通過串口控制台輸出錯誤資訊?sorry,現在離console驅動的初始化還早著呢。想點個LED燈看看核心運行情況?sorry,ioremp函數需要kmalloc分配記憶體,但是夥伴系統還沒有初始化呢。怎麼辦?一個最簡潔的方法就是簡化虛擬記憶體的分配和管理(ioremp中使用的管理虛擬記憶體地址的方法太重了),而最簡單的方法就是fix virtual address。

 

四、fixmap的具體位置在那裡?

fixmap的地址地區位於FIXADDR_START和FIXADDR_TOP之間,具體可以參考:

中,紅色框的block就是fixmap address的具體位置。

 

五、fixmap具體應用在哪些情境?

fixmap的地址地區有被進一步細分,如下:

enum fixed_addresses {
    FIX_HOLE, 
    FIX_FDT_END,
    FIX_FDT = FIX_FDT_END + FIX_FDT_SIZE / PAGE_SIZE - 1,

    FIX_EARLYCON_MEM_BASE,
    FIX_TEXT_POKE0,
    __end_of_permanent_fixed_addresses,

    FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
    FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
    __end_of_fixed_addresses
};

由定義可知,fixmap地址地區又分成了兩個部分,一部分叫做permanent fixed address,是用於具體的某個核心模組的,使用關係是永久性的。另外一個叫做temporary fixed address,各個核心模組都可以使用,用完之後就釋放,模組和虛擬位址之間是動態關係。

permanent fixed address主要涉及的模組包括:

(1)dtb解析模組。

(2)early console模組。標準的串口控制台驅動的初始化在整個kernel初始化過程中是很靠後的事情了,如果能夠在kernel啟動階段的初期就有一個console,能夠輸出各種debug資訊是多買美妙的事情啊,early console就能滿足你的這個願望,這個模組是使用early param來初始化該模組的功能的,因此可以很早就投入使用,從而協助工程師瞭解核心的啟動過程。

(3)動態打補丁的模組。本文段一般都被映射成read only的,該模組可以使用fix mapped address來映射RW的本文段,從動態修改程式本文段,從而完成動態打補丁的功能。

temporary fixed address主要用於early ioremap模組。linux kernel在fix map地區的虛擬位址空間中開了FIX_BTMAPS_SLOTS個的slot(每個slot的size是NR_FIX_BTMAPS),核心中的模組都能夠通過early_ioremap、early_iounmap的介面來申請或者釋放對某個slot 虛擬位址的使用。

Fix-Mapped Addresses

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.