Skip to content

Commit a694962

Browse files
Song Shuaik-hagio
Song Shuai
authored andcommitted
RISCV64: Add per-cpu overflow stacks support
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 <[email protected]>
1 parent 12fbed3 commit a694962

File tree

2 files changed

+118
-1
lines changed

2 files changed

+118
-1
lines changed

defs.h

+6
Original file line numberDiff line numberDiff line change
@@ -3655,6 +3655,9 @@ typedef signed int s32;
36553655
#define VM_L5_2M (0x100)
36563656
#define VM_L5_1G (0x200)
36573657
#define IRQ_STACKS (0x400)
3658+
#define OVERFLOW_STACKS (0x800)
3659+
3660+
#define RISCV64_OVERFLOW_STACK_SIZE (1 << 12)
36583661

36593662
#define VM_FLAGS (VM_L3_4K | VM_L3_2M | VM_L3_1G | \
36603663
VM_L4_4K | VM_L4_2M | VM_L4_1G | \
@@ -7061,6 +7064,9 @@ struct machine_specific {
70617064
struct riscv64_register *crash_task_regs;
70627065
ulong irq_stack_size;
70637066
ulong *irq_stacks;
7067+
7068+
ulong overflow_stack_size;
7069+
ulong *overflow_stacks;
70647070
};
70657071
/* from arch/riscv/include/asm/pgtable-bits.h */
70667072
#define _PAGE_PRESENT (machdep->machspec->_page_present)

riscv64.c

+112-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ static int riscv64_kvtop(struct task_context *tc, ulong kvaddr,
3434
physaddr_t *paddr, int verbose);
3535
static void riscv64_cmd_mach(void);
3636
static void riscv64_irq_stack_init(void);
37+
static void riscv64_overflow_stack_init(void);
3738
static void riscv64_stackframe_init(void);
3839
static void riscv64_back_trace_cmd(struct bt_info *bt);
3940
static int riscv64_eframe_search(struct bt_info *bt);
@@ -59,6 +60,8 @@ static int riscv64_on_irq_stack(int , ulong);
5960
static int riscv64_on_process_stack(struct bt_info *, ulong );
6061
static void riscv64_set_process_stack(struct bt_info *);
6162
static void riscv64_set_irq_stack(struct bt_info *);
63+
static int riscv64_on_overflow_stack(int, ulong);
64+
static void riscv64_set_overflow_stack(struct bt_info *);
6265

6366
#define REG_FMT "%016lx"
6467
#define SZ_2G 0x80000000
@@ -206,6 +209,8 @@ riscv64_dump_machdep_table(ulong arg)
206209
fprintf(fp, "%sKSYMS_START", others++ ? "|" : "");
207210
if (machdep->flags & IRQ_STACKS)
208211
fprintf(fp, "%sIRQ_STACKS", others++ ? "|" : "");
212+
if (machdep->flags & OVERFLOW_STACKS)
213+
fprintf(fp, "%sOVERFLOW_STACKS", others++ ? "|" : "");
209214
fprintf(fp, ")\n");
210215

211216
fprintf(fp, " kvbase: %lx\n", machdep->kvbase);
@@ -270,6 +275,15 @@ riscv64_dump_machdep_table(ulong arg)
270275
fprintf(fp, " irq_stack_size: (unused)\n");
271276
fprintf(fp, " irq_stacks: (unused)\n");
272277
}
278+
if (machdep->flags & OVERFLOW_STACKS) {
279+
fprintf(fp, " overflow_stack_size: %ld\n", ms->overflow_stack_size);
280+
for (i = 0; i < kt->cpus; i++)
281+
fprintf(fp, " overflow_stacks[%d]: %lx\n",
282+
i, ms->overflow_stacks[i]);
283+
} else {
284+
fprintf(fp, " overflow_stack_size: (unused)\n");
285+
fprintf(fp, " overflow_stacks: (unused)\n");
286+
}
273287
}
274288

275289
static ulong
@@ -684,6 +698,48 @@ riscv64_display_full_frame(struct bt_info *bt, struct riscv64_unwind_frame *curr
684698
fprintf(fp, "\n");
685699
}
686700

