Takao Indoh wrote:
Hi,

I used crash-4.0-3.18 and found a problem.

When I used kmem command to get information of
virtual address e000000105090000, which is page ptr,
segmentation fault occurred.

-----------------------------------------------------------------------
      KERNEL: /usr/lib/debug/lib/modules/2.6.18-8.el5/vmlinux
    DUMPFILE: /dev/mem
        CPUS: 4
        DATE: Tue Feb  6 15:53:25 2007
      UPTIME: 01:12:05
LOAD AVERAGE: 0.55, 0.56, 0.30
       TASKS: 185
    NODENAME: build.fujitsu.com
     RELEASE: 2.6.18-8.el5
     VERSION: #1 SMP Fri Jan 26 14:16:09 EST 2007
     MACHINE: ia64  (1600 Mhz)
      MEMORY: 31.2 GB
         PID: 16173
     COMMAND: "crash"
        TASK: e0000040b2660000  [THREAD_INFO: e0000040b2661040]
         CPU: 1
       STATE: TASK_RUNNING (ACTIVE)

crash> kmem -p | grep e000000105090000
e000000105090000 180000000      -------       -----   0 600200080000
crash> kmem -p e000000105090000
Segmentation fault (core dumped)
-----------------------------------------------------------------------

This is a backtrace.

#0  0x40000000000faa20 in nr_to_section (nr=15032385540) at memory.c:11897
#1  0x40000000000fb360 in valid_section_nr (nr=15032385540) at memory.c:11966
#2  0x40000000000ab000 in dump_mem_map_SPARSEMEM (mi=0x60000fffffd88370)
    at memory.c:3754
#3  0x40000000000b00c0 in dump_mem_map (mi=0x60000fffffd88370) at memory.c:4120
#4  0x40000000000a7b70 in cmd_kmem () at memory.c:3345
#5  0x400000000005ad20 in exec_command () at main.c:528
#6  0x400000000005a900 in main_loop () at main.c:487

It seems that there is a problem in dump_mem_map_SPARSEMEM.
Here is a part of it.

    switch (mi->flags)
    {
    case ADDRESS_SPECIFIED:
            switch (mi->memtype)
            {
            case KVADDR:
1)                  if (is_page_ptr(mi->spec_addr, NULL))
                            pg_spec = TRUE;
                    else {
                            if (kvtop(NULL, mi->spec_addr, &phys, 0)) {
2)                                  mi->spec_addr = phys;
                                    phys_spec = TRUE;
                            }
                            else
                                    return;
                    }
                    break;
(snipped)
            if (mi->flags & ADDRESS_SPECIFIED) {
3)                  ulong pfn = mi->spec_addr >> PAGESHIFT();
                    section_nr = pfn_to_section_nr(pfn);
            }

4)          if (!(section = valid_section_nr(section_nr))) {

1) e000000105090000 is a page pointer, so is_page_ptr returns TRUE.
2) mi->spec_addr is converted to physical addr here, but, this
   code does not be executed in this case.
3) mi->spec_addr is converted to pfn, but mi->spec_addr has
   virtual address in this case, so this conversion fails.
4) section_nr has invalid section number and it causes fault.

I have yet to find how to fix it.
Any idea?

Takao Indoh
 

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);
                }
 

Dave