[Crash-utility] Re: [PATCH 3/3] RISCV64: Add per-cpu overflow stacks support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux