[Crash-utility] Re: crash 4.0-8.9 w/ 2.6.30-rc6

Dave Anderson anderson at redhat.com
Thu May 28 12:59:01 UTC 2009


----- "Daisuke Nishimura" <nishimura at mxp.nes.nec.co.jp> wrote:

> Hi, Dave.
> 
> It's a very and very dirty hack, but some of my colleagues say that
> a dump file of 2.6.30-rcX can be analyzed by this patch.
> 
> I hope it would be some help for you.
> 
> Thanks,
> Daisuke Nishimura.

Actually it's not so dirty at all -- it's pretty well done!

I was also tinkering with a few new schemes yesterday, and did
make it to the "crash> " prompt as well.  But I was allowing the
kt->__per_cpu_offset[] array to be initialized in kernel_init()
(line 195) as is done for x86, althougyh I think now that I prefer
the way that you guys have done it.

I also was trying to come up with a clean way to deal with
the x86_64 "per_cpu__xxx" symbols being contained in the 
in the crash kernel symbol list.  With my test crash -- and
I presume the same with your patch -- the symbol list
look like this:

  crash> sym -l
  0 (D) __per_cpu_start  
  0 (D) per_cpu__irq_stack_union  
  4000 (D) per_cpu__gdt_page  
  5000 (d) per_cpu__exception_stacks  
  b000 (D) per_cpu__current_task  
  b008 (d) per_cpu__is_idle  
  b010 (D) per_cpu__old_rsp  
  b018 (D) per_cpu__irq_regs  
  b020 (D) per_cpu__vector_irq  
  b420 (d) per_cpu__cpu_devices  
  b478 (D) per_cpu__cyc2ns  
  b480 (d) per_cpu__cpuid4_info  
  b488 (d) per_cpu__cache_kobject  
  b490 (d) per_cpu__index_kobject  
  b4a0 (D) per_cpu__irq_stack_ptr  
  b4a8 (D) per_cpu__kernel_stack  
  b4b0 (D) per_cpu__irq_count  
  b4c0 (D) per_cpu__orig_ist  
  ... [ snip ] ... 
  10540 (D) per_cpu__irq_stat  
  10580 (D) per_cpu__cpu_info  
  10680 (D) per_cpu__cpu_tlbstate  
  106c0 (d) per_cpu__runqueues  
  10fc0 (d) per_cpu__sched_clock_data  
  10fe0 (D) __per_cpu_end  
  ffffffff80200000 (T) _text  
  ffffffff80200000 (T) startup_64  
  ffffffff802000b7 (t) ident_complete
  ...

The problem with having symbols below "_text" in this case
is that commands like "rd -s" or other memory dumps that
do symbolic translations of numeric values run into the
per_cpu symbols.  So for example, a page of zeroes would 
look like this:

  crash> rd empty_zero_page 10
  ffffffff80833000:  0000000000000000 0000000000000000   ................
  ffffffff80833010:  0000000000000000 0000000000000000   ................
  ffffffff80833020:  0000000000000000 0000000000000000   ................
  ffffffff80833030:  0000000000000000 0000000000000000   ................
  ffffffff80833040:  0000000000000000 0000000000000000   ................
  crash> rd -s empty_zero_page 10
  ffffffff80833000:  per_cpu__irq_stack_union per_cpu__irq_stack_union 
  ffffffff80833010:  per_cpu__irq_stack_union per_cpu__irq_stack_union 
  ffffffff80833020:  per_cpu__irq_stack_union per_cpu__irq_stack_union 
  ffffffff80833030:  per_cpu__irq_stack_union per_cpu__irq_stack_union 
  ffffffff80833040:  per_cpu__irq_stack_union per_cpu__irq_stack_union 
  crash>

