----- Original Message ----- > Hi Dave, > > On Tue, Dec 18, 2012 at 6:52 AM, Dave Anderson <anderson@xxxxxxxxxx> > 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 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility