[Crash-utility] kmem: WARNING: cannot find mem_map page for address
Dave Anderson
anderson at redhat.com
Tue Dec 18 22:12:09 UTC 2012
----- Original Message -----
> Hi Dave,
>
> On Tue, Dec 18, 2012 at 6:52 AM, Dave Anderson <anderson at 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
More information about the Crash-utility
mailing list