Takao Indoh wrote:
On Tue, 06 Feb 2007 13:52:37 -0500, Dave Anderson wrote:

>How about changing section #3 above to something like this?:
>
>                 *  to the section with that page
>                 */
>                if (mi->flags & ADDRESS_SPECIFIED) {
>-                       ulong pfn = mi->spec_addr >> PAGESHIFT();
>+                       ulong pfn;
>+                       physaddr_t tmp;
>+
>+                       if (pg_spec) {
>+                               if (!page_to_phys(mi->spec_addr, &tmp))
>+                                       return;
>+                               pfn = tmp >> PAGESHIFT();
>+                       } else
>+                               pfn = mi->spec_addr >> PAGESHIFT();
>                        section_nr = pfn_to_section_nr(pfn);
>                }
>

Thanks, it looks good, but I found another problem.

I applied your patch and tested kmem command.

crash> kmem -p e000000105090000
      PAGE        PHYSICAL      MAPPING       INDEX CNT FLAGS

It seems kmem command entered infinite loop. It is another problem.
I found page_to_phys did not return correct physical address.
When mi->spec_addr is 0xe000000105090000, corresponding physical address
is 0x180000000.

> crash> kmem -p | grep e000000105090000
> e000000105090000 180000000      -------       -----   0 600200080000

However, page_to_phys returns 0x100000000. I think page_to_phys does not
support sparsemem system.

Takao Indoh

Yeah, something's not right.  I tested the patch on an x86_64,
and passed it the page addresses of the first page struct in each
sparsmem section, and it looks like it works OK:

crash> hex
output radix: 16 (hex)
crash> kmem -n

NODE    SIZE      PGLIST_DATA       BOOTMEM_DATA       NODE_ZONES
  0    262080   ffff81000000b000  ffffffff804a2e00  ffff81000000b000
                                                    ffff81000000bb00
                                                    ffff81000000c600
                                                    ffff81000000d100
    MEM_MAP       START_PADDR  START_MAPNR
ffff810009001000       0            0

ZONE  NAME         SIZE       MEM_MAP      START_PADDR  START_MAPNR
  0   DMA          4096  ffff810009001000            0            0
  1   DMA32      257984  ffff810009039000      1000000         4096
  2   Normal          0                 0            0            0
  3   HighMem         0                 0            0            0

-------------------------------------------------------------------

NR      SECTION        CODED_MEM_MAP        MEM_MAP       PFN
 0  ffff810009000000  ffff810009001000  ffff810009001000  0
 1  ffff810009000008  ffff810009001000  ffff8100091c1000  8000
 2  ffff810009000010  ffff810009001000  ffff810009381000  10000
 3  ffff810009000018  ffff810009001000  ffff810009541000  18000
 4  ffff810009000020  ffff810009001000  ffff810009701000  20000
 5  ffff810009000028  ffff810009001000  ffff8100098c1000  28000
 6  ffff810009000030  ffff810009001000  ffff810009a81000  30000
 7  ffff810009000038  ffff810009001000  ffff810009c41000  38000
crash>

So for each "MEM_MAP" address above, it should show its physical
address as the "PFN" value shifted into a physical address.
And that seems to work OK:

crash> kmem -p ffff810009001000 ffff8100091c1000 ffff810009381000 ffff810009541000 ffff810009701000 ffff8100098c1000 ffff810009a81000 ffff810009c41000
      PAGE       PHYSICAL      MAPPING       INDEX CNT FLAGS
ffff810009001000        0      -------       -----   1 400

      PAGE       PHYSICAL      MAPPING       INDEX CNT FLAGS
ffff8100091c1000  8000000      -------       -----   1 8080000000400

      PAGE       PHYSICAL      MAPPING       INDEX CNT FLAGS
ffff810009381000 10000000      -------       -----   0 10080000080000

      PAGE       PHYSICAL      MAPPING       INDEX CNT FLAGS
ffff810009541000 18000000      -------       -----   2 18080000000824

      PAGE       PHYSICAL      MAPPING       INDEX CNT FLAGS
ffff810009701000 20000000      -------       -----   0 20080000080000

      PAGE       PHYSICAL      MAPPING       INDEX CNT FLAGS
ffff8100098c1000 28000000      -------       -----   0 28080000080000

      PAGE       PHYSICAL      MAPPING       INDEX CNT FLAGS
ffff810009a81000 30000000      -------       -----   1 30080000000060

      PAGE       PHYSICAL      MAPPING       INDEX CNT FLAGS
ffff810009c41000 38000000      -------       -----   1 38080000000000
crash>

But then if I take the last physical address on the machine,
for example:

crash> kmem -p | tail
ffff810009e00dd0 3fff6000      -------       -----   0 0
ffff810009e00e08 3fff7000      -------       -----   0 0
ffff810009e00e40 3fff8000      -------       -----   0 0
ffff810009e00e78 3fff9000      -------       -----   0 0
ffff810009e00eb0 3fffa000      -------       -----   0 0
ffff810009e00ee8 3fffb000      -------       -----   0 0
ffff810009e00f20 3fffc000      -------       -----   0 0
ffff810009e00f58 3fffd000      -------       -----   0 0
ffff810009e00f90 3fffe000      -------       -----   0 0
ffff810009e00fc8 3ffff000      -------       -----   0 0
crash> kmem -p ffff810009e00fc8
      PAGE       PHYSICAL      MAPPING       INDEX CNT FLAGS
ffff81000922a000  9e00000      -------       -----   1 8080000000400
crash>

...it's incorrect.  I don't see any infinite loops though.

But something's out of whack here.  I'll take a look and
see what I can find.

Thanks,
  Dave