In fact, *any* value would translate to a symbol:

  crash> rd ffff88007e4ee820 10
  ffff88007e4ee820:  0000000000400000 0000000000409000   .. at .......@.....
  ffff88007e4ee830:  ffff88007e4eead8 0000000000000025   ..N~....%.......
  ffff88007e4ee840:  0000000008001875 ffff88007e4eeb09   u.........N~....
  ffff88007e4ee850:  0000000000000000 0000000000000000   ................
  ffff88007e4ee860:  ffff88007e4ee860 ffff88007e4ee860   `.N~....`.N~....
  crash> rd -s ffff88007e4ee820 10
  ffff88007e4ee820:  __per_cpu_end+4124704 __per_cpu_end+4161568 
  ffff88007e4ee830:  __per_cpu_end+-131939276301576 per_cpu__irq_stack_union+37 
  ffff88007e4ee840:  __per_cpu_end+134154389 __per_cpu_end+-131939276301527 
  ffff88007e4ee850:  per_cpu__irq_stack_union per_cpu__irq_stack_union 
  ffff88007e4ee860:  __per_cpu_end+-131939276302208 __per_cpu_end+-131939276302208 
  crash>

So clearly there will have to be special handling for those
symbols, because sometimes a caller will *want* to receive
information re: those symbols, and other times will not.
(i.e. in symbol_exists(), value_search(), etc.)  It was
never a problem in the past because the per_cpu__xxx
symbols were not "real" symbol values, but they were 
very large numberic values in the kernel symbol list.

So in any case, we're on the same page, and I do like
what you've done.  Thank you very much for having already
looked into this!

Dave


