我正在编写一个Linux内核模块,需要将特定的物理地址映射到特定的虚拟地址,而我却找不到办法。
答案 0 :(得分: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
func的页表条目{get_locked_pte
),该func需要与所需pte
对应的物理地址和未初始化的自旋锁(ptl
)。然后,我实际使用set_pte_at
func和mk_pte
宏映射页面,解锁自旋锁并刷新tlb缓存。
这个解决方案似乎运行得很好,但它不能在上下文切换后继续存在。
答案 1 :(得分:0)
您能告诉我们您使用的内核版本和CPU架构/类型吗?一般来说,如果要映射到的特定虚拟地址与内核虚拟地址(例如0xC0000000)不重叠,并且如果设备使用的物理地址与系统内存物理地址范围不重叠,则可以使用低级函数(如果没有,您可以使用汇编语言在内核启动期间直接设置MMU TLB条目)来设置MMU TLB条目,以在内核启动期间将特定地址映射到特定的虚拟地址。我可以提供一个基于2.6.10内核版本和飞思卡尔PowerPC CPU的示例,有一个函数io_block_mapping来做你想要的事情。