[Crash-utility] Re: [RFC]Patch to accomodate cpu_pda changes in x86_64 kernels

Dave Anderson anderson at redhat.com
Tue Jan 31 14:11:36 UTC 2006


Rachita Kothiyal wrote:

> Hi Dave,
>
> Following the changes in the way cpu_pda is accessed
> on x86_64 kernels, running crash to analyse kdump based
> crash dumps gave the following error:
>
>         crash: cannot resolve "cpu_pda"
>
> The following patch fixes this. Kindly review.
>

Hi Rachita,

Thanks for handling this.  I haven't looked at this, and correct me
if I'm wrong, but the kernel (what version exactly?) now has contains
a _cpu_pda[NR_CPUS] array containing pointers to the actual per-cpu
x8664_pda structures.  Given that, there's really no reason to GETBUF()
the storage location of the single per-cpu pointer.  When I compile
with "make Warn", I get this:

# make Warn
...
cc -c -g -DX86_64  x86_64.c -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror
x86_64.c: In function `x86_64_cpu_pda_init':
x86_64.c:389: warning: assignment from incompatible pointer type
x86_64.c:391: warning: assignment makes integer from pointer without a cast
x86_64.c: In function `x86_64_get_smp_cpus':
x86_64.c:2763: warning: assignment from incompatible pointer type
x86_64.c:2765: warning: assignment makes integer from pointer without a cast
make[3]: *** [x86_64.o] Error 1
make[2]: *** [gdb] Error 2
make[1]: *** [gdb_merge] Error 2
make: *** [Warn] Error 2
#

