我正在编写一个 Linux 内核模块,该模块需要将特定的物理地址映射到特定的虚拟地址,但我只是找不到方法。
问问题
1052 次
2 回答
2
好的,这是我目前的解决方案。要映射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
. 我得到了页表条目 ( pte
) 和get_locked_pte
func,它需要与想要的物理地址pte
和未初始化的自旋锁 ( ptl
) 相对应的物理地址。set_pte_at
然后,我实际上使用func 和宏映射页面mk_pte
,解锁自旋锁并刷新 tlb 缓存。
这个解决方案似乎工作得很好,尽管它不能在上下文切换中存活下来。
于 2013-04-02T07:48:13.073 回答
0
您能告诉我们您正在使用的内核版本和 CPU 架构/类型吗?一般来说,如果您要映射到的具体虚拟地址不与内核虚拟地址重叠(例如0xC0000000),并且如果您的设备正在使用的物理地址与系统内存物理地址范围不重叠,您可以使用低级函数(如果没有,您可以在内核启动期间使用汇编语言直接设置 MMU TLB 条目)设置 MMU TLB 条目以在内核启动期间将特定地址映射到特定的虚拟地址。我可以提供一个基于 2.6.10 内核版本和 Freescale PowerPC CPU 的示例,有一个函数 io_block_mapping 可以做你想做的事情。
于 2013-03-21T10:36:11.483 回答