summaryrefslogtreecommitdiff
path: root/arch/s390/kernel/unwind_bc.c
diff options
context:
space:
mode:
authorVasily Gorbik <gor@linux.ibm.com>2019-11-22 16:49:13 +0100
committerVasily Gorbik <gor@linux.ibm.com>2019-11-30 10:52:45 +0100
commite76e69611e944ecc38aaf8fe3a7bebdc3c5daf84 (patch)
tree0f57673f7fb9e0464b6985735009b8425a1541af /arch/s390/kernel/unwind_bc.c
parentcb7948e8c3f18f7ff0ab7d0fa1e6b108d938cdd6 (diff)
s390/unwind: stop gracefully at task pt_regs
Consider reaching task pt_regs graceful unwinder termination. Task pt_regs itself never contains a valid state to which a task might return within the kernel context (user task pt_regs is a special case). Since we already avoid printing user task pt_regs and in most cases we don't even bother filling task pt_regs psw and r15 with something reasonable simply skip task pt_regs altogether. With this change unwind_error() now accurately represent whether unwinder reached task pt_regs successfully or failed along the way. Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Diffstat (limited to 'arch/s390/kernel/unwind_bc.c')
-rw-r--r--arch/s390/kernel/unwind_bc.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/arch/s390/kernel/unwind_bc.c b/arch/s390/kernel/unwind_bc.c
index ac6cfab567d1..c5ebb8a4cdd6 100644
--- a/arch/s390/kernel/unwind_bc.c
+++ b/arch/s390/kernel/unwind_bc.c
@@ -36,6 +36,12 @@ static bool update_stack_info(struct unwind_state *state, unsigned long sp)
return true;
}
+static inline bool is_task_pt_regs(struct unwind_state *state,
+ struct pt_regs *regs)
+{
+ return task_pt_regs(state->task) == regs;
+}
+
bool unwind_next_frame(struct unwind_state *state)
{
struct stack_info *info = &state->stack_info;
@@ -69,7 +75,7 @@ bool unwind_next_frame(struct unwind_state *state)
if (!on_stack(info, sp, sizeof(struct pt_regs)))
goto out_err;
regs = (struct pt_regs *) sp;
- if (READ_ONCE_NOCHECK(regs->psw.mask) & PSW_MASK_PSTATE)
+ if (is_task_pt_regs(state, regs))
goto out_stop;
ip = READ_ONCE_NOCHECK(regs->psw.addr);
sp = READ_ONCE_NOCHECK(regs->gprs[15]);