我有一个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)。所以我想知道是否有可能将物理地址映射到用户空间虚拟地址而不在内核中映射这些物理地址?
提前致谢。
答案 0 :(得分:5)
为什么你的remap_pfn_range调用会触发内核BUG()
根据here BUG_ON
对remap_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_ON
或remap_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
函数
其他资源包括: