crash TODO list
by Dave Anderson
Nguyen Anh Quynh wrote:
>
> btw, we would love to see the "TODO" list, if you have any. those who
> are interested will know what is in the priority list, and might help
> out. what do you think?
>
On the http://people.redhat.com/anderson page I've added a
new link to a "crash TODO list". For each item in the list
there is a "DESCRIPTION" and a "RESOLUTION STATUS". If somebody
(including me) has started work on the issue, it will be marked
as such; if nobody has undertaken the issue, it will be marked
as "TBD".
I've seeded the list with 4 issues.
And Q, thanks for the suggestion, it was a good idea.
Dave
18 years, 8 months
Re: [Crash-utility] [Fwd: Some notes in descovering your crash]
by Dave Anderson
> Helo, i have reviewed which is really fascinating.
>
>
> The architecture i use :
> crash> sys
> KERNEL: /boot/vmlinux-2.6.15.2
> DUMPFILE: /dev/mem
> CPUS: 1
> DATE: Wed Mar 29 12:05:05 2006
> UPTIME: 04:33:58
> LOAD AVERAGE: 0.05, 0.06, 0.02
> TASKS: 67
> NODENAME: portable.domain.com
> RELEASE: 2.6.15.2
> VERSION: #4 PREEMPT Tue Mar 21 14:34:11 CET 2006
> MACHINE: i686 (748 Mhz)
> MEMORY: 511.9 MB
>
> A question : i could not find how to have a module withou [CONFIG_KALLSYMS] when
> i do mod
>
I'm not sure I understand the question?
> Some problems
>
> 1)kmem -s and kmem -S
>
> crash> kmem -s
>
> kmem: invalid structure member offset: kmem_cache_s_lists
> FILE: memory.c LINE: 7671 FUNCTION: do_slab_chain_percpu_v2()
>
> [./crash] error trace: 8099315 => 80a4d09 => 80a635d => 810cab0
> CACHE NAME OBJSIZE ALLOCATED TOTAL SLABS SSIZE
>
> 810cab0: OFFSET_verify+81
> 80a635d: do_slab_chain_percpu_v2+103
> 80a4d09: dump_kmem_cache_percpu_v2+1615
> 8099315: cmd_kmem+3392
>
> kmem: invalid structure member offset: kmem_cache_s_lists
> FILE: memory.c LINE: 7671 FUNCTION: do_slab_chain_percpu_v2()
>
>
> 2) crash> kmem -i
> PAGES TOTAL PERCENTAGE
> TOTAL MEM 128778 503 MB ----
> FREE 44244 172.8 MB 34% of TOTAL MEM
> USED 84534 330.2 MB 65% of TOTAL MEM
> SHARED 45690 178.5 MB 35% of TOTAL MEM
> BUFFERS 4371 17.1 MB 3% of TOTAL MEM
> CACHED 51358 200.6 MB 39% of TOTAL MEM
> SLAB 0 0 0% of TOTAL MEM
>
> TOTAL HIGH 0 0 0% of TOTAL MEM
>
> The command stops and SLAB is certainly not correct
>
See the prior messages on March 28th from Sharyathi Nagesh
in the mailing list; he is currently working on this.
>
> 3) net -s and net -S
> crash> net -s
>
> net: invalid structure member offset: files_struct_max_fdset
> FILE: net.c LINE: 1117 FUNCTION: dump_sockets_workhorse()
>
> [./crash] error trace: 80dca66 => 80ded3a => 80def30 => 810cab0
> PID: 5489 TASK: d7b97000 CPU: 0 COMMAND: "crash"
>
> 810cab0: OFFSET_verify+81
> 80def30: dump_sockets_workhorse+164
> 80ded3a: dump_sockets+80
> 80dca66: cmd_net+418
>
> net: invalid structure member offset: files_struct_max_fdset
> FILE: net.c LINE: 1117 FUNCTION: dump_sockets_workhorse()
>
Interesting. This will require the same type of changes that
are in open_files_dump() in filesys.c (lines 2129 - 2156), which
calculate the local max_fdset and max_fds variables.
>
> 4)
> The problems withe those commands are normal i think, the structures are not
> supported in kernel 2.6?
>
> kmem -la, -La, -li, -Li do not find active_list and inactive_list
> irq -b
> net -a
>
Correct. Either the structures are not supported in 2.6, or
continued support of the option has been deprecated.
Thanks for the report -- and please join the list!
Dave Anderson
18 years, 8 months
Re: [Crash-utility] crash version 4.0-2.22 is available
by Dave Anderson
Sharyathi Nagesh wrote:
Dave
You were right it should be buffer_size instead of objectsize.(As obj_size is the size of debugging information).
I modified function vm_init() and do_slab_chain_percpu_v2() to make it work with current dumps. This is just a code
part to show how to fix the problem but it is not a patch as such...
Please go through and let me know would it be good idea to write a new function (as you have suggested earlier) or
is it possible to accommodate by calling do_slab_chain_percpu_v2() iteratively with different nodes by passing them as
parameter.
Changes to vm_init()
if(MEMBER_EXISTS("kmem_cache","objsize"))
MEMBER_OFFSET_INIT(kmem_cache_s_objsize, "kmem_cache",
"objsize");
else if(MEMBER_EXISTS("kmem_cache","buffer_size"))
MEMBER_OFFSET_INIT(kmem_cache_s_objsize, "kmem_cache",
"buffer_size")
Changes to do_slab_chain_percpu_v2()
ulong start_address[MAX_NUMNODES];
if (!readmem(si->cache+OFFSET(kmem_cache_s_lists),
KVADDR, &start_address[0],
sizeof(ulong) * MAX_NUMNODES,
"array nodelist array", RETURN_ON_ERROR))
{printf("\n Error encountered with readmem \n");exit(0);}
for (i = 0; i < MAX_NUMNODES ; i++) {
slab_chains[0] = start_address[i] + OFFSET(kmem_list3_slabs_partial);
slab_chains[1] = start_address[i] + OFFSET(kmem_list3_slabs_full);
slab_chains[2] = start_address[i] + OFFSET(kmem_list3_slabs_free);
The vm_init() change is fine, but it would also need:
(1) the same kind of offset initializer to handle the kmem_cache
structure's "lists"-to-"nodelist" name change.
(2) A new flag in vt->flags to signal this node-enhanced version
of the kmem_cache struct.
(3) a check of the dimension of some processor-neutral, always-there,
kernel array indexed by MAX_NUMNODES, so that you can determine
what MAX_NUMNODES is equal to, and then store that value in a
new vm_table entry.
With respect to do_slab_chain_percpu_v2(), I would prefer that
it be left as is, and either
(1) at the top of the function, check for your new "node-enhanced"
flag, and call a new do_slab_chain_percpu_v2_nodes() function, or
(2) alternatively, the two locations where do_slab_chain_percpu_v2()
gets called could be qualified based upon the new flag, and the
appropriate function called.
In that new function, the usage of a static start_address[] array
as you indicate above would have to be replaced with dynamically
allocated and freed with GETBUF() and FREEBUF(), based upon
the predetermined size of MAX_NUMNODES.
Doing it that way leaves the current functionality untouched, makes
me a lot less nervous, and should make your task a bit easier.
Make sense?
Dave
18 years, 8 months
crash version 4.0-2.22 is available
by Dave Anderson
- Incorporated initial patch-set to implement support for kernels built
with CONFIG_SPARSEMEM. (dwilder(a)us.ibm.com)
- Fix for post-2.6.15 ppc64 kernels to use cpu_online_map when perusing
the paca array for the per_cpu_offsets. (haren(a)us.ibm.com)
- Fix for ppc64 "bt" command for active tasks that were running in
user space at the time of crash. (haren(a)us.ibm.com)
- Fix to remove dependencies upon any kernel header files so as to
allow crash to build in a Ubuntu environment. (aquynh(a)gmail.com)
- Fix size of x86_64 "cpu_khz" variable to match that of the kernel.
(sharyath(a)in.ibm.com)
- Created framework for support of Xen kernel dumpfiles and live Xen
kernels; this is going to be a long-period work-in-progress affair,
and the code added in this release is being done now primarily to aid
in future patch integration efforts. (anderson(a)redhat.com)
Download from: http://people.redhat.com/anderson
18 years, 8 months
Patch to fix Incorrect Incorrect Processor speed in x86_64
by Sharyathi Nagesh
This is a patch to fix incorrect Processor speed being displayed on
dumps taken over x86_64 machines. Please review and let me know of your
views...
--- crash-4.0-2.21.old/x86_64.c 2006-02-15 04:10:02.000000000 +0530
+++ crash-4.0-2.21/x86_64.c 2006-03-23 11:22:43.000000000 +0530
@@ -1044,13 +1044,13 @@ x86_64_is_task_addr(ulong task)
static ulong
x86_64_processor_speed(void)
{
- unsigned long cpu_khz;
+ unsigned long cpu_khz=0;
if (machdep->mhz)
return (machdep->mhz);
if (symbol_exists("cpu_khz")) {
- get_symbol_data("cpu_khz", sizeof(long), &cpu_khz);
+ get_symbol_data("cpu_khz", sizeof(int), &cpu_khz);
if (cpu_khz)
return(machdep->mhz = cpu_khz/1000);
}
18 years, 8 months
What happened to the archives?
by Dave Anderson
Just a test -- trying to understand if not only have the archives been
lost, but that messages aren't even being sent out...
Dave
18 years, 8 months
[RFC]Patch to add sparse memory support
by David Wilder
Happy St. Patty's day everyone!
This patch add sparsemem support to crash. Please comment.
Per-node memory display functions (kmem -n) are not yet working
for sparsemem kernels. This will come in a later patch. This patch
applies to 4.0-2.21.
(Dave A. your patch for the un-named structure in struct page is
already included
in this patch.)
Signed-off-by: David Wilder <dwilder(a)us.ibm.com
diff -Naur crash-4.0-2.21/defs.h crash-4.0-2.21-sparse.4/defs.h
--- crash-4.0-2.21/defs.h 2006-02-14 14:40:02.000000000 -0800
+++ crash-4.0-2.21-sparse.4/defs.h 2006-03-17 11:58:32.000000000 -0800
@@ -663,6 +663,10 @@
int ptrs_per_pgd;
char *cmdline_arg;
struct machine_specific *machspec;
+ ulong section_size_bits;
+ ulong max_physaddr_bits;
+ ulong max_physmem_bits;
+ ulong sections_per_root;
};
/*
@@ -1230,6 +1234,7 @@
long x8664_pda_cpunumber;
long x8664_pda_me;
long tss_struct_ist;
+ long mem_section_section_mem_map;
};
struct size_table { /* stash of commonly-used sizes */
@@ -1464,6 +1469,7 @@
ulong cached_vma_hits[VMA_CACHE];
int vma_cache_index;
ulong vma_cache_fills;
+ void *mem_sec;
};
#define NODES (0x1)
@@ -1474,7 +1480,15 @@
#define V_MEM_MAP (0x20)
#define PERCPU_KMALLOC_V2 (0x40)
#define KMEM_CACHE_UNAVAIL (0x80)
-#define DISCONTIGMEM (0x100)
+#define FLATMEM (0x100)
+#define DISCONTIGMEM (0x200)
+#define SPARSEMEM (0x400)
+#define SPARSEMEM_EX (0x800)
+
+#define IS_FLATMEM() (vt->flags & FLATMEM)
+#define IS_DISCONTIGMEM() (vt->flags & DISCONTIGMEM)
+#define IS_SPARSEMEM() (vt->flags & SPARSEMEM)
+#define IS_SPARSEMEM_EX() (vt->flags & SPARSEMEM_EX)
#define COMMON_VADDR_SPACE() (vt->flags & COMMON_VADDR)
#define PADDR_PRLEN (vt->paddr_prlen)
@@ -1703,6 +1717,34 @@
#define VIRTPAGEBASE(X) (((ulong)(X)) & (ulong)machdep->pagemask)
#define PHYSPAGEBASE(X) (((physaddr_t)(X)) &
(physaddr_t)machdep->pagemask)
+/*
+ * Sparse memory stuff
+ * These must follow the definitions in the kernel mmzone.h
+ */
+#define SECTION_SIZE_BITS() (machdep->section_size_bits)
+#define MAX_PHYSADDR_BITS() (machdep->max_physaddr_bits)
+#define MAX_PHYSMEM_BITS() (machdep->max_physmem_bits)
+#define SECTIONS_SHIFT() (MAX_PHYSMEM_BITS() - SECTION_SIZE_BITS())
+#define PA_SECTION_SHIFT() (SECTION_SIZE_BITS())
+#define PFN_SECTION_SHIFT() (SECTION_SIZE_BITS() - PAGESHIFT())
+#define NR_MEM_SECTIONS() (1UL << SECTIONS_SHIFT())
+#define PAGES_PER_SECTION() (1UL << PFN_SECTION_SHIFT())
+#define PAGE_SECTION_MASK() (~(PAGES_PER_SECTION()-1))
+
+#define pfn_to_section_nr(pfn) ((pfn) >> PFN_SECTION_SHIFT())
+#define section_nr_to_pfn(sec) ((sec) << PFN_SECTION_SHIFT())
+
+#define SECTIONS_PER_ROOT() (machdep->sections_per_root)
+
+/* CONFIG_SPARSEMEM_EXTREME */
+#define _SECTIONS_PER_ROOT_EXTREME() (PAGESIZE() /
STRUCT_SIZE("mem_section"))
+/* !CONFIG_SPARSEMEM_EXTREME */
+#define _SECTIONS_PER_ROOT() (1)
+
+#define SECTION_NR_TO_ROOT(sec) ((sec) / SECTIONS_PER_ROOT())
+#define NR_SECTION_ROOTS() (NR_MEM_SECTIONS() / SECTIONS_PER_ROOT())
+#define SECTION_ROOT_MASK() (SECTIONS_PER_ROOT() - 1)
+
/*
* Machine specific stuff
*/
@@ -1747,6 +1789,16 @@
#define TIF_SIGPENDING (2)
+// CONFIG_X86_PAE
+#define _SECTION_SIZE_BITS_PAE 30
+#define _MAX_PHYSADDR_BITS_PAE 36
+#define _MAX_PHYSMEM_BITS_PAE 36
+
+// !CONFIG_X86_PAE
+#define _SECTION_SIZE_BITS 26
+#define _MAX_PHYSADDR_BITS 32
+#define _MAX_PHYSMEM_BITS 32
+
#endif /* X86 */
#ifdef X86_64
@@ -1861,6 +1913,10 @@
#define VALID_LEVEL4_PGT_ADDR(X) \
(((X) == VIRTPAGEBASE(X)) && IS_KVADDR(X) && !IS_VMALLOC_ADDR(X))
+#define _SECTION_SIZE_BITS 27
+#define _MAX_PHYSADDR_BITS 40
+#define _MAX_PHYSMEM_BITS 40
+
#endif /* X86_64 */
#ifdef ALPHA
@@ -1939,6 +1995,10 @@
#define TIF_SIGPENDING (2)
+#define _SECTION_SIZE_BITS 24
+#define _MAX_PHYSADDR_BITS 44
+#define _MAX_PHYSMEM_BITS 44
+
#endif /* PPC */
#ifdef IA64
@@ -1963,6 +2023,9 @@
#define KERNEL_UNCACHED_BASE ((ulong)KERNEL_UNCACHED_REGION <<
REGION_SHIFT)
#define KERNEL_CACHED_BASE ((ulong)KERNEL_CACHED_REGION << REGION_SHIFT)
+#define _SECTION_SIZE_BITS 30
+#define _MAX_PHYSMEM_BITS 50
+
/*
* As of 2.6, these are no longer straight forward.
*/
@@ -2168,6 +2231,10 @@
#define STACK_FRAME_OVERHEAD 112
#define EXCP_FRAME_MARKER 0x7265677368657265
+#define _SECTION_SIZE_BITS 24
+#define _MAX_PHYSADDR_BITS 44
+#define _MAX_PHYSMEM_BITS 44
+
#endif /* PPC64 */
#ifdef S390
diff -Naur crash-4.0-2.21/ia64.c crash-4.0-2.21-sparse.4/ia64.c
--- crash-4.0-2.21/ia64.c 2006-02-14 14:40:02.000000000 -0800
+++ crash-4.0-2.21-sparse.4/ia64.c 2006-03-16 11:28:57.000000000 -0800
@@ -206,6 +206,9 @@
ARRAY_LENGTH_INIT(machdep->nr_irqs, irq_desc,
"_irq_desc", NULL, 0);
machdep->hz = 1024;
+ machdep->section_size_bits = _SECTION_SIZE_BITS;
+ machdep->max_physaddr_bits = _MAX_PHYSADDR_BITS;
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
ia64_create_memmap();
break;
diff -Naur crash-4.0-2.21/memory.c crash-4.0-2.21-sparse.4/memory.c
--- crash-4.0-2.21/memory.c 2006-02-14 14:40:02.000000000 -0800
+++ crash-4.0-2.21-sparse.4/memory.c 2006-03-17 13:47:17.000000000 -0800
@@ -132,8 +132,18 @@
static void do_vm_flags(ulong);
static void PG_reserved_flag_init(void);
static ulong nr_blockdev_pages(void);
-
-
+void sparse_mem_init(void);
+void list_mem_sections(void);
+void sparse_dump_mem_map(void);
+ulong sparse_decode_mem_map(ulong, ulong);
+char *read_mem_section(ulong);
+ulong nr_to_section(ulong);
+int valid_section(ulong);
+int section_has_mem_map(ulong);
+ulong section_mem_map_addr(ulong);
+ulong valid_section_nr(ulong);
+void list_mem_sections(void);
+ulong pfn_to_map(ulong);
/*
* Memory display modes specific to this file.
@@ -447,10 +457,17 @@
error(FATAL, "no swapper_pg_dir or cpu_pgd symbols exist?\n");
get_symbol_data("high_memory", sizeof(ulong), &vt->high_memory);
- if (kernel_symbol_exists("mem_map"))
+
+ if (kernel_symbol_exists("mem_map")){
get_symbol_data("mem_map", sizeof(char *), &vt->mem_map);
+ vt->flags |= FLATMEM;
+ } else if (kernel_symbol_exists("mem_section"))
+ vt->flags |= SPARSEMEM;
else
vt->flags |= DISCONTIGMEM;
+
+ sparse_mem_init();
+
vt->vmalloc_start = machdep->vmalloc_start();
if (IS_VMALLOC_ADDR(vt->mem_map))
vt->flags |= V_MEM_MAP;
@@ -3480,9 +3497,9 @@
static void
dump_mem_map(struct meminfo *mi)
{
- long i, n;
+ long node;
long total_pages;
- int others, page_not_mapped, phys_not_mapped;
+ int others, page_not_mapped, phys_not_mapped, page_mapping;
ulong pp, ppend;
physaddr_t phys, physend;
ulong tmp, reserved, shared, slabs;
@@ -3502,6 +3519,7 @@
char buf4[BUFSIZE];
char *page_cache;
char *pcache;
+ ulong section, section_nr, nr_mem_sections, node_or_section_size;
v22 = VALID_MEMBER(page_inode); /* page.inode vs. page.mapping */
@@ -3589,22 +3607,63 @@
done = FALSE;
total_pages = 0;
- for (n = 0; n < vt->numnodes; n++) {
+ if (IS_SPARSEMEM()){
+ nr_mem_sections = NR_MEM_SECTIONS();
+ }else{
+ nr_mem_sections = 1;
+ }
+
+ /* iterate over all possable section */
+ node = 0;
+ for (section_nr = 0; section_nr < nr_mem_sections ; section_nr++){
+
+
+ if (CRASHDEBUG(2))
+ printf("section_nr = %d\n",section_nr);
+
+ /* If we are looking up a spicific address jump directly
+ to the section with that page */
+ if (IS_SPARSEMEM() && mi->flags&ADDRESS_SPECIFIED){
+ ulong pfn = mi->spec_addr >> PAGESHIFT();
+ section_nr=pfn_to_section_nr(pfn);
+ }
+
+ if(IS_SPARSEMEM() &&
!(section=valid_section_nr(section_nr))){
+ /*break; on a real sparsemem system we need
to check
+ * every section as gaps may exist. But this
+ * can be slow. If we know we dont have gaps
+ * just stop validating sections when we
+ * get to the end of the valid ones.
+ * In the future find a way to short circuit
+ * this loop.
+ */
+ continue;
+ }
+
if (print_hdr) {
- fprintf(fp, "%s%s", n ? "\n" : "", hdr);
+ fprintf(fp, "%s%s", node ? "\n" : "", hdr);
print_hdr = FALSE;
}
- nt = &vt->node_table[n];
- total_pages += nt->size;
- pp = nt->mem_map;
- phys = nt->start_paddr;
- if ((vt->flags & V_MEM_MAP) && (vt->numnodes == 1))
- node_size = vt->max_mapnr;
- else
- node_size = nt->size;
+next_node:
+ if (IS_SPARSEMEM()){
+ pp = section_mem_map_addr(section);
+ pp = sparse_decode_mem_map(pp,section_nr);
+ phys = section_nr*PAGES_PER_SECTION()*PAGESIZE();
+ node_or_section_size = PAGES_PER_SECTION();
+ }else{
+ nt = &vt->node_table[node];
+ total_pages += nt->size;
+ pp = nt->mem_map;
+ phys = nt->start_paddr;
+ if ((vt->flags & V_MEM_MAP) && (vt->numnodes == 1))
+ node_or_section_size = vt->max_mapnr;
+ else
+ node_or_section_size = nt->size;
+ }
- for (i = 0; i < node_size;
+ ulong i;
+ for (i = 0; i < node_or_section_size;
i++, pp += SIZE(page), phys += PAGESIZE()) {
if ((i % PGMM_CACHED) == 0) {
@@ -3693,11 +3752,12 @@
}
continue;
}
+ page_mapping = VALID_MEMBER(page_mapping);
if (v22) {
inode = ULONG(pcache + OFFSET(page_inode));
offset = ULONG(pcache + OFFSET(page_offset));
- } else {
+ } else if (page_mapping) {
mapping = ULONG(pcache +
OFFSET(page_mapping));
index = ULONG(pcache + OFFSET(page_index));
@@ -3740,6 +3800,20 @@
space(MINSPACE),
mkstring(buf4, 8, CENTER|RJUST, " "),
" ");
+ else if (!page_mapping)
+ fprintf(fp, "%s%s%s%s%s%s%s %2d ",
+ mkstring(buf0, VADDR_PRLEN,
+ LJUST|LONG_HEX, MKSTR(pp)),
+ space(MINSPACE),
+ mkstring(buf1, MAX(PADDR_PRLEN,
+ strlen("PHYSICAL")),
+ RJUST|LONGLONG_HEX, MKSTR(&phys)),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN,
+ CENTER|RJUST, "-------"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, "-----"),
+ count);
else
fprintf(fp, "%s%s%s%s%s%s%8ld %2d ",
mkstring(buf0, VADDR_PRLEN,
@@ -3801,6 +3875,7 @@
fprintf(fp, "\n");
} else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
fprintf(fp, "%lx\n", flags);
+ node=node;
} else {
if ((flags >> v24_PG_locked) & 1)
@@ -3864,9 +3939,12 @@
if (done)
break;
}
-
if (done)
break;
+ node++;
+ if ( (node < vt->numnodes) && (!IS_SPARSEMEM())) {
+ goto next_node;
+ }
}
switch (mi->flags)
@@ -8904,6 +8982,16 @@
physaddr_t pstart, pend;
ulong node_size;
+ if (IS_SPARSEMEM()){
+ ulong map;
+ map = pfn_to_map(phys >> PAGESHIFT());
+ if ( map ){
+ *pp = map;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
for (n = 0; n < vt->numnodes; n++) {
nt = &vt->node_table[n];
if ((vt->flags & V_MEM_MAP) && (vt->numnodes == 1))
@@ -9009,8 +9097,12 @@
fprintf(fp, "%sV_MEM_MAP", others++ ? "|" : "");
if (vt->flags & KMEM_CACHE_UNAVAIL)
fprintf(fp, "%sKMEM_CACHE_UNAVAIL", others++ ? "|" : "");
- if (vt->flags & DISCONTIGMEM)
- fprintf(fp, "%sDISCONTIGMEM", others++ ? "|" : "");
+ if (vt->flags & FLATMEM)
+ fprintf(fp, "%sFLATMEM", others++ ? "|" : "");
+ if (vt->flags & SPARSEMEM)
+ fprintf(fp, "%sSPARSEMEM", others++ ? "|" : "");\
+ if (vt->flags & SPARSEMEM_EX)
+ fprintf(fp, "%sSPARSEMEM_EX", others++ ? "|" : "");\
fprintf(fp, ")\n");
if (vt->kernel_pgd[0] == vt->kernel_pgd[1])
fprintf(fp, " kernel_pgd[NR_CPUS]: %lx ...\n",
@@ -10015,6 +10107,11 @@
char buf5[BUFSIZE];
struct node_table *nt;
+ if (IS_SPARSEMEM() && !initialize){
+ error(WARNING,"Per node memory data is not available for this
kernel\n");
+ return;
+ }
+
if (!(vt->flags & NODES)) {
if (!initialize)
error(FATAL,
@@ -10054,12 +10151,6 @@
"node_mem_map", FAULT_ON_ERROR);
} else {
node_mem_map = BADADDR;
- if (!badaddr && initialize) {
- error(INFO,
- "pglist_data.node_mem_map structure member does not exist.\n");
- error(INFO,
- "certain memory-related commands will fail or display invalid
data\n\n");
- }
badaddr = TRUE;
}
@@ -10570,3 +10661,172 @@
return retval;
}
+
+/* Functions for sparse mem support */
+ulong sparse_decode_mem_map(ulong coded_mem_map, ulong section_nr)
+{
+ return coded_mem_map +
(section_nr_to_pfn(section_nr)*STRUCT_SIZE("struct page"));
+}
+
+void
+sparse_mem_init(void)
+{
+ ulong addr;
+ ulong mem_section_size;
+
+ if (!IS_SPARSEMEM())
+ return;
+
+ /* How can I tell if SPARSEMEM_EX is set? */
+ vt->flags |= SPARSEMEM_EX;
+
+
+ if (IS_SPARSEMEM_EX()){
+ machdep->sections_per_root = _SECTIONS_PER_ROOT_EXTREME();
+ mem_section_size = sizeof(void *)*NR_SECTION_ROOTS();
+ }else{
+ machdep->sections_per_root = _SECTIONS_PER_ROOT();
+ mem_section_size = STRUCT_SIZE("struct
mem_section")*NR_SECTION_ROOTS();
+ }
+
+ if (CRASHDEBUG(1)){
+ fprintf(fp, "PAGESIZE=%d\n",PAGESIZE());
+ fprintf(fp,"mem_section_size = %d\n",mem_section_size);
+ fprintf(fp, "NR_SECTION_ROOTS=%d\n", NR_SECTION_ROOTS());
+ fprintf(fp, "NR_MEM_SECTIONS=%d\n",NR_MEM_SECTIONS());
+ fprintf(fp, "SECTIONS_PER_ROOT = %d\n",SECTIONS_PER_ROOT() );
+ fprintf(fp, "SECTION_ROOT_MASK=0x%x\n", SECTION_ROOT_MASK());
+ fprintf(fp, "PAGES_PER_SECTION=%d\n", PAGES_PER_SECTION());
+ }
+
+ if (!(vt->mem_sec = malloc(mem_section_size)))
+ error(FATAL, "cannot malloc mem_sec cache\n");
+
+ addr = symbol_value("mem_section");
+ readmem(addr, KVADDR,vt->mem_sec ,mem_section_size,
+ "memory section root table", FAULT_ON_ERROR);
+
+ MEMBER_OFFSET_INIT(mem_section_section_mem_map,
"mem_section","section_mem_map");
+}
+
+char
+*read_mem_section(ulong addr)
+{
+ static char *mem_section;
+
+ if (!mem_section){
+ mem_section = GETBUF(STRUCT_SIZE("struct mem_section"));
+ }
+
+ if (!IS_KVADDR(addr))
+ return 0;
+
+ readmem(addr,KVADDR,mem_section,STRUCT_SIZE("struct mem_section"),
+ "memory section", FAULT_ON_ERROR);
+
+ return mem_section;
+}
+
+ulong
+nr_to_section(ulong nr)
+{
+ ulong addr;
+
+ ulong *mem_sec = vt->mem_sec;
+ if (!IS_KVADDR(mem_sec[SECTION_NR_TO_ROOT(nr)]))
+ return 0;
+
+ if (IS_SPARSEMEM_EX())
+ addr=mem_sec[SECTION_NR_TO_ROOT(nr)] + (nr &
SECTION_ROOT_MASK())* STRUCT_SIZE("struct mem_section");
+ else
+ addr=mem_sec[0] + (nr & SECTION_ROOT_MASK())*
STRUCT_SIZE("struct mem_section");
+
+ if (!IS_KVADDR(addr))
+ return 0;
+
+ return addr;
+}
+
+/*
+ * We use the lower bits of the mem_map pointer to store
+ * a little bit of information. There should be at least
+ * 3 bits here due to 32-bit alignment.
+ */
+#define SECTION_MARKED_PRESENT (1UL<<0)
+#define SECTION_HAS_MEM_MAP (1UL<<1)
+#define SECTION_MAP_LAST_BIT (1UL<<2)
+#define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1))
+
+
+int valid_section(ulong addr)
+{
+ char *mem_section;
+
+ if ((mem_section = read_mem_section(addr)))
+ return (ULONG(mem_section+OFFSET(mem_section_section_mem_map))
+ && SECTION_MARKED_PRESENT);
+ return 0;
+}
+
+int section_has_mem_map(ulong addr)
+{
+ char *mem_section;
+
+ if ((mem_section = read_mem_section(addr)))
+ return (ULONG(mem_section+OFFSET(mem_section_section_mem_map))
+ && SECTION_HAS_MEM_MAP);
+ return 0;
+}
+
+ulong section_mem_map_addr(ulong addr)
+{
+ char *mem_section;
+ ulong map;
+
+ if ((mem_section = read_mem_section(addr))){
+ map = ULONG(mem_section+OFFSET(mem_section_section_mem_map));
+ map &= SECTION_MAP_MASK;
+ return map;
+ }
+ return 0;
+}
+
+
+ulong valid_section_nr(ulong nr)
+{
+ ulong addr = nr_to_section(nr);
+ if(valid_section(addr))
+ return addr;
+ return 0;
+}
+
+ulong pfn_to_map(ulong pfn)
+{
+ ulong section, page_offset;
+
+ section=pfn_to_section_nr(pfn);
+ if (section_has_mem_map(section)){
+ page_offset = pfn - section_nr_to_pfn(section);
+ return(section_mem_map_addr(section) + (page_offset*PAGESIZE()));
+ }
+ return 0;
+}
+
+void list_mem_sections(void)
+{
+ ulong nr,addr;
+ ulong nr_mem_sections = NR_MEM_SECTIONS();
+ ulong coded_mem_map;
+
+ for (nr = 0; nr <= nr_mem_sections ; nr++){
+ if( (addr=valid_section_nr(nr)) ){
+ coded_mem_map=section_mem_map_addr(addr);
+ fprintf(fp,"nr=%d section = %llx coded_mem_map=%lx pfn=%d
mem_map=%lx\n",
+ nr,
+ addr,
+ coded_mem_map,
+ section_nr_to_pfn(nr),
+ sparse_decode_mem_map(coded_mem_map,nr));
+ }
+ }
+}
diff -Naur crash-4.0-2.21/ppc64.c crash-4.0-2.21-sparse.4/ppc64.c
--- crash-4.0-2.21/ppc64.c 2006-02-14 14:40:02.000000000 -0800
+++ crash-4.0-2.21-sparse.4/ppc64.c 2006-03-17 12:14:28.000000000 -0800
@@ -162,7 +162,9 @@
m->l3_shift = m->l2_shift + m->l2_index_size;
m->l4_shift = m->l3_shift + m->l3_index_size;
}
-
+ machdep->section_size_bits = _SECTION_SIZE_BITS;
+ machdep->max_physaddr_bits = _MAX_PHYSADDR_BITS;
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
ppc64_paca_init();
machdep->vmalloc_start = ppc64_vmalloc_start;
MEMBER_OFFSET_INIT(thread_struct_pg_tables,
diff -Naur crash-4.0-2.21/ppc.c crash-4.0-2.21-sparse.4/ppc.c
--- crash-4.0-2.21/ppc.c 2006-02-14 14:40:02.000000000 -0800
+++ crash-4.0-2.21-sparse.4/ppc.c 2006-03-17 12:20:36.000000000 -0800
@@ -138,6 +138,9 @@
machdep->hz = HZ;
if (THIS_KERNEL_VERSION >= LINUX(2,6,0))
machdep->hz = 1000;
+ machdep->section_size_bits = _SECTION_SIZE_BITS;
+ machdep->max_physaddr_bits = _MAX_PHYSADDR_BITS;
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
break;
case POST_INIT:
diff -Naur crash-4.0-2.21/s390.c crash-4.0-2.21-sparse.4/s390.c
--- crash-4.0-2.21/s390.c 2006-02-14 14:40:02.000000000 -0800
+++ crash-4.0-2.21-sparse.4/s390.c 2006-03-16 11:28:57.000000000 -0800
@@ -159,6 +159,9 @@
machdep->vmalloc_start = s390_vmalloc_start;
machdep->dump_irq = s390_dump_irq;
machdep->hz = HZ;
+ machdep->section_size_bits = _SECTION_SIZE_BITS;
+ machdep->max_physaddr_bits = _MAX_PHYSADDR_BITS;
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
break;
case POST_INIT:
diff -Naur crash-4.0-2.21/s390x.c crash-4.0-2.21-sparse.4/s390x.c
--- crash-4.0-2.21/s390x.c 2006-02-14 14:40:02.000000000 -0800
+++ crash-4.0-2.21-sparse.4/s390x.c 2006-03-16 11:28:57.000000000 -0800
@@ -174,6 +174,9 @@
machdep->vmalloc_start = s390x_vmalloc_start;
machdep->dump_irq = s390x_dump_irq;
machdep->hz = HZ;
+ machdep->section_size_bits = _SECTION_SIZE_BITS;
+ machdep->max_physaddr_bits = _MAX_PHYSADDR_BITS;
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
break;
case POST_INIT:
diff -Naur crash-4.0-2.21/x86_64.c crash-4.0-2.21-sparse.4/x86_64.c
--- crash-4.0-2.21/x86_64.c 2006-02-14 14:40:02.000000000 -0800
+++ crash-4.0-2.21-sparse.4/x86_64.c 2006-03-16 11:28:57.000000000 -0800
@@ -211,6 +211,9 @@
machdep->hz = HZ;
if (THIS_KERNEL_VERSION >= LINUX(2,6,0))
machdep->hz = 1000;
+ machdep->section_size_bits = _SECTION_SIZE_BITS;
+ machdep->max_physaddr_bits = _MAX_PHYSADDR_BITS;
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
break;
case POST_INIT:
diff -Naur crash-4.0-2.21/x86.c crash-4.0-2.21-sparse.4/x86.c
--- crash-4.0-2.21/x86.c 2006-02-14 14:40:02.000000000 -0800
+++ crash-4.0-2.21-sparse.4/x86.c 2006-03-16 11:28:57.000000000 -0800
@@ -1741,6 +1741,9 @@
machdep->hz = HZ;
if (THIS_KERNEL_VERSION >= LINUX(2,6,0))
machdep->hz = 1000;
+ machdep->section_size_bits = _SECTION_SIZE_BITS;
+ machdep->max_physaddr_bits = _MAX_PHYSADDR_BITS;
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
break;
case POST_INIT:
--
David Wilder
IBM Linux Technology Center
Beaverton, Oregon, USA
dwilder(a)us.ibm.com
(503)578-3789
18 years, 8 months