vmalloc_to_pfn returns 32 bit address on Linux 32 system. Why does it chop off higher bits of PAE physical address?

若如初见. 提交于 2019-12-01 22:03:21

问题


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?


回答1:


I am myself studying this, and am on 32 bit - so this is not exactly an answer. But digging through the same stuff, I can see the source for vmalloc_to_pfn says:

/*
 * 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);

So, it should not actually return an address - it should return a "page frame number" (PFN). In relation to that:

http://www.tldp.org/LDP/tlk/mm/memory.html

Using the above example again, process Y's virtual page frame number 1 is mapped to physical page frame number 4 which starts at 0x8000 (4 x 0x2000). Adding in the 0x194 byte offset gives us a final physical address of 0x8194.

So apparently, one should multiply the PFN by PAGE_SIZE to get an actual address - which then makes it strange, how come you got "returns 32 bit address on Linux 32 system" to work at all (but then again, I'm no expert - maybe PFN is equivalent to an address for 32 bit?). Probably a minimal working example of a module in the question OP, and output on both platforms for comparison, would have been in order.

In any case, I just have noticed what you have - that Physical Address Extension (PAE) may make a difference in paging; apparently, the value stored as a PFN in Page Global Directory (PGD) is architecture-specific, and is defined differently depending on it:

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

To summarize - just using vmalloc_to_pfn() is probably not the whole story in getting the physical address.



来源:https://stackoverflow.com/questions/11442773/vmalloc-to-pfn-returns-32-bit-address-on-linux-32-system-why-does-it-chop-off-h

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!