我需要从内核中保留大量物理上连续的 RAM 缓冲区,并且能够保证该缓冲区将始终使用特定的硬编码物理地址。这个缓冲区应该为内核的整个生命周期保留。我已经编写了一个 chardev 驱动程序作为在用户空间中访问此缓冲区的接口。我的平台是一个带有 ARMv7 架构的嵌入式系统,运行 2.6 Linux 内核。
Linux Device Drivers, Third Edition的第 15 章有以下关于该主题的内容(第 443 页):
保留 RAM 的顶部是通过
mem=
在引导时向内核传递一个参数来完成的。例如,如果您有 256 MB,则该参数mem=255M
会阻止内核使用最高兆字节。您的模块稍后可以使用以下代码来访问此类内存:dmabuf = ioremap (0xFF00000 /* 255M */, 0x100000 /* 1M */);
我已经做到了,还有其他几件事:
memmap
除了那个之外,我还在使用bootargmem
。内核引导参数文档建议在使用时始终使用memmap
以mem
避免地址冲突。- 我
request_mem_region
在调用之前使用过ioremap
,当然,我在继续之前检查它是否成功。
这是我完成所有这些后系统的样子:
# cat /proc/cmdline
root=/dev/mtdblock2 console=ttyS0,115200 init=/sbin/preinit earlyprintk debug mem=255M memmap=1M$255M
# cat /proc/iomem
08000000-0fffffff : PCIe Outbound Window, Port 0
08000000-082fffff : PCI Bus 0001:01
08000000-081fffff : 0001:01:00.0
08200000-08207fff : 0001:01:00.0
18000300-18000307 : serial
18000400-18000407 : serial
1800c000-1800cfff : dmu_regs
18012000-18012fff : pcie0
18013000-18013fff : pcie1
18014000-18014fff : pcie2
19000000-19000fff : cru_regs
1e000000-1fffffff : norflash
40000000-47ffffff : PCIe Outbound Window, Port 1
40000000-403fffff : PCI Bus 0002:01
40000000-403fffff : 0002:01:00.0
40400000-409fffff : PCI Bus 0002:01
40400000-407fffff : 0002:01:00.0
40800000-40807fff : 0002:01:00.0
80000000-8fefffff : System RAM
80052000-8045dfff : Kernel text
80478000-80500143 : Kernel data
8ff00000-8fffffff : foo
到目前为止一切看起来都不错,我的驱动程序运行良好。我可以直接读写我选择的特定物理地址。
然而,在启动过程中,触发了一个可怕的警告( ™<sup>):
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 ]---
/*
* 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 leads\n"
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);
}
这究竟会导致什么问题?它们可以减轻吗?我的替代方案是什么?