On Wed, Dec 7, 2022 at 8:47 AM HAGIO KAZUHITO(萩尾 一仁) <k-hagio-ab(a)nec.com> wrote:
 The following kernel commits (in linux-next now, to be updated)
 introduced struct pcpu_hot and moved several per-cpu variables into it.
    d7b6d709a76a x86/percpu: Move irq_stack variables next to current_task
    7443b296e699 x86/percpu: Move cpu_number next to current_task
    e57ef2ed97c1 x86: Put hot per CPU variables into a struct
 Without the patch, crash fails to start session with the following
 error:
    bt: invalid size request: 0  type: "stack contents"
    bt: read of stack at 0 failed
       <segmentation violation in gdb>
 
Thank you for the early fix, Kazu.
This change looks good. So: Ack
Thanks.
Lianbo
 Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
 ---
   x86_64.c | 44 +++++++++++++++++++++++++++++++++-----------
   1 file changed, 33 insertions(+), 11 deletions(-)
 diff --git a/x86_64.c b/x86_64.c
 index 74bd1bbde41c..7a5d6f050c89 100644
 --- a/x86_64.c
 +++ b/x86_64.c
 @@ -1290,12 +1290,15 @@ x86_64_per_cpu_init(void)
   {
         int i, cpus, cpunumber;
         struct machine_specific *ms;
 -       struct syment *irq_sp, *curr_sp, *cpu_sp, *hardirq_stack_ptr_sp;
 +       struct syment *irq_sp, *curr_sp, *cpu_sp, *hardirq_stack_ptr_sp, *pcpu_sp;
         ulong hardirq_stack_ptr;
         ulong __per_cpu_load = 0;
 +       long hardirq_addr = 0, cpu_addr = 0, curr_addr = 0;
         ms = machdep->machspec;
 +       pcpu_sp = per_cpu_symbol_search("pcpu_hot");
 +
         hardirq_stack_ptr_sp = per_cpu_symbol_search("hardirq_stack_ptr");
         irq_sp = per_cpu_symbol_search("per_cpu__irq_stack_union");
         cpu_sp = per_cpu_symbol_search("per_cpu__cpu_number");
 @@ -1324,7 +1327,7 @@ x86_64_per_cpu_init(void)
                 return;
         }
 -       if (!cpu_sp || (!irq_sp && !hardirq_stack_ptr_sp))
 +       if (!pcpu_sp && (!cpu_sp || (!irq_sp && !hardirq_stack_ptr_sp)))
                 return;
         if (MEMBER_EXISTS("irq_stack_union", "irq_stack"))
 @@ -1337,10 +1340,21 @@ x86_64_per_cpu_init(void)
         if (kernel_symbol_exists("__per_cpu_load"))
                 __per_cpu_load = symbol_value("__per_cpu_load");
 +       if (pcpu_sp) {
 +               hardirq_addr = pcpu_sp->value + MEMBER_OFFSET("pcpu_hot",
"hardirq_stack_ptr");
 +               cpu_addr = pcpu_sp->value + MEMBER_OFFSET("pcpu_hot",
"cpu_number");
 +               curr_addr = pcpu_sp->value + MEMBER_OFFSET("pcpu_hot",
"current_task");
 +       } else {
 +               if (hardirq_stack_ptr_sp)
 +                       hardirq_addr = hardirq_stack_ptr_sp->value;
 +               cpu_addr = cpu_sp->value;
 +               curr_addr = curr_sp->value;
 +       }
 +
         for (i = cpus = 0; i < NR_CPUS; i++) {
                 if (__per_cpu_load && kt->__per_cpu_offset[i] ==
__per_cpu_load)
                         break;
 -               if (!readmem(cpu_sp->value + kt->__per_cpu_offset[i],
 +               if (!readmem(cpu_addr + kt->__per_cpu_offset[i],
                     KVADDR, &cpunumber, sizeof(int),
                     "cpu number (per_cpu)", QUIET|RETURN_ON_ERROR))
                         break;
 @@ -1349,8 +1363,8 @@ x86_64_per_cpu_init(void)
                         break;
                 cpus++;
 -               if (hardirq_stack_ptr_sp) {
 -                       if (!readmem(hardirq_stack_ptr_sp->value +
kt->__per_cpu_offset[i],
 +               if (pcpu_sp || hardirq_stack_ptr_sp) {
 +                       if (!readmem(hardirq_addr + kt->__per_cpu_offset[i],
                             KVADDR, &hardirq_stack_ptr, sizeof(void *),
                             "hardirq_stack_ptr (per_cpu)",
QUIET|RETURN_ON_ERROR))
                                 continue;
 @@ -1373,13 +1387,13 @@ x86_64_per_cpu_init(void)
         else
                 kt->cpus = cpus;
 -       if (DUMPFILE() && curr_sp) {
 +       if (DUMPFILE() && (pcpu_sp || curr_sp)) {
                 if ((ms->current = calloc(kt->cpus, sizeof(ulong))) == NULL)
                         error(FATAL,
                             "cannot calloc %d x86_64 current pointers!\n",
                                 kt->cpus);
                 for (i = 0; i < kt->cpus; i++)
 -                       if (!readmem(curr_sp->value + kt->__per_cpu_offset[i],
 +                       if (!readmem(curr_addr + kt->__per_cpu_offset[i],
                             KVADDR, &ms->current[i], sizeof(ulong),
                             "current_task (per_cpu)", RETURN_ON_ERROR))
                                 continue;
 @@ -5625,11 +5639,19 @@ x86_64_get_smp_cpus(void)
         char *cpu_pda_buf;
         ulong level4_pgt, cpu_pda_addr;
         struct syment *sp;
 -       ulong __per_cpu_load = 0;
 +       ulong __per_cpu_load = 0, cpu_addr;
         if (!VALID_STRUCT(x8664_pda)) {
 -               if (!(sp = per_cpu_symbol_search("per_cpu__cpu_number")) ||
 -                   !(kt->flags & PER_CPU_OFF))
 +
 +               if (!(kt->flags & PER_CPU_OFF))
 +                       return 1;
 +
 +               if ((sp = per_cpu_symbol_search("pcpu_hot")) &&
 +                   (cpu_addr = MEMBER_OFFSET("pcpu_hot",
"cpu_number")) != INVALID_OFFSET)
 +                       cpu_addr += sp->value;
 +               else if ((sp = per_cpu_symbol_search("per_cpu__cpu_number")))
 +                       cpu_addr = sp->value;
 +               else
                         return 1;
                 if (kernel_symbol_exists("__per_cpu_load"))
 @@ -5638,7 +5660,7 @@ x86_64_get_smp_cpus(void)
                 for (i = cpus = 0; i < NR_CPUS; i++) {
                         if (__per_cpu_load && kt->__per_cpu_offset[i] ==
__per_cpu_load)
                                 break;
 -                       if (!readmem(sp->value + kt->__per_cpu_offset[i],
 +                       if (!readmem(cpu_addr + kt->__per_cpu_offset[i],
                             KVADDR, &cpunumber, sizeof(int),
                             "cpu number (per_cpu)", QUIET|RETURN_ON_ERROR))
                                 break;
 --
 2.31.1