Skip to content

Commit e42404f

Browse files
committed
ARC: stack unwinding: don't assume non-current task is sleeping
To start stack unwinding (SP, PC and BLINK) are needed. When the explicit execution context (pt_regs etc) is not available, unwinder assumes the task is sleeping (in __switch_to()) and fetches SP and BLINK from kernel mode stack. But this assumption is not true, specially in a SMP system, when top runs on 1 core, there may be active running processes on all cores. So when unwinding non courrent tasks, ensure they are NOT running. And while at it, handle the self unwinding case explicitly. This came out of investigation of a customer reported hang with rcutorture+top Link: foss-for-synopsys-dwc-arc-processors#31 Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
1 parent 5f840df commit e42404f

1 file changed

Lines changed: 15 additions & 8 deletions

File tree

arch/arc/kernel/stacktrace.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@
3838

3939
#ifdef CONFIG_ARC_DW2_UNWIND
4040

41-
static void seed_unwind_frame_info(struct task_struct *tsk,
42-
struct pt_regs *regs,
43-
struct unwind_frame_info *frame_info)
41+
static int
42+
seed_unwind_frame_info(struct task_struct *tsk, struct pt_regs *regs,
43+
struct unwind_frame_info *frame_info)
4444
{
4545
/*
4646
* synchronous unwinding (e.g. dump_stack)
4747
* - uses current values of SP and friends
4848
*/
49-
if (tsk == NULL && regs == NULL) {
49+
if (regs == NULL && (tsk == NULL || tsk == current)) {
5050
unsigned long fp, sp, blink, ret;
5151
frame_info->task = current;
5252

@@ -65,11 +65,15 @@ static void seed_unwind_frame_info(struct task_struct *tsk,
6565
frame_info->call_frame = 0;
6666
} else if (regs == NULL) {
6767
/*
68-
* Asynchronous unwinding of sleeping task
69-
* - Gets SP etc from task's pt_regs (saved bottom of kernel
70-
* mode stack of task)
68+
* Asynchronous unwinding of a likely sleeping task
69+
* - first ensure it is actually sleeping
70+
* - if so, it will be in __switch_to, kernel mode SP of task
71+
* is safe-kept and BLINK at a well known location in there
7172
*/
7273

74+
if (tsk->state == TASK_RUNNING)
75+
return -1;
76+
7377
frame_info->task = tsk;
7478

7579
frame_info->regs.r27 = TSK_K_FP(tsk);
@@ -103,6 +107,8 @@ static void seed_unwind_frame_info(struct task_struct *tsk,
103107
frame_info->regs.r63 = regs->ret;
104108
frame_info->call_frame = 0;
105109
}
110+
111+
return 0;
106112
}
107113

108114
#endif
@@ -116,7 +122,8 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs,
116122
unsigned int address;
117123
struct unwind_frame_info frame_info;
118124

119-
seed_unwind_frame_info(tsk, regs, &frame_info);
125+
if (seed_unwind_frame_info(tsk, regs, &frame_info))
126+
return 0;
120127

121128
while (1) {
122129
address = UNW_PC(&frame_info);

0 commit comments

Comments
 (0)