> 
> Signed-off-by: Daisuke Nishimura <nishimura at mxp.nes.nec.co.jp>
> ---
>  defs.h   |    1 +
>  x86_64.c |   78
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 74 insertions(+), 5 deletions(-)
> 
> diff --git a/defs.h b/defs.h
> index e5e3538..32b2e1e 100755
> --- a/defs.h
> +++ b/defs.h
> @@ -3851,6 +3851,7 @@ struct machine_specific {
>  #define PHYS_BASE     (0x80)
>  #define VM_XEN_RHEL4 (0x100)
>  #define VMEMMAP      (0x200)
> +#define KSYMS_PERCPU (0x400)
>  
>  #define VM_FLAGS (VM_ORIG|VM_2_6_11|VM_XEN|VM_XEN_RHEL4)
>  
> diff --git a/x86_64.c b/x86_64.c
> index 993827e..4813f96 100755
> --- a/x86_64.c
> +++ b/x86_64.c
> @@ -71,6 +71,7 @@ static int x86_64_is_uvaddr(ulong, struct
> task_context *);
>  void x86_64_compiler_warning_stub(void);
>  static void x86_64_init_kernel_pgd(void);
>  static void x86_64_cpu_pda_init(void);
> +static void x86_64_per_cpu_init(void);
>  static void x86_64_ist_init(void);
>  static void x86_64_post_init(void);
>  static void parse_cmdline_arg(void);
> @@ -290,7 +291,10 @@ x86_64_init(int when)
>  		MEMBER_OFFSET_INIT(user_regs_struct_ss,
>  			"user_regs_struct", "ss");
>  		STRUCT_SIZE_INIT(user_regs_struct, "user_regs_struct");
> -		x86_64_cpu_pda_init();
> +		if (STRUCT_EXISTS("x8664_pda"))
> +			x86_64_cpu_pda_init();
> +		else
> +			x86_64_per_cpu_init();
>  		x86_64_ist_init();
>                  if ((machdep->machspec->irqstack = (char *)
>  		    malloc(machdep->machspec->stkinfo.isize)) == NULL)
> @@ -677,6 +681,51 @@ x86_64_cpu_pda_init(void)
>  	FREEBUF(cpu_pda_buf);
>  }
>  
> +static void
> +x86_64_per_cpu_init(void)
> +{
> +	int i, cpus, cpunumber;
> +	ulong istacksize;
> +
> +	if (!(kt->flags & PER_CPU_OFF))
> +		return;
> +
> +	if (!symbol_exists("per_cpu__cpu_number") || !symbol_exists("per_cpu__irq_stack_ptr"))
> +		return;
> +
> +	for (i = cpus = 0; i < NR_CPUS; i++) {
> +		readmem(symbol_value("per_cpu__cpu_number") + kt->__per_cpu_offset[i],
> +			KVADDR, &cpunumber, sizeof(int),
> +			"cpu number (per_cpu)", FAULT_ON_ERROR);
> +		if (cpunumber != cpus)
> +			break;
> +		cpus++;
> +
> +		readmem(symbol_value("per_cpu__irq_stack_ptr") + kt->__per_cpu_offset[i],
> +			KVADDR, &machdep->machspec->stkinfo.ibase[i],
> +			sizeof(ulong), "irq stack ptr (per cpu)", FAULT_ON_ERROR);
> +	}
> +
> +	istacksize = 16384;	/* 16K */
> +	machdep->machspec->stkinfo.isize = istacksize;
> +
> +	/*
> +	 *  Adjust the kernel top-of-stack values down to their base.
> +	 */
> +	for (i = 0; i < NR_CPUS; i++) {
> +		if (machdep->machspec->stkinfo.ibase[i])
> +			machdep->machspec->stkinfo.ibase[i] -= (istacksize-64);
> +		else
> +			break;
> +	}
> +
> +	kt->cpus = cpus;
> +	if (kt->cpus > 1)
> +		kt->flags |= SMP;
> +
> +	verify_spinlock();
> +}
> +
>  /*
>   *  Gather the ist addresses for each CPU.
>   */
> @@ -754,7 +803,7 @@ x86_64_ist_init(void)
>  	 */
>          sp = value_search(ms->stkinfo.ebase[0][0], &offset);
>         	if (!sp || offset || !STREQ(sp->name,
> "boot_exception_stacks")) {
> -		if (symbol_value("boot_exception_stacks")) {
> +		if (symbol_exists("boot_exception_stacks")) {
>                  	error(WARNING,
>      "cpu 0 first exception stack: %lx\n        
> boot_exception_stacks: %lx\n\n",
>                          	ms->stkinfo.ebase[0][0], 
> @@ -1706,8 +1755,12 @@ x86_64_verify_symbol(const char *name, ulong
> value, char type)
>  {
>          if (STREQ(name, "_text") || STREQ(name, "_stext"))
>                  machdep->flags |= KSYMS_START;
> +	if (STREQ(name, "__per_cpu_start"))
> +		machdep->flags |= KSYMS_PERCPU;
> +	if (STREQ(name, "__per_cpu_end"))
> +		machdep->flags &= ~KSYMS_PERCPU;
>  
> -        if (!name || !strlen(name) || !(machdep->flags & KSYMS_START))
> +        if (!name || !strlen(name) || !(machdep->flags & (KSYMS_START | KSYMS_PERCPU)))
>                  return FALSE;
>  	return TRUE;
>  }
> @@ -3943,8 +3996,23 @@ x86_64_get_smp_cpus(void)
>  	char *cpu_pda_buf;
>  	ulong level4_pgt, cpu_pda_addr;
>  
> -	if (!VALID_STRUCT(x8664_pda))
> -		return 1;
> +	if (!VALID_STRUCT(x8664_pda)) {
> +		if (!(kt->flags & PER_CPU_OFF))
> +			return 1;
> +
> +		if (!symbol_exists("per_cpu__cpu_number"))
> +			return 1;
> +
> +		for (i = cpus = 0; i < NR_CPUS; i++) {
> +			readmem(symbol_value("per_cpu__cpu_number") + kt->__per_cpu_offset[i],
> +				KVADDR, &cpunumber, sizeof(int),
> +				"cpu number (per_cpu)",FAULT_ON_ERROR);
> +			if (cpunumber != cpus)
> +				break;
> +			cpus++;
> +		}
> +		return cpus;
> +	}
>  
>  	cpu_pda_buf = GETBUF(SIZE(x8664_pda));
>  




More information about the Crash-utility mailing list