我正在使用 vmalloc_to_pfn()来获取32位PAE Linux系统上的物理地址。看起来vmalloc_to_pfn()返回“unsigned long”,这意味着它在32位系统上是32位,在64位系统上是64位。在64位Linux上,unsigned long是64位,我没有问题。
问题: 使用此功能将虚拟转换为物理:
VA: 0xf8ab87fc PA使用vmalloc_to_pfn: 0x36f7f7fc 。但我实际上是在期待: 0x136f7f7fc 。
物理地址介于4到5 GB之间。但我无法得到确切的物理地址,我只能得到切断的32位地址。是否有其他方法可以获得真实的实际地址?
答案 0 :(得分:0)
我自己正在研究这个问题,而且我是32位 - 所以这不是一个答案。但仔细研究相同的东西,我可以看到vmalloc_to_pfn
的来源说:
/*
* Map a vmalloc()-space virtual address to the physical page frame number.
*/
unsigned long vmalloc_to_pfn(const void *vmalloc_addr)
{
return page_to_pfn(vmalloc_to_page(vmalloc_addr));
}
EXPORT_SYMBOL(vmalloc_to_pfn);
因此,它实际上不应该返回一个地址 - 它应该返回一个“页面帧号”(PFN)。与此相关:
http://www.tldp.org/LDP/tlk/mm/memory.html
再次使用上面的例子,进程Y的虚拟页面帧号1被映射到物理页面帧号4,其开始于0x8000(4×0x2000)。添加0x194字节偏移量给出了最终的物理地址0x8194。
显然,人们应该将PFN乘以PAGE_SIZE
以得到一个实际地址 - 然后让它变得奇怪,你怎么得到“在Linux 32系统上返回32位地址”完全工作(但话说再说一遍,我不是专家 - 也许PFN相当于一个32位的地址?)。可能是问题OP中模块的最小工作示例,以及两个平台上用于比较的输出都是有序的。
在任何情况下,我只是注意到你拥有的东西 - 物理地址扩展(PAE)可能会对分页产生影响;显然,在页面全局目录(PGD)中存储为PFN的值是特定于体系结构的,并且根据它的不同定义:
typedef unsigned long pgdval_t; // arch/x86/include/asm/pgtable-2level_types.h
typedef u64 pgdval_t; // arch/x86/include/asm/pgtable-3level_types.h
typedef unsigned long pgdval_t; // arch/x86/include/asm/pgtable_64_types.h
总结一下 - 仅仅使用vmalloc_to_pfn()
可能不是获取实际地址的全部故事。