4

I'm using vmalloc_to_pfn() to get the physical address on a 32-bit PAE Linux system. It looks like vmalloc_to_pfn() returns "unsigned long" which means it is 32 bit on a 32 bit system, 64 bit on a 64-bit system. On 64-bit Linux, unsigned long is 64 bit and I've no issues.

Problem: Using this function to convert virtual to physical:

VA: 0xf8ab87fc PA using vmalloc_to_pfn: 0x36f7f7fc. But I'm actually expecting: 0x136f7f7fc.

The physical address falls between 4 to 5 GB. But I can't get the exact physical address, I only get the chopped off 32-bit address. Is there another way to get true physical address?

4

1 回答 1

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 x 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()可能不是获取物理地址的全部内容。

于 2014-02-25T11:44:30.410 回答