701+
702+
/*
703+
* Gather Overflow stack values.
704+
*/
705+
static void
706+
riscv64_overflow_stack_init(void)
707+
{
708+
int i;
709+
struct syment *sp;
710+
struct gnu_request request, *req;
711+
struct machine_specific *ms = machdep->machspec;
712+
req = &request;
713+
714+
if (symbol_exists("overflow_stack") &&
715+
(sp = per_cpu_symbol_search("overflow_stack")) &&
716+
get_symbol_type("overflow_stack", NULL, req)) {
717+
if (CRASHDEBUG(1)) {
718+
fprintf(fp, "overflow_stack: \n");
719+
fprintf(fp, " type: %x, %s\n",
720+
(int)req->typecode,
721+
(req->typecode == TYPE_CODE_ARRAY) ?
722+
"TYPE_CODE_ARRAY" : "other");
723+
fprintf(fp, " target_typecode: %x, %s\n",
724+
(int)req->target_typecode,
725+
req->target_typecode == TYPE_CODE_INT ?
726+
"TYPE_CODE_INT" : "other");
727+
fprintf(fp, " target_length: %ld\n",
728+
req->target_length);
729+
fprintf(fp, " length: %ld\n", req->length);
730+
}
731+
732+
if (!(ms->overflow_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong)))))
733+
error(FATAL, "cannot malloc overflow_stack addresses\n");
734+
735+
ms->overflow_stack_size = RISCV64_OVERFLOW_STACK_SIZE;
736+
machdep->flags |= OVERFLOW_STACKS;
737+
738+
for (i = 0; i < kt->cpus; i++)
739+
ms->overflow_stacks[i] = kt->__per_cpu_offset[i] + sp->value;
740+
}
741+
}
742+
687743
/*
688744
* Gather IRQ stack values.
689745
*/
@@ -757,6 +813,23 @@ riscv64_on_irq_stack(int cpu, ulong stkptr)
757813
return FALSE;
758814
}
759815

816+
static int
817+
riscv64_on_overflow_stack(int cpu, ulong stkptr)
818+
{
819+
struct machine_specific *ms = machdep->machspec;
820+
ulong * stacks = ms->overflow_stacks;
821+
ulong stack_size = ms->overflow_stack_size;
822+
823+
if ((cpu >= kt->cpus) || (stacks == NULL) || !stack_size)
824+
return FALSE;
825+
826+
if ((stkptr >= stacks[cpu]) &&
827+
(stkptr < (stacks[cpu] + stack_size)))
828+
return TRUE;
829+
830+
return FALSE;
831+
}
832+
760833
static int
761834
riscv64_on_process_stack(struct bt_info *bt, ulong stkptr)
762835
{
@@ -781,6 +854,16 @@ riscv64_set_irq_stack(struct bt_info *bt)
781854
alter_stackbuf(bt);
782855
}
783856

857+
static void
858+
riscv64_set_overflow_stack(struct bt_info *bt)
859+
{
860+
struct machine_specific *ms = machdep->machspec;
861+
862+
bt->stackbase = ms->overflow_stacks[bt->tc->processor];
863+
bt->stacktop = bt->stackbase + ms->overflow_stack_size;
864+
alter_stackbuf(bt);
865+
}
866+
784867
static void
785868
riscv64_set_process_stack(struct bt_info *bt)
786869
{
@@ -875,7 +958,7 @@ riscv64_back_trace_cmd(struct bt_info *bt)
875958
{
876959
struct riscv64_unwind_frame current, previous;
877960
struct stackframe curr_frame;
878-
struct riscv64_register *regs, *irq_regs;
961+
struct riscv64_register *regs, *irq_regs, *overflow_regs;
879962
int level = 0;
880963

881964
if (bt->flags & BT_REGS_NOT_FOUND)
@@ -888,6 +971,11 @@ riscv64_back_trace_cmd(struct bt_info *bt)
888971
bt->flags |= BT_IRQSTACK;
889972
}
890973

974+
if (riscv64_on_overflow_stack(bt->tc->processor, bt->frameptr)) {
975+
riscv64_set_overflow_stack(bt);
976+
bt->flags |= BT_OVERFLOW_STACK;
977+
}
978+
891979
current.pc = bt->instptr;
892980
current.sp = bt->stkptr;
893981
current.fp = bt->frameptr;
@@ -971,6 +1059,28 @@ riscv64_back_trace_cmd(struct bt_info *bt)
9711059
}
9721060
}
9731061

1062+
/*
1063+
* When backtracing to handle_kernel_stack_overflow()
1064+
* use pt_regs saved in overflow stack to continue
1065+
*/
1066+
if ((bt->flags & BT_OVERFLOW_STACK) &&
1067+
!riscv64_on_overflow_stack(bt->tc->processor, current.fp)) {
1068+
1069+
overflow_regs = (struct riscv64_register *)
1070+
&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(current.sp))];
1071+
1072+
riscv64_print_exception_frame(bt, current.sp, KERNEL_MODE);
1073+
1074+
current.pc = overflow_regs->regs[RISCV64_REGS_EPC];
1075+
current.fp = overflow_regs->regs[RISCV64_REGS_FP];
1076+
current.sp = overflow_regs->regs[RISCV64_REGS_SP];
1077+
1078+
riscv64_set_process_stack(bt);
1079+
1080+
bt->flags &= ~BT_OVERFLOW_STACK;
1081+
fprintf(fp, "--- <OVERFLOW stack> ---\n");
1082+
}
1083+
9741084
if (CRASHDEBUG(8))
9751085
fprintf(fp, "next %d pc %#lx sp %#lx fp %lx\n",
9761086
level, current.pc, current.sp, current.fp);
@@ -1583,6 +1693,7 @@ riscv64_init(int when)
15831693
machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
15841694

15851695
riscv64_irq_stack_init();
1696+
riscv64_overflow_stack_init();
15861697
riscv64_stackframe_init();
15871698
riscv64_page_type_init();
15881699

0 commit comments

Comments
 (0)