powerpc/livepatch: small cleanups in save_stack_trace_tsk_reliable()
authorJoe Lawrence <joe.lawrence@redhat.com>
Tue, 22 Jan 2019 15:57:23 +0000 (10:57 -0500)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 31 Jan 2019 05:43:38 +0000 (16:43 +1100)
Mostly cosmetic changes:

- Group common stack pointer code at the top
- Simplify the first frame logic
- Code stackframe iteration into for...loop construct
- Check for trace->nr_entries overflow before adding any into the array

Suggested-by: Nicolai Stange <nstange@suse.de>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/kernel/stacktrace.c

index 06688f4d557b4e820c02a351404f7711c3150176..28c3c25755d7fef3d4082c4d3fec63a695c655d6 100644 (file)
@@ -95,20 +95,11 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,
                                struct stack_trace *trace)
 {
        unsigned long sp;
+       unsigned long newsp;
        unsigned long stack_page = (unsigned long)task_stack_page(tsk);
        unsigned long stack_end;
        int graph_idx = 0;
-
-       /*
-        * The last frame (unwinding first) may not yet have saved
-        * its LR onto the stack.
-        */
-       int firstframe = 1;
-
-       if (tsk == current)
-               sp = current_stack_pointer();
-       else
-               sp = tsk->thread.ksp;
+       bool firstframe;
 
        stack_end = stack_page + THREAD_SIZE;
        if (!is_idle_task(tsk)) {
@@ -135,14 +126,20 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,
                stack_end -= STACK_FRAME_OVERHEAD;
        }
 
+       if (tsk == current)
+               sp = current_stack_pointer();
+       else
+               sp = tsk->thread.ksp;
+
        if (sp < stack_page + sizeof(struct thread_struct) ||
            sp > stack_end - STACK_FRAME_MIN_SIZE) {
                return 1;
        }
 
-       for (;;) {
+       for (firstframe = true; sp != stack_end;
+            firstframe = false, sp = newsp) {
                unsigned long *stack = (unsigned long *) sp;
-               unsigned long newsp, ip;
+               unsigned long ip;
 
                /* sanity check: ABI requires SP to be aligned 16 bytes. */
                if (sp & 0xF)
@@ -163,10 +160,8 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,
                 * rest of the frame may be uninitialized, continue to
                 * the next.
                 */
-               if (firstframe) {
-                       firstframe = 0;
-                       goto next;
-               }
+               if (firstframe)
+                       continue;
 
                /* Mark stacktraces with exception frames as unreliable. */
                if (sp <= stack_end - STACK_INT_FRAME_SIZE &&
@@ -193,19 +188,12 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,
                        return 1;
 #endif
 
+               if (trace->nr_entries >= trace->max_entries)
+                       return -E2BIG;
                if (!trace->skip)
                        trace->entries[trace->nr_entries++] = ip;
                else
                        trace->skip--;
-
-next:
-               if (newsp == stack_end)
-                       break;
-
-               if (trace->nr_entries >= trace->max_entries)
-                       return -E2BIG;
-
-               sp = newsp;
        }
        return 0;
 }