【发布时间】:2013-03-10 17:24:28
【问题描述】:
我正在编写一个需要将特定物理地址映射到特定虚拟地址的 Linux 内核模块,但我就是找不到方法。
【问题讨论】:
标签: linux memory kernel memory-address
我正在编写一个需要将特定物理地址映射到特定虚拟地址的 Linux 内核模块,但我就是找不到方法。
【问题讨论】:
标签: linux memory kernel memory-address
好的,这是我目前的解决方案。要将phys_addr 映射到virt_addr,我使用以下代码:
page = pfn_to_page(virt_addr >> PAGE_SHIFT);
pte = get_locked_pte(&init_mm, phys_addr, &ptl);
set_pte_at(&init_mm, phys_addr, pte, mk_pte(page, VM_READ | VM_WRITE | VM_EXEC));
spin_unlock(ptl);
flush_tlb_all();
一些解释:我使用pfn_to_page func 来获取与我的virt_addr 对应的页面结构。我得到带有get_locked_pte 函数的页表条目(pte),它需要对应于所需pte 的物理地址和一个未初始化的自旋锁(ptl)。然后,我实际上使用set_pte_at func 和mk_pte 宏映射页面,解锁自旋锁并刷新tlb 缓存。
这个解决方案似乎工作得很好,尽管它无法在上下文切换中存活。
【讨论】:
能否告诉我们您正在使用的内核版本和 CPU 架构/类型?一般来说,如果您要映射到的具体虚拟地址不与内核虚拟地址重叠(例如0xC0000000),并且如果您的设备正在使用的物理地址与系统内存物理地址范围不重叠,您可以使用低级函数(如果没有,您可以在内核启动期间使用汇编语言直接设置 MMU TLB 条目)设置 MMU TLB 条目以在内核启动期间将特定地址映射到特定的虚拟地址。我可以提供一个基于 2.6.10 内核版本和 Freescale PowerPC CPU 的示例,有一个函数 io_block_mapping 可以做你想做的事情。
【讨论】: