[Crash-utility] [PATCH] x86_64: Fix for move of per-cpu variables into struct pcpu_hot
lijiang
lijiang at redhat.com
Mon Dec 12 07:34:13 UTC 2022
On Wed, Dec 7, 2022 at 8:47 AM HAGIO KAZUHITO(萩尾 一仁) <k-hagio-ab at 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 at 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
More information about the Crash-utility
mailing list