enf*_*net 2 kernel memory-management linux-kernel arm64 page-tables
有人可以解释一下内核页表中的宏吗?
#define pgd_bad(pgd) (!(pgd_val(pgd) & 2))
#define pmd_bad(pmd) (!(pmd_val(pmd) & 2))
#define pud_bad(pud) (!(pud_val(pud) & 2))
Run Code Online (Sandbox Code Playgroud)
正如最初定义的那样现在已经过时了(但很好) 了解 Linux 虚拟内存管理器_bad()
宏确定指定的页表条目是否处于不适合修改的状态。
然而,事实证明这些宏在不同架构中有些模糊,最好在 arm64 中描述为确定一个条目是否不包含对包含下一级页表的表的页的引用 -有关详细信息,请参阅此提交。
扩展@Notlikethat 的答案,宏确实引用了“表”位,这反过来(至少在 linux 内核使用中,可能有更详细的特定于体系结构的细节在起作用)确定条目的物理地址是否指向一个巨大的页面(64KiB - 请参阅arm64 内存布局文档)与否。
如果我们查看pte_huge()
which 确定页面条目是否引用大页面,我们会看到:
#define pte_huge(pte) (!(pte_val(pte) & PTE_TABLE_BIT))
Run Code Online (Sandbox Code Playgroud)
这表明如果该位被设置,页面大小是 4KiB,如果它被清除,它是 64KiB,因此是巨大的。
这得出的结论是,在 arm64 中,pXX_bad()
如果使用大页面,宏将返回 true。
但是,如果启用了大表,您给出的定义实际上不会被使用:)
再次查看上面引用的内存布局文档,结果是大页表布局仅使用了 2 个级别。linux 处理少于 4 个页表级别的体系结构的方法是将不存在的级别“折叠”到现有表中,并让编译器删除所有不必要的代码。
如果我们查看arch/arm64/include/asm/pgtable.h
上面的pgd_bad()
定义(在撰写本文时在第 445 行),我们会看到:
#if CONFIG_PGTABLE_LEVELS > 3
Run Code Online (Sandbox Code Playgroud)
在pud_bad()
定义之上(在撰写本文时在第 392 行),我们看到:
#if CONFIG_PGTABLE_LEVELS > 2
Run Code Online (Sandbox Code Playgroud)
所以实际上因为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
Run Code Online (Sandbox Code Playgroud)
所以实际上使用了定义 from 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; }
Run Code Online (Sandbox Code Playgroud)
我们已经有了:
#define pmd_bad(pmd) (!(pmd_val(pmd) & 2))
Run Code Online (Sandbox Code Playgroud)
这意味着任何pmd_bad()
调用它的大页面 PMD 条目都将返回 true。但是,如果您查看我上面提到的提交,您会看到在提交之前,_bad()
返回 true 将导致代码处理“部分映射”情况,其中 PMD 可能包含不同的元数据(我不想要潜水过深在这里:)和单独的代码时,现在的通过处理pmd_sect()
,我们不关心什么pmd_bad()
说,如果该条目是一款地图。
看着arch/arm64/mm/mmu.c
,pmd_set_huge()
(撰写本文时的第 828 行),似乎巨大的表 PMD 被设置为截面图,这意味着我们不需要关心pmd_bad()
(我可能在这里弄错了,我没有深入研究或浏览过)使用调试器,但似乎是这样。)
因此,总体_bad()
而言,现在的情况似乎有所不同 - 它只是表明一个错误导致了一些旨在处理非节映射/巨大页表条目的代码正在处理巨大的节映射页表条目,这显然需要要指出。
注意:由于我创建了一个帐户只是为了在这里回复,我没有足够的声誉来提供更多链接:) 一个有更多代表的好心人可能想在他们有意义的地方添加链接,例如“在第 XX 行”写作时间。)
归档时间: |
|
查看次数: |
1676 次 |
最近记录: |