Hi Dave,
On Tue, Dec 18, 2012 at 6:52 AM, Dave Anderson <anderson(a)redhat.com> wrote:
#define __page_to_pfn(pg) \
({ const struct page *__pg = (pg); \
int __sec = page_to_section(__pg); \
(unsigned long)(__pg - __section_mem_map_addr(__nr_to_section(__sec))); \
})
Maybe you could play around with emulating that macro w/crash, and see what
comes up?
Hey, that was sure fun. :(
Since "struct page" is another name for "cfs_page_t":
crash> p $tp->page->flags
$9 = 0x200000000000000
"page to section" is a 43 bit right shift:
crash> p ($tp->page->flags >> 43)
$10 = 0x4000
static inline struct mem_section *__nr_to_section(unsigned long nr)
{
if (!mem_section[SECTION_NR_TO_ROOT(nr)])
return NULL;
return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK];
}
There are 16 maps per mem section, so a 4 bit shift and mask yield:
return &mem_section[0x400][0]
crash> p mem_section[0x400]
$13 = (struct mem_section *) 0xffffffff81a26658
crash> p mem_section[0x400][0x0]
$14 = {
section_mem_map = 0xffffffff81a26630,
pageblock_flags = 0xffffffff81a26680
}
So the result of __page_to_pfn is the difference between
crash> p $pg
$24 = (cfs_page_t *) 0xffffea001bb1d1e8
and the return result of
__section_mem_map_addr((struct mem_section *) 0xffffffff81a26658)
static inline struct page *__section_mem_map_addr(struct mem_section
*section)
{
unsigned long map = section->section_mem_map;
map &= SECTION_MAP_MASK;
return (struct page *)map;
}
SECTION_MAP_MASK maps off the low order 3 bits, yielding:
(cfs_page_t *) 0xffffffff81a26630
crash> gdb set $mpg = (cfs_page_t *)0xffffffff81a26630
crash> p ($pg - $mpg)
$32 = 0xffffff9b707721ed
Now what do I do with that number? :) It is the difference between
the numeric values of $pg and $mpg, divided by the size of "struct page"
(which is 0x38 bytes) and sign extended.