On 2023/12/13 18:45, Song Shuai wrote: > The patch introduces per-cpu overflow stacks for RISCV64 to let > "bt" do backtrace on it and the 'help -m' command dispalys the > addresss of each per-cpu overflow stack. > > TEST: a lkdtm DIRECT EXHAUST_STACK vmcore > > ``` > crash> bt > PID: 1 TASK: ff600000000d8000 CPU: 1 COMMAND: "sh" > #0 [ff6000001fc501c0] riscv_crash_save_regs at ffffffff8000a1dc > #1 [ff6000001fc50320] panic at ffffffff808773ec > #2 [ff6000001fc50380] walk_stackframe at ffffffff800056da > PC: ffffffff80876a34 [memset+96] > RA: ffffffff80563dc0 [recursive_loop+68] > SP: ff2000000000fd50 CAUSE: 000000000000000f > epc : ffffffff80876a34 ra : ffffffff80563dc0 sp : ff2000000000fd50 > gp : ffffffff81515d38 tp : 0000000000000000 t0 : ff2000000000fd58 > t1 : ff600000000d88c8 t2 : 6143203a6d74646b s0 : ff20000000010190 > s1 : 0000000000000012 a0 : ff2000000000fd58 a1 : 1212121212121212 > a2 : 0000000000000400 a3 : ff20000000010158 a4 : 0000000000000000 > a5 : 725bedba92260900 a6 : 000000000130e0f0 a7 : 0000000000000000 > s2 : ff2000000000fd58 s3 : ffffffff815170d8 s4 : ff20000000013e60 > s5 : 000000000000000e s6 : ff20000000013e60 s7 : 0000000000000000 > s8 : ff60000000861000 s9 : 00007fffc3641694 s10: 00007fffc3641690 > s11: 00005555796ed240 t3 : 0000000000010297 t4 : ffffffff80c17810 > t5 : ffffffff8195e7b8 t6 : ff20000000013b18 > status: 0000000200000120 badaddr: ff2000000000fd58 > cause: 000000000000000f orig_a0: 0000000000000000 > --- <OVERFLOW stack> --- > #3 [ff2000000000fd50] memset at ffffffff80876a34 > #4 [ff20000000010190] recursive_loop at ffffffff80563e16 > #5 [ff200000000105d0] recursive_loop at ffffffff80563e16 > < recursive_loop ...> > #16 [ff20000000013490] recursive_loop at ffffffff80563e16 > #17 [ff200000000138d0] recursive_loop at ffffffff80563e16 > #18 [ff20000000013d10] lkdtm_EXHAUST_STACK at ffffffff8088005e > #19 [ff20000000013d30] lkdtm_do_action at ffffffff80563292 > #20 [ff20000000013d40] direct_entry at ffffffff80563474 > #21 [ff20000000013d70] full_proxy_write at ffffffff8032fb3a > #22 [ff20000000013db0] vfs_write at ffffffff801d6414 > #23 [ff20000000013e60] ksys_write at ffffffff801d67b8 > #24 [ff20000000013eb0] __riscv_sys_write at ffffffff801d6832 > #25 [ff20000000013ec0] do_trap_ecall_u at ffffffff80884a20 > crash> > > crash> help -m > <snip> > irq_stack_size: 16384 > irq_stacks[0]: ff20000000000000 > irq_stacks[1]: ff20000000008000 > overflow_stack_size: 4096 > overflow_stacks[0]: ff6000001fa7a510 > overflow_stacks[1]: ff6000001fc4f510 > crash> > ``` > Signed-off-by: Song Shuai <songshuaishuai@xxxxxxxxxxx> > --- > defs.h | 6 +++ > riscv64.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- > 2 files changed, 120 insertions(+), 3 deletions(-) > > diff --git a/defs.h b/defs.h > index 7b9fcce..5369d57 100644 > --- a/defs.h > +++ b/defs.h > @@ -3656,6 +3656,9 @@ typedef signed int s32; > #define VM_L5_2M (0x100) > #define VM_L5_1G (0x200) > #define IRQ_STACKS (0x400) > +#define OVERFLOW_STACKS (0x800) > + > +#define RISCV64_OVERFLOW_STACK_SIZE (1 << 12) > > #define VM_FLAGS (VM_L3_4K | VM_L3_2M | VM_L3_1G | \ > VM_L4_4K | VM_L4_2M | VM_L4_1G | \ > @@ -7048,6 +7051,9 @@ struct machine_specific { > struct riscv64_register *crash_task_regs; > ulong irq_stack_size; > ulong *irq_stacks; > + > + ulong overflow_stack_size; > + ulong *overflow_stacks; > }; > /* from arch/riscv/include/asm/pgtable-bits.h */ > #define _PAGE_PRESENT (machdep->machspec->_page_present) > diff --git a/riscv64.c b/riscv64.c > index a69dfe5..c5a85e8 100644 > --- a/riscv64.c > +++ b/riscv64.c > @@ -34,6 +34,7 @@ static int riscv64_kvtop(struct task_context *tc, ulong kvaddr, > physaddr_t *paddr, int verbose); > static void riscv64_cmd_mach(void); > static void riscv64_irq_stack_init(void); > +static void riscv64_overflow_stack_init(void); > static void riscv64_stackframe_init(void); > static void riscv64_back_trace_cmd(struct bt_info *bt); > static int riscv64_eframe_search(struct bt_info *bt); > @@ -59,9 +60,13 @@ static int riscv64_on_irq_stack(int , ulong); > static int riscv64_on_process_stack(struct bt_info *, ulong ); > static void riscv64_set_process_stack(struct bt_info *); > static void riscv64_set_irq_stack(struct bt_info *); > +static int riscv64_on_overflow_stack(int, ulong); > +static void riscv64_set_overflow_stack(struct bt_info *); > > #define REG_FMT "%016lx" > #define SZ_2G 0x80000000 > +#define USER_MODE (0) > +#define KERNEL_MODE (1) I moved this "move" to the 2/3 patch due to a compilation error and tweaked some indents and spaces, and applied. https://github.com/crash-utility/crash/compare/edb2bd5...a694962 (ugh, I didn't notice that those stack addresses should be printed by "mach" command like other architectures..) Thanks, Kazu > > /* > * Holds registers during the crash. > @@ -204,6 +209,8 @@ riscv64_dump_machdep_table(ulong arg) > fprintf(fp, "%sKSYMS_START", others++ ? "|" : ""); > if (machdep->flags & IRQ_STACKS) > fprintf(fp, "%sIRQ_STACKS", others++ ? "|" : ""); > + if (machdep->flags & OVERFLOW_STACKS) > + fprintf(fp, "%sOVERFLOW_STACKS", others++ ? "|" : ""); > fprintf(fp, ")\n"); > > fprintf(fp, " kvbase: %lx\n", machdep->kvbase); > @@ -268,6 +275,15 @@ riscv64_dump_machdep_table(ulong arg) > fprintf(fp, " irq_stack_size: (unused)\n"); > fprintf(fp, " irq_stacks: (unused)\n"); > } > + if (machdep->flags & OVERFLOW_STACKS) { > + fprintf(fp, " overflow_stack_size: %ld\n", ms->overflow_stack_size); > + for (i = 0; i < kt->cpus; i++) > + fprintf(fp, " overflow_stacks[%d]: %lx\n", > + i, ms->overflow_stacks[i]); > + } else { > + fprintf(fp, " overflow_stack_size: (unused)\n"); > + fprintf(fp, " overflow_stacks: (unused)\n"); > + } > } > > static ulong > @@ -682,6 +698,48 @@ riscv64_display_full_frame(struct bt_info *bt, struct riscv64_unwind_frame *curr > fprintf(fp, "\n"); > } > > + > +/* > + * Gather Overflow stack values. > + */ > +static void > +riscv64_overflow_stack_init(void) > +{ > + int i; > + struct syment *sp; > + struct gnu_request request, *req; > + struct machine_specific *ms = machdep->machspec; > + req = &request; > + > + if (symbol_exists("overflow_stack") && > + (sp = per_cpu_symbol_search("overflow_stack")) && > + get_symbol_type("overflow_stack", NULL, req)) { > + if (CRASHDEBUG(1)) { > + fprintf(fp, "overflow_stack: \n"); > + fprintf(fp, " type: %x, %s\n", > + (int)req->typecode, > + (req->typecode == TYPE_CODE_ARRAY) ? > + "TYPE_CODE_ARRAY" : "other"); > + fprintf(fp, " target_typecode: %x, %s\n", > + (int)req->target_typecode, > + req->target_typecode == TYPE_CODE_INT ? > + "TYPE_CODE_INT" : "other"); > + fprintf(fp, " target_length: %ld\n", > + req->target_length); > + fprintf(fp, " length: %ld\n", req->length); > + } > + > + if (!(ms->overflow_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong))))) > + error(FATAL, "cannot malloc overflow_stack addresses\n"); > + > + ms->overflow_stack_size = RISCV64_OVERFLOW_STACK_SIZE; > + machdep->flags |= OVERFLOW_STACKS; > + > + for (i = 0; i < kt->cpus; i++) > + ms->overflow_stacks[i] = kt->__per_cpu_offset[i] + sp->value; > + } > +} > + > /* > * Gather IRQ stack values. > */ > @@ -755,6 +813,23 @@ riscv64_on_irq_stack(int cpu, ulong stkptr) > return FALSE; > } > > +static int > +riscv64_on_overflow_stack(int cpu, ulong stkptr) > +{ > + struct machine_specific *ms = machdep->machspec; > + ulong * stacks = ms->overflow_stacks; > + ulong stack_size = ms->overflow_stack_size; > + > + if ((cpu >= kt->cpus) || (stacks == NULL) || !stack_size) > + return FALSE; > + > + if ((stkptr >= stacks[cpu]) && > + (stkptr < (stacks[cpu] + stack_size))) > + return TRUE; > + > + return FALSE; > +} > + > static int > riscv64_on_process_stack(struct bt_info *bt, ulong stkptr) > { > @@ -779,6 +854,16 @@ riscv64_set_irq_stack(struct bt_info *bt) > alter_stackbuf(bt); > } > > +static void > +riscv64_set_overflow_stack(struct bt_info *bt) > +{ > + struct machine_specific *ms = machdep->machspec; > + > + bt->stackbase = ms->overflow_stacks[bt->tc->processor]; > + bt->stacktop = bt->stackbase + ms->overflow_stack_size; > + alter_stackbuf(bt); > +} > + > static void > riscv64_set_process_stack(struct bt_info *bt) > { > @@ -873,7 +958,7 @@ riscv64_back_trace_cmd(struct bt_info *bt) > { > struct riscv64_unwind_frame current, previous; > struct stackframe curr_frame; > - struct riscv64_register *regs, *irq_regs; > + struct riscv64_register *regs, *irq_regs, *overflow_regs; > int level = 0; > > if (bt->flags & BT_REGS_NOT_FOUND) > @@ -885,6 +970,11 @@ riscv64_back_trace_cmd(struct bt_info *bt) > if (riscv64_on_irq_stack(bt->tc->processor, bt->frameptr)) { > riscv64_set_irq_stack(bt); > bt->flags |= BT_IRQSTACK; > + } > + > + if (riscv64_on_overflow_stack(bt->tc->processor, bt->frameptr)) { > + riscv64_set_overflow_stack(bt); > + bt->flags |= BT_OVERFLOW_STACK; > } > > current.pc = bt->instptr; > @@ -970,6 +1060,28 @@ riscv64_back_trace_cmd(struct bt_info *bt) > } > } > > + /* When backtracing to handle_kernel_stack_overflow() > + * use pt_regs saved in overflow stack to continue > + */ > + > + if ((bt->flags & BT_OVERFLOW_STACK) && > + !riscv64_on_overflow_stack(bt->tc->processor, current.fp)) { > + > + overflow_regs = (struct riscv64_register *) > + &bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(current.sp))]; > + > + riscv64_print_exception_frame(bt, current.sp, KERNEL_MODE); > + > + current.pc = overflow_regs->regs[RISCV64_REGS_EPC]; > + current.fp = overflow_regs->regs[RISCV64_REGS_FP]; > + current.sp = overflow_regs->regs[RISCV64_REGS_SP]; > + > + riscv64_set_process_stack(bt); > + > + bt->flags &= ~BT_OVERFLOW_STACK; > + fprintf(fp, "--- <OVERFLOW stack> ---\n"); > + } > + > if (CRASHDEBUG(8)) > fprintf(fp, "next %d pc %#lx sp %#lx fp %lx\n", > level, current.pc, current.sp, current.fp); > @@ -1582,6 +1694,7 @@ riscv64_init(int when) > machdep->max_physmem_bits = _MAX_PHYSMEM_BITS; > > riscv64_irq_stack_init(); > + riscv64_overflow_stack_init(); > riscv64_stackframe_init(); > riscv64_page_type_init(); > > @@ -1678,8 +1791,6 @@ riscv64_display_regs_from_elf_notes(int cpu, FILE *ofp) > riscv64_dump_pt_regs(regs, ofp, 0); > } > > -#define USER_MODE (0) > -#define KERNEL_MODE (1) > > static void > riscv64_print_exception_frame(struct bt_info *bt, ulong ptr, int mode) -- Crash-utility mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxxxxxx To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxxxxxx https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/ Contribution Guidelines: https://github.com/crash-utility/crash/wiki