Arm-Linux二級頁表的問題
在do_page_fault()過程中,有下面函數(shù)會被調(diào)到:
本文引用地址:http://m.butianyuan.cn/article/201611/317851.htm[c]static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval){pmdp[0] = __pmd(pmdval);pmdp[1] = __pmd(pmdval 256 * sizeof(pte_t));flush_pmd_entry(pmdp);}[/c]
它的功能是把在這一個新申請的二級頁表與PMD關(guān)聯(lián)起來。在這之前,pmdp指向的PMD項是空的,當前的過程正是在為它建立映射。在調(diào)用這個函數(shù)之前,已經(jīng)申請好了一張4K大小的二級頁表。
pmdp[0] = __pmd(pmdval); 這一行很容易理解,這是在把根據(jù)pte生成的PMD表項值賦值給PMD項。但是下面這一句是為什么呢?
首先先看一張二級頁表有多大,arm-linux采用的是粗粒度二級頁表映射,使用這種一映射關(guān)系,一個PMD表項下面映射/覆蓋1M內(nèi)存,一個PTE項下面映射/覆蓋4K內(nèi)存,所以一張二級表應(yīng)該有1M/4K=256個表項。而一個二級表項是4字節(jié),所以一張二級表應(yīng)該占用空間256*4=1K字節(jié)。一個4K的內(nèi)存頁可以容納4張二級表。
其次,關(guān)于二級頁表,不知為什么內(nèi)核要為一張二級頁表提供兩份版本(一個Linux版本,一個硬件版本)。而且兩個版本的表的位置關(guān)系定義得很別扭??磒galloc.h中的一個注釋圖:
從上(低地址)到下(高地址)分別是:第一張表的硬件版本、第二張表的硬件版本,第一張表的Linux版本、第二張表的Linux版本??梢?,同一張表的linux版本和硬件版本是不連續(xù)的,但兩張不同表的同一版本是連續(xù)的。我想,把這樣的4張表放在一起,正是為了向4K的頁面大小對齊,不至于浪費空間。
這樣,一切就都好理解了。上述函數(shù)中,接下來這一行:
pmdp[1] = __pmd(pmdval 256 * sizeof(pte_t));
正是把第二張硬件表的對應(yīng)的PMD值寫到接下來的一個PMD表項中去。
這個函數(shù)實際上是完成了兩張二級表的映射。
評論