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>

Signed-off-by: Kazuhito Hagio <k-hagio...@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
--
Crash-utility mailing list
Crash-utility@redhat.com
https://listman.redhat.com/mailman/listinfo/crash-utility
Contribution Guidelines: https://github.com/crash-utility/crash/wiki

Reply via email to