Skip to content

Commit eef06cb

Browse files
author
Vasily Gorbik
committed
s390/unwind: stop gracefully at user mode pt_regs in irq stack
Consider reaching user mode pt_regs at the bottom of irq stack graceful unwinder termination. This is the case when irq/mcck/ext interrupt arrives while in user mode. Signed-off-by: Vasily Gorbik <[email protected]>
1 parent c23587c commit eef06cb

File tree

1 file changed

+11
-4
lines changed

1 file changed

+11
-4
lines changed

arch/s390/kernel/unwind_bc.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,17 @@ static bool update_stack_info(struct unwind_state *state, unsigned long sp)
3636
return true;
3737
}
3838

39-
static inline bool is_task_pt_regs(struct unwind_state *state,
40-
struct pt_regs *regs)
39+
static inline bool is_final_pt_regs(struct unwind_state *state,
40+
struct pt_regs *regs)
4141
{
42-
return task_pt_regs(state->task) == regs;
42+
/* user mode or kernel thread pt_regs at the bottom of task stack */
43+
if (task_pt_regs(state->task) == regs)
44+
return true;
45+
46+
/* user mode pt_regs at the bottom of irq stack */
47+
return state->stack_info.type == STACK_TYPE_IRQ &&
48+
state->stack_info.end - sizeof(struct pt_regs) == (unsigned long)regs &&
49+
READ_ONCE_NOCHECK(regs->psw.mask) & PSW_MASK_PSTATE;
4350
}
4451

4552
bool unwind_next_frame(struct unwind_state *state)
@@ -80,7 +87,7 @@ bool unwind_next_frame(struct unwind_state *state)
8087
if (!on_stack(info, sp, sizeof(struct pt_regs)))
8188
goto out_err;
8289
regs = (struct pt_regs *) sp;
83-
if (is_task_pt_regs(state, regs))
90+
if (is_final_pt_regs(state, regs))
8491
goto out_stop;
8592
ip = READ_ONCE_NOCHECK(regs->psw.addr);
8693
sp = READ_ONCE_NOCHECK(regs->gprs[15]);

0 commit comments

Comments
 (0)