----- Original Message -----
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. :(
It's a nightmare, isn't it?
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.
The $mpg value would also have to resolve to a vmemmap address (ffffea00...),
which would have to be smaller in value than your $pg address of 0xffffea001bb1d1e8
in order for it to make sense.
So, you show that you stripped off 3 bits from something (not shown) in order
to get the $mpg of 0xffffffff81a26630 -- which should be derived from the
section_mem_map member of the mem_section at address 0xffffffff81a26658.
What did the mem_section structure look like? In other words:
crash> struct mem_section 0xffffffff81a26658
struct mem_section {
section_mem_map = <vmemmap-addr-you-need-to-strip-3-bits-from>
...
Here's an example mem_section:
crash> struct mem_section ffff88021e5eb000 -x
struct mem_section {
section_mem_map = 0xffffea0000000003,
pageblock_flags = 0xffff88021e1eaa00,
page_cgroup = 0xffff880215880000,
pad = 0x0
}
where the section_mem_map field contains a vmemmap address plus a few
flag bits in the lower byte.
Dave