2016-04-27 484 views

回答

1

按照最初定義的,而現在已經過時(但優秀)的深入理解Linux虛擬內存管理器_bad()宏確定指定的頁表項是否在修改一個合適的狀態不是

然而事實證明宏是不同的體系結構稍有含糊不清,並可能更好arm64作爲確定條目是否確實包含對包含該表爲下一級頁面表頁面的引用來描述 - 見this commit瞭解一些細節。

在@ Notlikethat的答案上擴展時,宏指向'table'位,這反過來(至少在Linux內核使用中,可能有更詳細的架構特定細節)決定了條目的物理地址指大頁面(64KiB--見arm64 memory layout doc)或不大。

如果我們看一下pte_huge()它決定一個網頁條目是否指的是一個巨大的網頁或沒有,我們看到:

#define pte_huge(pte)   (!(pte_val(pte) & PTE_TABLE_BIT)) 

這表明,如果該位被設置頁面大小是4KiB,如果它是清零這是64KiB,因此巨大。

由此得出的結論是,在arm64中,如果使用大頁面,則pXX_bad()宏返回true。

但是,如果巨大的表啓用:)

在上面提到的內存佈局文檔再次找實際上不使用你給的定義,事實證明,巨大的頁表佈局僅使用2級。 Linux處理少於4個頁表級別的體系結構的方式是將不存在的級別「摺疊」到現有表中,並讓編譯器刪除所有不必要的代碼。

如果我們看一下arch/arm64/include/asm/pgtable.h以上pgd_bad()定義(上線445在寫作的時候),我們可以看到:

#if CONFIG_PGTABLE_LEVELS > 3 

和上面pud_bad()定義(關於在寫作的時間線392)我們看到:

#if CONFIG_PGTABLE_LEVELS > 2 

所以實際上因爲在巨大的表的情況下CONFIG_PGTABLE_LEVELS == 2,使用不同的定義。

arch/arm64/include/asm/pgtable-types.h我們看到(在在寫作的時間線89):

#if CONFIG_PGTABLE_LEVELS == 2 
#include <asm-generic/pgtable-nopmd.h> 
#elif CONFIG_PGTABLE_LEVELS == 3 
#include <asm-generic/pgtable-nopud.h> 
#endif 

所以從include/asm-generic/pgtable-nopmd.h實際上定義使用,這本身進口include/asm-generic/pgtable-nopud.h,給我們:

static inline int pgd_bad(pgd_t pgd)   { return 0; } 
static inline int pud_bad(pud_t pud)   { return 0; } 

並且我們已經有:

#define pmd_bad(pmd)   (!(pmd_val(pmd) & 2)) 

其中m意味着任何有pmd_bad()調用的大頁面PMD條目將返回true。然而,如果你看看我上面提到的提交,你會看到在提交之前,_bad()返回true會導致代碼處理'section map'情況,其中大概是PMD包含不同的元數據(我不想要潛水深在這裏:),並使用單獨的代碼,現在通過pmd_sect()處理,我們不在乎pmd_bad()說什麼,如果條目是一個部分地圖。在arch/arm64/mm/mmu.c

來看,pmd_set_huge()(線828在寫作的時候),它看起來像巨大的表的PMD被設置爲部分地圖意味着我們並不需要關心pmd_bad()(我可以在這裏誤會,我沒有深入研究過,也沒有經過調試器,但似乎是這樣。)

所以看起來總體上_bad()案例現在意味着不同的東西 - 它只是表明一個錯誤導致了一些代碼意味着正在處理一個非剖面圖/巨大的頁面表項正在處理一個巨大的剖面圖頁面表項,這顯然需要指出。

注意:由於我創建了一個帳戶只是爲了在這裏回覆,我沒有足夠的信譽來提供更多的鏈接:)一個有更多代表的人可能想要添加他們有意義的鏈接,例如, '在寫作時在XX行'的條目)。

1

在ARMv8 64位頁表描述符的格式,一個有效的(即,第0位組)0級,1或2項,位表和塊(hugepage)條目之間1個判別。因此,如果給定條目具有位1設置,則這些宏將返回false,指示預期的表條目,如果它清楚指示塊或無效條目,則這些宏將返回false。 p*d_val()訪問器只是optionally enforcing type-safety的包裝器。