【问题标题】:Linux - Mapping user space memory in kernel codeLinux - 在内核代码中映射用户空间内存
【发布时间】:2012-11-15 04:42:23
【问题描述】:

我正在编写一段代码,该代码需要在 SOC 关闭之前存储位于特定物理地址的 10k 内存。

我的问题是这个物理地址不是内核空间的一部分,所以我必须创建一个临时内存映射,这样我才能访问这个内存空间。

我尝试使用 io-remap,但它(显然)不适用于非内核空间。

是否有任何 API 可以做到这一点? 我应该使用 kmap 吗?

提前致谢

【问题讨论】:

  • 您能否确定在引导期间(在 U-​​Boot 函数中)要保留哪些内存区域,在(有效)内存列表中排除这些区域,然后编写一个驱动程序来实际映射并使用该“特殊的“记忆”? stackoverflow.com/questions/11580285/…
  • 我可以在启动过程中从 ATAG 中排除内存,但是如何映射这些区域? ioremap 以前似乎不起作用。也许是因为该区域是不同内存空间的一部分?
  • "io-remap ... 不 ... 在非内核空间上工作" - “内核”和“用户”内存空间参考 虚拟内存。 ioremap() 必须提供一个物理地址范围。请注意,在没有虚拟或物理限定词的情况下使用“内存”一词可能会产生歧义或混淆。也许您需要重新审视和分析为什么ioremap() 似乎没有“工作”。这是另一个涉及为内核驱动程序使用物理内存的问答:stackoverflow.com/questions/12516603/…
  • @JonathanLeffler - 您的编辑,尤其是“此物理地址在用户空间中”,毫无意义,并且可能错误地陈述了问题。
  • @sawdust:好的;然后修复它,请。没关系,我会把它回滚,让别人试一试。

标签: linux memory-management linux-kernel memory-mapping mmu


【解决方案1】:

听起来像内存映射外围设备。为了紧密绑定到您的内核中,它会将条目添加到 initdata 中,该条目将转到 iotable_init()。例如arch/arm/mach-vexpress/ct-ca9x4.c ct_ca9x4_io_desc[]。这会创建虚拟到物理的映射。然后内核代码可以使用带有虚拟地址的 writel 在那里写入。

【讨论】:

  • 实际上地址空间是每个 DRAM 芯片选择的前 10k,这些可能会根据板设置而改变。所以,我必须在运行时这样做。我无法在编译时告诉地址空间位置。
  • stackoverflow.com/questions/7894160/… 中有一些很好的信息。但是注意“这是一个非常复杂的编程领域,你不可能在如此有限的空间里得到你需要的答案……”
【解决方案2】:

找到答案

关键是使用为给定页表创建映射的 vmap 函数。问题是如何将页表结构初始化为某个物理地址,但似乎也存在一个 API

这里是一个分配单个页面的例子

void *virt_addr_ptr
struct page **my_page = kmalloc(sizeof (*my_page), GFP_KERNEL);
my_page = phys_to_page(phys_addr_ptr);
virt_addr_ptr = vmap(my_page, 1, VM_MAP, PAGE_KERNEL);

/*now its possible to access this space */
memcpy(store_buffer, virt_addr_ptr, store_size);

【讨论】:

  • 您是在用户空间还是在内核模块中执行此操作?
  • 希望这篇文章对编辑来说不会太死。 my_page = phys_to_page(phys_addr_ptr); 应该是 *my_page = phys_to_page(phys_addr_ptr);,因为 phys_to_page() 的返回是 struct page *
猜你喜欢
  • 2014-06-10
  • 2015-12-22
  • 2014-02-15
  • 2014-01-14
  • 2021-10-29
  • 2016-03-10
  • 2011-05-02
  • 2015-06-26
  • 2016-05-05
相关资源
最近更新 更多