s390/unwind: make reuse_sp default when unwinding pt_regs
authorVasily Gorbik <gor@linux.ibm.com>
Fri, 22 Nov 2019 14:58:42 +0000 (15:58 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Sat, 30 Nov 2019 09:52:45 +0000 (10:52 +0100)
Currently unwinder yields 2 entries when pt_regs are met:
sp="address of pt_regs itself" ip=pt_regs->psw
sp=pt_regs->gprs[15] ip="r14 from stack frame pointed by pt_regs->gprs[15]"

And neither of those 2 states (combination of sp and ip) ever happened.

reuse_sp has been introduced by commit a1d863ac3e10 ("s390/unwind: fix
mixing regs and sp"). reuse_sp=true makes unwinder keen to produce the
following result, when pt_regs are given (as an arg to unwind_start):
sp=pt_regs->gprs[15] ip=pt_regs->psw
sp=pt_regs->gprs[15] ip="r14 from stack frame pointed by pt_regs->gprs[15]"

The first state is an actual state in which a task was when pt_regs were
collected. The second state is marked unreliable and is for debugging
purposes to cover the case when a task has been interrupted in between
stack frame allocation and writing back_chain - in this case r14 might
show an actual caller.

Make unwinder behaviour enabled via reuse_sp=true default and drop the
special case handling.

Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/include/asm/unwind.h
arch/s390/kernel/unwind_bc.c

index a2d8dd766987e233b0d91ba7519dd7d418e6fdb7..5d6c8fe7a271b6f885897cea476c20d8288158a6 100644 (file)
@@ -35,7 +35,6 @@ struct unwind_state {
        struct task_struct *task;
        struct pt_regs *regs;
        unsigned long sp, ip;
-       bool reuse_sp;
        int graph_idx;
        bool reliable;
        bool error;
index fd90b6e2166365662063f25df3277646bd02a990..ac6cfab567d189eadacd67036d43b416402d8cf1 100644 (file)
@@ -46,16 +46,7 @@ bool unwind_next_frame(struct unwind_state *state)
 
        regs = state->regs;
        if (unlikely(regs)) {
-               if (state->reuse_sp) {
-                       sp = state->sp;
-                       state->reuse_sp = false;
-               } else {
-                       sp = READ_ONCE_NOCHECK(regs->gprs[15]);
-                       if (unlikely(outside_of_stack(state, sp))) {
-                               if (!update_stack_info(state, sp))
-                                       goto out_err;
-                       }
-               }
+               sp = state->sp;
                sf = (struct stack_frame *) sp;
                ip = READ_ONCE_NOCHECK(sf->gprs[8]);
                reliable = false;
@@ -81,6 +72,11 @@ bool unwind_next_frame(struct unwind_state *state)
                        if (READ_ONCE_NOCHECK(regs->psw.mask) & PSW_MASK_PSTATE)
                                goto out_stop;
                        ip = READ_ONCE_NOCHECK(regs->psw.addr);
+                       sp = READ_ONCE_NOCHECK(regs->gprs[15]);
+                       if (unlikely(outside_of_stack(state, sp))) {
+                               if (!update_stack_info(state, sp))
+                                       goto out_err;
+                       }
                        reliable = true;
                }
        }
@@ -107,7 +103,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
 {
        struct stack_info *info = &state->stack_info;
        unsigned long *mask = &state->stack_mask;
-       bool reliable, reuse_sp;
+       bool reliable;
        struct stack_frame *sf;
        unsigned long ip;
 
@@ -134,12 +130,10 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
        if (regs) {
                ip = READ_ONCE_NOCHECK(regs->psw.addr);
                reliable = true;
-               reuse_sp = true;
        } else {
                sf = (struct stack_frame *) sp;
                ip = READ_ONCE_NOCHECK(sf->gprs[8]);
                reliable = false;
-               reuse_sp = false;
        }
 
        ip = ftrace_graph_ret_addr(state->task, &state->graph_idx, ip, NULL);
@@ -148,6 +142,5 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
        state->sp = sp;
        state->ip = ip;
        state->reliable = reliable;
-       state->reuse_sp = reuse_sp;
 }
 EXPORT_SYMBOL_GPL(__unwind_start);