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

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

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

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

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

提前致谢。


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

在呼叫BUG_ONremap_pfn_range按这里

2277 BUG_ON(addr >= end);

remap_pfn_range调用remap_pud_range ,它调用remap_pmd_range ,它调用remap_pte_range

随后在这里从remap_pmd_range调用BUG_ONVM_BUG_ON

2191 VM_BUG_ON(pmd_trans_huge(*pmd));

并从这里remap_pte_range

2171 BUG_ON(!pte_none(*pte));

这里定义了BUG_ON

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

在其上定义BUG宏以打印消息和恐慌。

在这里定义unlikely

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

所以当在addr开始的目标用户地址大于或等于end ,它被定义为end = addr + PAGE_ALIGN(size); ,BUG_ON返回1并调用BUG。

或者当这里定义的pmd_trans_huge

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 }

返回0,这发生在内核中未配置CONFIG_TRANSPARENT_HUGEPAGE时,或者如果pmd (Page Metadate)值或& _PAGE_PSE

或者当pte_none在相应条目不存在时返回1,如果存在则返回0。

因此!pte_none在相应的页表条目不存在时返回0,并且在条件传递到BUG_ON

如果页表项已经存在,则发生对BUG宏的调用。

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

因此,无论您的起始地址是否大于您的结束地址,或者CONFIG_TRANSPARENT_HUGEPAGE未在内核中配置,或者您所指的页面元数据不存在或页表项已存在。

从注释中澄清,您对remap_pfn_range的调用引用了已经指向页表项或pte Page Table Entry指针或*pte pte

这意味着set_pte_at(mm, addr, pte, pte_mkspecial(pfn_pte(pfn, prot))); 将会失败,因为pte指针已经指向一个页表项,因此不能设置为pte_mkspecial(pfn_pte(pfn, prot))pte

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

请参阅以下文章Linux内核中的高内存

请参阅以下邮件列表文章,其中讨论了有关HIGHMEM的至少1GB内存的其他信息。

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

将内核虚拟地址和非内核映射到用户空间的一种方法是使用remap_pfn_range 。 有关更多信息,请参阅Linux内存映射。

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

其他资源包括:

  • 内核空间 - 用户空间接口
  • DeviceDriverMmap Linux内存管理Wiki
  • 驱动程序页面重新映射的演变
  • 错误填充(),nopfn()和nopage()
  • 了解Linux虚拟内存管理器
  • 适用于Linux驱动程序的Mmap
  • Linux设备驱动程序第3版第15.1章。 内存管理在Linux中
  • Linux设备驱动程序第3版第15.2章。 mmap设备操作
  • Linux设备驱动程序第3版第15.4章。 直接内存访问
  • Linux设备驱动程序第3版第9.4章。 使用I / O内存
  • 链接地址: http://www.djcxy.com/p/70315.html

    上一篇: How to map 1GB (or more) of physical memory

    下一篇: Prototype Kernel and modules