如何映射1GB(或更多)物理内存

时间:2012-03-09 17:01:29

标签: c linux kernel i386

我有一个2GB内存的设置,我想将1GB(或更多)物理内存映射到用户空间虚拟地址。理论上可行,因为32位设置,3GB的虚拟地址可供用户登陆应用程序使用。

我使用以下参数更新了内核命令行:mem = 1G memmap = 1G $ 1G 强制内核看到1GB的RAM并保留最后的1GB。

我有自定义驱动程序,它将处理用户空间mmap()调用,并使用函数remap_pfn_range()将物理地址0x40000000(1G)映射到用户空间地址。 但该函数在remap_pte_range()中触发内核BUG()。同样的调用过去使用300MB重映射而不是1GB。

我通常在我的驱动程序中调用ioremap()来将物理地址映射到内核虚拟地址。在这种情况下,我不能因为1G / 3G虚拟地址分裂(内核为1G,应用为3G)。所以我想知道是否有可能将物理地址映射到用户空间虚拟地址而不在内核中映射这些物理地址?

提前致谢。

1 个答案:

答案 0 :(得分:5)

为什么你的remap_pfn_range调用会触发内核BUG()

根据here BUG_ONremap_pfn_range中的2277 BUG_ON(addr >= end);宏的调用

remap_pfn_range

remap_pud_range调用remap_pmd_range,调用调用remap_pte_range的{​​{1}}。

来自BUG_ON here

的后续来电VM_BUG_ONremap_pmd_range

2191 VM_BUG_ON(pmd_trans_huge(*pmd));

remap_pte_range here

2171 BUG_ON(!pte_none(*pte));

BUG_ON宏定义为here

作为

#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0)

其中BUG宏定义在it上方以打印邮件并发生恐慌。

unlikely宏定义为here

# define unlikely(x) (__builtin_expect(!!(x), 0))

因此,当从addr开始的目标用户地址大于或等于定义为end的{​​{1}}时,BUG_ON返回1并调用BUG。

end = addr + PAGE_ALIGN(size);定义时here

pmd_trans_huge

返回0,当内核中未配置CONFIG_TRANSPARENT_HUGEPAGE或者 153 #ifdef CONFIG_TRANSPARENT_HUGEPAGE 154 static inline int pmd_trans_splitting(pmd_t pmd) 155 { 156 return pmd_val(pmd) & _PAGE_SPLITTING; 157 } 158 159 static inline int pmd_trans_huge(pmd_t pmd) 160 { 161 return pmd_val(pmd) & _PAGE_PSE; 162 } 163 164 static inline int has_transparent_hugepage(void) 165 { 166 return cpu_has_pse; 167 } (页面元数据)值或pmd

如果相应的条目不存在,& _PAGE_PSE返回1,如果存在,则返回0。

因此pte_none在相应的页表条目不存在时返回0,而另一个则在条件传递到!pte_none时返回。

如果页表条目已存在,则会发生对BUG_ON宏的调用。

如果指定的内存量低于!GB,大于300MB,比如500MB或800MB,会发生什么?

因此,您的起始地址大于结束地址,或者您在内核中未配置BUG,或者您指的是页面元数据不存在或已存在的页表条目。

从评论中澄清,您对CONFIG_TRANSPARENT_HUGEPAGE的引用引用了已指向页表条目或remap_pfn_range的页表条目指针或*pte

这意味着pte会失败,因为pte指针已指向页表条目,因此无法设置为set_pte_at(mm, addr, pte, pte_mkspecial(pfn_pte(pfn, prot))); pte

绕过1G / 3G虚拟地址分割

请参阅以下文章High Memory In The Linux Kernel

请参阅以下邮件列表post,其中讨论了有关至少1GB RAM的HIGHMEM的一些其他信息。

有关将内核和非内核虚拟地址空间映射到用户区的信息

将内核虚拟地址和非内核(由vmalloc()返回)虚拟地址映射到用户空间的一种方法是使用pte_mkspecial(pfn_pte(pfn, prot))。有关其他信息,请参阅Linux Memory Mapping

替换旧内核上nopage处理程序使用的另一种方法是remap_pfn_range函数

其他资源包括:

相关问题