which is complaining about the cpu_pda pointer and its use:

    389                 cpu_pda_addr = GETBUF(sizeof(unsigned long));
    390                 for (i = cpus = 0; i < nr_pda; i++) {
    391                         *cpu_pda_addr = NULL;

   2763                 cpu_pda_addr = GETBUF(sizeof(unsigned long));
   2764                 for (i = cpus = 0; i < nr_pda; i++) {
   2765                         *cpu_pda_addr = NULL;

I'd just make cpu_pda_addr a ulong stack variable, zero it out on lines
389 and 2765, and change the _CPU_PDA_READ() macro to look
like this:

#define _CPU_PDA_READ(CPU, BUFFER) \
        ((STRNEQ("_cpu_pda", closest_symbol((symbol_value("_cpu_pda") + \
             ((CPU) * sizeof(unsigned long)))))) &&                             \
        (readmem(symbol_value("_cpu_pda") + ((CPU) * sizeof(unsigned long)),\
         KVADDR, &cpu_pda_addr, sizeof(unsigned long), "_cpu_pda addr",     \
        FAULT_ON_ERROR)) &&                                                \
        (readmem(cpu_pda_addr ,                   \
                KVADDR, (BUFFER), SIZE(x8664_pda), "cpu_pda entry",        \
                FAULT_ON_ERROR)))

Unless I'm missing something, that simplifies things and should work
just fine. But I can't test it here other than to verify that it's
backwards compatible.  Can you verify that?

Thanks again,
  Dave



>
> Thanks
> Rachita
>
> Signed-off-by: Rachita Kothiyal <rachita at in.ibm.com>
> ---
>
>  defs.h   |   10 ++++
>  x86_64.c |  139 ++++++++++++++++++++++++++++++++++++++++++++-------------------
>  2 files changed, 108 insertions(+), 41 deletions(-)
>
> diff -puN x86_64.c~crash-fix-cpu-pda x86_64.c
> --- crash-4.0-2.19/x86_64.c~crash-fix-cpu-pda   2006-01-31 17:21:35.430960480 +0530
> +++ crash-4.0-2.19-rachita/x86_64.c     2006-01-31 17:23:44.893279216 +0530
> @@ -367,7 +367,7 @@ x86_64_cpu_pda_init(void)
>  {
>         int i, cpus, nr_pda, cpunumber;
>         char *cpu_pda_buf;
> -       ulong level4_pgt, data_offset;
> +       ulong level4_pgt, data_offset, *cpu_pda_addr;
>         struct syment *sp, *nsp;
>         ulong offset, istacksize;
>
> @@ -383,36 +383,68 @@ x86_64_cpu_pda_init(void)
>
>         cpu_pda_buf = GETBUF(SIZE(x8664_pda));
>
> -       if (!(nr_pda = get_array_length("cpu_pda", NULL, 0)))
> -               nr_pda = NR_CPUS;
> -
> -       for (i = cpus = 0; i < nr_pda; i++) {
> -               if (!CPU_PDA_READ(i, cpu_pda_buf))
> -                       break;
> -               if (VALID_MEMBER(x8664_pda_level4_pgt)) {
> -                       level4_pgt = ULONG(cpu_pda_buf + OFFSET(x8664_pda_level4_pgt));
> -                       if (!VALID_LEVEL4_PGT_ADDR(level4_pgt))
> +       if (symbol_exists("_cpu_pda")) {
> +               if (!(nr_pda = get_array_length("_cpu_pda", NULL, 0)))
> +                       nr_pda = NR_CPUS;
> +               cpu_pda_addr = GETBUF(sizeof(unsigned long));
> +               for (i = cpus = 0; i < nr_pda; i++) {
> +                       *cpu_pda_addr = NULL;
> +                       if (!_CPU_PDA_READ(i, cpu_pda_buf))
>                                 break;
> -               }
> -               cpunumber = INT(cpu_pda_buf + OFFSET(x8664_pda_cpunumber));
> -               if (cpunumber != cpus)
> -                       break;
> -               cpus++;
>
> -               if (VALID_MEMBER(x8664_pda_data_offset)) {
> -                       data_offset = ULONG(cpu_pda_buf +
> -                               OFFSET(x8664_pda_data_offset));
> -                        kt->__per_cpu_offset[i] = data_offset;
> -                        kt->flags |= PER_CPU_OFF;
> -               } else
> -                       data_offset = 0;
> +                       if (VALID_MEMBER(x8664_pda_level4_pgt)) {
> +                               level4_pgt = ULONG(cpu_pda_buf + OFFSET(x8664_pda_level4_pgt));
> +                               if (!VALID_LEVEL4_PGT_ADDR(level4_pgt))
> +                                       break;
> +                       }
> +                       cpunumber = INT(cpu_pda_buf + OFFSET(x8664_pda_cpunumber));
> +                       if (cpunumber != cpus)
> +                               break;
> +                       cpus++;
>
> -               machdep->machspec->stkinfo.ibase[i] = ULONG(cpu_pda_buf +
> -                       OFFSET(x8664_pda_irqstackptr));
> +                       if (VALID_MEMBER(x8664_pda_data_offset)) {
> +                               data_offset = ULONG(cpu_pda_buf +
> +                                       OFFSET(x8664_pda_data_offset));
> +                               kt->__per_cpu_offset[i] = data_offset;
> +                               kt->flags |= PER_CPU_OFF;
> +                       } else
> +                               data_offset = 0;
> +                       machdep->machspec->stkinfo.ibase[i] = ULONG(cpu_pda_buf +
> +                               OFFSET(x8664_pda_irqstackptr));
> +                       if (CRASHDEBUG(2))
> +                               fprintf(fp, "CPU%d: level4_pgt: %lx data_offset: %lx\n",
> +                                       i, level4_pgt, data_offset);
> +               }
> +               FREEBUF(cpu_pda_addr);
> +       } else if (symbol_exists("cpu_pda")) {
> +               if (!(nr_pda = get_array_length("cpu_pda", NULL, 0)))
> +                       nr_pda = NR_CPUS;
> +               for (i = cpus = 0; i < nr_pda; i++) {
> +                       if (!CPU_PDA_READ(i, cpu_pda_buf))
> +                               break;
> +                       if (VALID_MEMBER(x8664_pda_level4_pgt)) {
> +                               level4_pgt = ULONG(cpu_pda_buf + OFFSET(x8664_pda_level4_pgt));
> +                               if (!VALID_LEVEL4_PGT_ADDR(level4_pgt))
> +                                       break;
> +                       }
> +                       cpunumber = INT(cpu_pda_buf + OFFSET(x8664_pda_cpunumber));
> +                       if (cpunumber != cpus)
> +                               break;
> +                       cpus++;
>
> -               if (CRASHDEBUG(2))
> -                       fprintf(fp, "CPU%d: level4_pgt: %lx data_offset: %lx\n",
> -                               i, level4_pgt, data_offset);
> +                       if (VALID_MEMBER(x8664_pda_data_offset)) {
> +                               data_offset = ULONG(cpu_pda_buf +
> +                                       OFFSET(x8664_pda_data_offset));
> +                               kt->__per_cpu_offset[i] = data_offset;
> +                               kt->flags |= PER_CPU_OFF;
> +                       } else
> +                               data_offset = 0;
> +                       machdep->machspec->stkinfo.ibase[i] = ULONG(cpu_pda_buf +
> +                               OFFSET(x8664_pda_irqstackptr));
> +                       if (CRASHDEBUG(2))
> +                               fprintf(fp, "CPU%d: level4_pgt: %lx data_offset: %lx\n",
> +                                       i, level4_pgt, data_offset);
> +               }
>         }
>
>
> @@ -2718,29 +2750,51 @@ x86_64_get_smp_cpus(void)
>  {
>         int i, cpus, nr_pda, cpunumber;
>         char *cpu_pda_buf;
> -       ulong level4_pgt;
> +       ulong level4_pgt, *cpu_pda_addr;
>
>         if (!VALID_STRUCT(x8664_pda))
>                 return 1;
>
>         cpu_pda_buf = GETBUF(SIZE(x8664_pda));
>
> -       if (!(nr_pda = get_array_length("cpu_pda", NULL, 0)))
> -               nr_pda = NR_CPUS;
> +       if (symbol_exists("_cpu_pda")){
> +               if (!(nr_pda = get_array_length("_cpu_pda", NULL, 0)))
> +                      nr_pda = NR_CPUS;
> +               cpu_pda_addr = GETBUF(sizeof(unsigned long));
> +               for (i = cpus = 0; i < nr_pda; i++) {
> +                       *cpu_pda_addr = NULL;
> +                       if (!_CPU_PDA_READ(i, cpu_pda_buf))
> +                               break;
>
> -       for (i = cpus = 0; i < nr_pda; i++) {
> -               if (!CPU_PDA_READ(i, cpu_pda_buf))
> -                       break;
> +                       if (VALID_MEMBER(x8664_pda_level4_pgt)) {
> +                               level4_pgt = ULONG(cpu_pda_buf + OFFSET(x8664_pda_level4_pgt));
> +                               if (!VALID_LEVEL4_PGT_ADDR(level4_pgt))
> +                                       break;
> +                       }
> +                       cpunumber = INT(cpu_pda_buf + OFFSET(x8664_pda_cpunumber));
> +                       if (cpunumber != cpus)
> +                               break;
> +                       cpus++;
> +               }
> +               FREEBUF(cpu_pda_addr);
> +       }
> +       else if (symbol_exists("cpu_pda")){
> +               if (!(nr_pda = get_array_length("cpu_pda", NULL, 0)))
> +                      nr_pda = NR_CPUS;
> +               for (i = cpus = 0; i < nr_pda; i++) {
> +                       if (!CPU_PDA_READ(i, cpu_pda_buf))
> +                               break;
>
> -               if (VALID_MEMBER(x8664_pda_level4_pgt)) {
> -                       level4_pgt = ULONG(cpu_pda_buf + OFFSET(x8664_pda_level4_pgt));
> -                       if (!VALID_LEVEL4_PGT_ADDR(level4_pgt))
> +                       if (VALID_MEMBER(x8664_pda_level4_pgt)) {
> +                               level4_pgt = ULONG(cpu_pda_buf + OFFSET(x8664_pda_level4_pgt));
> +                               if (!VALID_LEVEL4_PGT_ADDR(level4_pgt))
> +                                       break;
> +                       }
> +                       cpunumber = INT(cpu_pda_buf + OFFSET(x8664_pda_cpunumber));
> +                       if (cpunumber != cpus)
>                                 break;
> +                       cpus++;
>                 }
> -               cpunumber = INT(cpu_pda_buf + OFFSET(x8664_pda_cpunumber));
> -               if (cpunumber != cpus)
> -                       break;
> -                cpus++;
>         }
>
>         FREEBUF(cpu_pda_buf);
> @@ -2828,7 +2882,10 @@ x86_64_display_cpu_data(void)
>                 boot_cpu = TRUE;
>                 cpus = 1;
>         }
> -       cpu_pda = symbol_value("cpu_pda");
> +       if (symbol_exists("_cpu_pda"))
> +               cpu_pda = symbol_value("_cpu_pda");
> +       else if (symbol_exists("cpu_pda"))
> +               cpu_pda = symbol_value("cpu_pda");
>
>          for (cpu = 0; cpu < cpus; cpu++) {
>                 if (boot_cpu)
> diff -puN defs.h~crash-fix-cpu-pda defs.h
> --- crash-4.0-2.19/defs.h~crash-fix-cpu-pda     2006-01-31 17:25:59.479818952 +0530
> +++ crash-4.0-2.19-rachita/defs.h       2006-01-31 17:26:23.969096016 +0530
> @@ -1840,6 +1840,16 @@ struct load_module {
>
>  #define PAGEBASE(X)           (((ulong)(X)) & (ulong)machdep->pagemask)
>
> +#define _CPU_PDA_READ(CPU, BUFFER) \
> +       ((STRNEQ("_cpu_pda", closest_symbol((symbol_value("_cpu_pda") + \
> +            ((CPU) * sizeof(unsigned long)))))) &&                             \
> +               (readmem(symbol_value("_cpu_pda") + ((CPU) * sizeof(unsigned long)),\
> +        KVADDR, cpu_pda_addr, sizeof(unsigned long), "_cpu_pda addr",     \
> +       FAULT_ON_ERROR)) &&                                                \
> +       (readmem(*cpu_pda_addr ,                   \
> +               KVADDR, (BUFFER), SIZE(x8664_pda), "cpu_pda entry",        \
> +               FAULT_ON_ERROR)))
> +
>  #define CPU_PDA_READ(CPU, BUFFER) \
>         (STRNEQ("cpu_pda", closest_symbol((symbol_value("cpu_pda") +    \
>              ((CPU) * SIZE(x8664_pda))))) &&                            \
> _
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/crash-utility/attachments/20060131/f99035e9/attachment.htm>


More information about the Crash-utility mailing list