linux – 为什么我不应该在ARMv6的系统内存上使用ioremap?
我需要从内核中保留一个物理连续RAM的大缓冲区,并且能够保证缓冲区将始终使用特定的硬编码物理地址.此缓冲区应保留为内核的整个生命周期.我编写了一个chardev驱动程序作为用户空间中访问此缓冲区的接口.我的平台是一个嵌入式系统,ARMv7架构运行2.6
Linux内核.
有关该主题(第443页)的第15章(共Linux Device Drivers,Third Edition页):
我已经完成了这个以及其他一些事情: >除了mem之外,我还在使用memmap bootarg. kernel boot parameters documentation建议在使用mem时始终使用memmap以避免地址冲突. 这是我完成所有这些后系统的样子: # cat /proc/cmdline root=/dev/mtdblock2 console=ttyS0,115200 init=/sbin/preinit earlyprintk debug mem=255M memmap=1M$255M # cat /proc/iomem000-0fffffff : PCIe Outbound Window,Port 0 到目前为止,一切看起来都很好,我的司机工作得很好.我能够直接读取和写入我选择的特定物理地址. 但是,在启动过程中,触发了一个很大的可怕警告(?): BUG: Your driver calls ioremap() on system memory. This leads to architecturally unpredictable behaviour on ARMv6+,and ioremap() will fail in the next kernel release. Please fix your driver. ------------[ cut here ]------------ WARNING: at arch/arm/mm/ioremap.c:211 __arm_ioremap_pfn_caller+0x8c/0x144() Modules linked in: [] (unwind_backtrace+0x0/0xf8) from [] (warn_slowpath_common+0x4c/0x64) [] (warn_slowpath_common+0x4c/0x64) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null+0x1c/0x24) from [] (__arm_ioremap_pfn_caller+0x8c/0x144) [] (__arm_ioremap_pfn_caller+0x8c/0x144) from [] (__arm_ioremap_caller+0x50/0x58) [] (__arm_ioremap_caller+0x50/0x58) from [] (foo_init+0x204/0x2b0) [] (foo_init+0x204/0x2b0) from [] (do_one_initcall+0x30/0x19c) [] (do_one_initcall+0x30/0x19c) from [] (kernel_init+0x154/0x218) [] (kernel_init+0x154/0x218) from [] (kernel_thread_exit+0x0/0x8) ---[ end trace 1a4cab5dbc05c3e7 ]--- 触发自:arc/arm/mm/ioremap.c /* * Don't allow RAM to be mapped - this causes problems with ARMv6+ */ if (pfn_valid(pfn)) { printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory. This leadsn" KERN_WARNING "to architecturally unpredictable behaviour on ARMv6+,and ioremap()n" KERN_WARNING "will fail in the next kernel release. Please fix your driver.n"); WARN_ON(1); } 确切地说,这会导致什么问题?他们能减轻吗?我有什么选择? 解决方法
提供内核命令行(例如/ proc / cmdline)和生成的内存映射(即/ proc / iomem)来验证这一点.
在系统内存上使用ioremap()的问题是,您最终会将冲突的属性分配给内存,从而导致“不可预测”的行为.
请注意,“系统内存”是由内核管理的RAM.
您必须确保您想要ioremap()的RAM不是“系统内存”,即由内核管理. 附录 关注您的此警告是pfn_valid(pfn)返回TRUE而不是FALSE的结果. memblock_is_memory(pfn << PAGE_SHIFT); 这反过来只是返回结果 memblock_search(&memblock.memory,addr) != -1; 我建议破解内核代码,以便揭示冲突. static int __init_memblock memblock_search(struct memblock_type *type,phys_addr_t addr) { unsigned int left = 0,right = type->cnt; do { unsigned int mid = (right + left) / 2; if (addr < type->regions[mid].base) right = mid; else if (addr >= (type->regions[mid].base + type->regions[mid].size)) left = mid + 1; - else + else { + if (memblock_debug) + pr_info("MATCH for 0x%x: m=0x%x b=0x%x s=0x%xn",+ addr,mid,+ type->regions[mid].base,+ type->regions[mid].size); return mid; + } } while (left < right); return -1; } 如果要查看所有内存块,请使用变量memblock_debug调用memblock_dump_all()为TRUE. [有趣的是,这实际上是一个编程问题,但我们还没有看到你的任何代码.] 附录2 由于您可能正在使用ATAG(而不是设备树),并且您想要专用内存区域,请修复ATAG_MEM以反映这种较小的物理内存大小. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |