linux/arch/xtensa/kernel/stacktrace.c
<<
>>
Prefs
   1/*
   2 * Kernel and userspace stack tracing.
   3 *
   4 * This file is subject to the terms and conditions of the GNU General Public
   5 * License.  See the file "COPYING" in the main directory of this archive
   6 * for more details.
   7 *
   8 * Copyright (C) 2001 - 2013 Tensilica Inc.
   9 * Copyright (C) 2015 Cadence Design Systems Inc.
  10 */
  11#include <linux/export.h>
  12#include <linux/sched.h>
  13#include <linux/stacktrace.h>
  14
  15#include <asm/stacktrace.h>
  16#include <asm/traps.h>
  17#include <linux/uaccess.h>
  18
  19#if IS_ENABLED(CONFIG_OPROFILE) || IS_ENABLED(CONFIG_PERF_EVENTS)
  20
  21/* Address of common_exception_return, used to check the
  22 * transition from kernel to user space.
  23 */
  24extern int common_exception_return;
  25
  26void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
  27                           int (*ufn)(struct stackframe *frame, void *data),
  28                           void *data)
  29{
  30        unsigned long windowstart = regs->windowstart;
  31        unsigned long windowbase = regs->windowbase;
  32        unsigned long a0 = regs->areg[0];
  33        unsigned long a1 = regs->areg[1];
  34        unsigned long pc = regs->pc;
  35        struct stackframe frame;
  36        int index;
  37
  38        if (!depth--)
  39                return;
  40
  41        frame.pc = pc;
  42        frame.sp = a1;
  43
  44        if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
  45                return;
  46
  47        /* Two steps:
  48         *
  49         * 1. Look through the register window for the
  50         * previous PCs in the call trace.
  51         *
  52         * 2. Look on the stack.
  53         */
  54
  55        /* Step 1.  */
  56        /* Rotate WINDOWSTART to move the bit corresponding to
  57         * the current window to the bit #0.
  58         */
  59        windowstart = (windowstart << WSBITS | windowstart) >> windowbase;
  60
  61        /* Look for bits that are set, they correspond to
  62         * valid windows.
  63         */
  64        for (index = WSBITS - 1; (index > 0) && depth; depth--, index--)
  65                if (windowstart & (1 << index)) {
  66                        /* Get the PC from a0 and a1. */
  67                        pc = MAKE_PC_FROM_RA(a0, pc);
  68                        /* Read a0 and a1 from the
  69                         * corresponding position in AREGs.
  70                         */
  71                        a0 = regs->areg[index * 4];
  72                        a1 = regs->areg[index * 4 + 1];
  73
  74                        frame.pc = pc;
  75                        frame.sp = a1;
  76
  77                        if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
  78                                return;
  79                }
  80
  81        /* Step 2. */
  82        /* We are done with the register window, we need to
  83         * look through the stack.
  84         */
  85        if (!depth)
  86                return;
  87
  88        /* Start from the a1 register. */
  89        /* a1 = regs->areg[1]; */
  90        while (a0 != 0 && depth--) {
  91                pc = MAKE_PC_FROM_RA(a0, pc);
  92
  93                /* Check if the region is OK to access. */
  94                if (!access_ok(VERIFY_READ, &SPILL_SLOT(a1, 0), 8))
  95                        return;
  96                /* Copy a1, a0 from user space stack frame. */
  97                if (__get_user(a0, &SPILL_SLOT(a1, 0)) ||
  98                    __get_user(a1, &SPILL_SLOT(a1, 1)))
  99                        return;
 100
 101                frame.pc = pc;
 102                frame.sp = a1;
 103
 104                if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
 105                        return;
 106        }
 107}
 108EXPORT_SYMBOL(xtensa_backtrace_user);
 109
 110void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
 111                             int (*kfn)(struct stackframe *frame, void *data),
 112                             int (*ufn)(struct stackframe *frame, void *data),
 113                             void *data)
 114{
 115        unsigned long pc = regs->depc > VALID_DOUBLE_EXCEPTION_ADDRESS ?
 116                regs->depc : regs->pc;
 117        unsigned long sp_start, sp_end;
 118        unsigned long a0 = regs->areg[0];
 119        unsigned long a1 = regs->areg[1];
 120
 121        sp_start = a1 & ~(THREAD_SIZE - 1);
 122        sp_end = sp_start + THREAD_SIZE;
 123
 124        /* Spill the register window to the stack first. */
 125        spill_registers();
 126
 127        /* Read the stack frames one by one and create the PC
 128         * from the a0 and a1 registers saved there.
 129         */
 130        while (a1 > sp_start && a1 < sp_end && depth--) {
 131                struct stackframe frame;
 132
 133                frame.pc = pc;
 134                frame.sp = a1;
 135
 136                if (kernel_text_address(pc) && kfn(&frame, data))
 137                        return;
 138
 139                if (pc == (unsigned long)&common_exception_return) {
 140                        regs = (struct pt_regs *)a1;
 141                        if (user_mode(regs)) {
 142                                if (ufn == NULL)
 143                                        return;
 144                                xtensa_backtrace_user(regs, depth, ufn, data);
 145                                return;
 146                        }
 147                        a0 = regs->areg[0];
 148                        a1 = regs->areg[1];
 149                        continue;
 150                }
 151
 152                sp_start = a1;
 153
 154                pc = MAKE_PC_FROM_RA(a0, pc);
 155                a0 = SPILL_SLOT(a1, 0);
 156                a1 = SPILL_SLOT(a1, 1);
 157        }
 158}
 159EXPORT_SYMBOL(xtensa_backtrace_kernel);
 160
 161#endif
 162
 163void walk_stackframe(unsigned long *sp,
 164                int (*fn)(struct stackframe *frame, void *data),
 165                void *data)
 166{
 167        unsigned long a0, a1;
 168        unsigned long sp_end;
 169
 170        a1 = (unsigned long)sp;
 171        sp_end = ALIGN(a1, THREAD_SIZE);
 172
 173        spill_registers();
 174
 175        while (a1 < sp_end) {
 176                struct stackframe frame;
 177
 178                sp = (unsigned long *)a1;
 179
 180                a0 = SPILL_SLOT(a1, 0);
 181                a1 = SPILL_SLOT(a1, 1);
 182
 183                if (a1 <= (unsigned long)sp)
 184                        break;
 185
 186                frame.pc = MAKE_PC_FROM_RA(a0, a1);
 187                frame.sp = a1;
 188
 189                if (fn(&frame, data))
 190                        return;
 191        }
 192}
 193
 194#ifdef CONFIG_STACKTRACE
 195
 196struct stack_trace_data {
 197        struct stack_trace *trace;
 198        unsigned skip;
 199};
 200
 201static int stack_trace_cb(struct stackframe *frame, void *data)
 202{
 203        struct stack_trace_data *trace_data = data;
 204        struct stack_trace *trace = trace_data->trace;
 205
 206        if (trace_data->skip) {
 207                --trace_data->skip;
 208                return 0;
 209        }
 210        if (!kernel_text_address(frame->pc))
 211                return 0;
 212
 213        trace->entries[trace->nr_entries++] = frame->pc;
 214        return trace->nr_entries >= trace->max_entries;
 215}
 216
 217void save_stack_trace_tsk(struct task_struct *task, struct stack_trace *trace)
 218{
 219        struct stack_trace_data trace_data = {
 220                .trace = trace,
 221                .skip = trace->skip,
 222        };
 223        walk_stackframe(stack_pointer(task), stack_trace_cb, &trace_data);
 224}
 225EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
 226
 227void save_stack_trace(struct stack_trace *trace)
 228{
 229        save_stack_trace_tsk(current, trace);
 230}
 231EXPORT_SYMBOL_GPL(save_stack_trace);
 232
 233#endif
 234
 235#ifdef CONFIG_FRAME_POINTER
 236
 237struct return_addr_data {
 238        unsigned long addr;
 239        unsigned skip;
 240};
 241
 242static int return_address_cb(struct stackframe *frame, void *data)
 243{
 244        struct return_addr_data *r = data;
 245
 246        if (r->skip) {
 247                --r->skip;
 248                return 0;
 249        }
 250        if (!kernel_text_address(frame->pc))
 251                return 0;
 252        r->addr = frame->pc;
 253        return 1;
 254}
 255
 256unsigned long return_address(unsigned level)
 257{
 258        struct return_addr_data r = {
 259                .skip = level + 1,
 260        };
 261        walk_stackframe(stack_pointer(NULL), return_address_cb, &r);
 262        return r.addr;
 263}
 264EXPORT_SYMBOL(return_address);
 265
 266#endif
 267