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_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        if (IS_ENABLED(CONFIG_USER_ABI_CALL0_ONLY) ||
  48            (IS_ENABLED(CONFIG_USER_ABI_CALL0_PROBE) &&
  49             !(regs->ps & PS_WOE_MASK)))
  50                return;
  51
  52        /* Two steps:
  53         *
  54         * 1. Look through the register window for the
  55         * previous PCs in the call trace.
  56         *
  57         * 2. Look on the stack.
  58         */
  59
  60        /* Step 1.  */
  61        /* Rotate WINDOWSTART to move the bit corresponding to
  62         * the current window to the bit #0.
  63         */
  64        windowstart = (windowstart << WSBITS | windowstart) >> windowbase;
  65
  66        /* Look for bits that are set, they correspond to
  67         * valid windows.
  68         */
  69        for (index = WSBITS - 1; (index > 0) && depth; depth--, index--)
  70                if (windowstart & (1 << index)) {
  71                        /* Get the PC from a0 and a1. */
  72                        pc = MAKE_PC_FROM_RA(a0, pc);
  73                        /* Read a0 and a1 from the
  74                         * corresponding position in AREGs.
  75                         */
  76                        a0 = regs->areg[index * 4];
  77                        a1 = regs->areg[index * 4 + 1];
  78
  79                        frame.pc = pc;
  80                        frame.sp = a1;
  81
  82                        if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
  83                                return;
  84                }
  85
  86        /* Step 2. */
  87        /* We are done with the register window, we need to
  88         * look through the stack.
  89         */
  90        if (!depth)
  91                return;
  92
  93        /* Start from the a1 register. */
  94        /* a1 = regs->areg[1]; */
  95        while (a0 != 0 && depth--) {
  96                pc = MAKE_PC_FROM_RA(a0, pc);
  97
  98                /* Check if the region is OK to access. */
  99                if (!access_ok(&SPILL_SLOT(a1, 0), 8))
 100                        return;
 101                /* Copy a1, a0 from user space stack frame. */
 102                if (__get_user(a0, &SPILL_SLOT(a1, 0)) ||
 103                    __get_user(a1, &SPILL_SLOT(a1, 1)))
 104                        return;
 105
 106                frame.pc = pc;
 107                frame.sp = a1;
 108
 109                if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
 110                        return;
 111        }
 112}
 113EXPORT_SYMBOL(xtensa_backtrace_user);
 114
 115void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
 116                             int (*kfn)(struct stackframe *frame, void *data),
 117                             int (*ufn)(struct stackframe *frame, void *data),
 118                             void *data)
 119{
 120        unsigned long pc = regs->depc > VALID_DOUBLE_EXCEPTION_ADDRESS ?
 121                regs->depc : regs->pc;
 122        unsigned long sp_start, sp_end;
 123        unsigned long a0 = regs->areg[0];
 124        unsigned long a1 = regs->areg[1];
 125
 126        sp_start = a1 & ~(THREAD_SIZE - 1);
 127        sp_end = sp_start + THREAD_SIZE;
 128
 129        /* Spill the register window to the stack first. */
 130        spill_registers();
 131
 132        /* Read the stack frames one by one and create the PC
 133         * from the a0 and a1 registers saved there.
 134         */
 135        while (a1 > sp_start && a1 < sp_end && depth--) {
 136                struct stackframe frame;
 137
 138                frame.pc = pc;
 139                frame.sp = a1;
 140
 141                if (kernel_text_address(pc) && kfn(&frame, data))
 142                        return;
 143
 144                if (pc == (unsigned long)&common_exception_return) {
 145                        regs = (struct pt_regs *)a1;
 146                        if (user_mode(regs)) {
 147                                if (ufn == NULL)
 148                                        return;
 149                                xtensa_backtrace_user(regs, depth, ufn, data);
 150                                return;
 151                        }
 152                        a0 = regs->areg[0];
 153                        a1 = regs->areg[1];
 154                        continue;
 155                }
 156
 157                sp_start = a1;
 158
 159                pc = MAKE_PC_FROM_RA(a0, pc);
 160                a0 = SPILL_SLOT(a1, 0);
 161                a1 = SPILL_SLOT(a1, 1);
 162        }
 163}
 164EXPORT_SYMBOL(xtensa_backtrace_kernel);
 165
 166#endif
 167
 168void walk_stackframe(unsigned long *sp,
 169                int (*fn)(struct stackframe *frame, void *data),
 170                void *data)
 171{
 172        unsigned long a0, a1;
 173        unsigned long sp_end;
 174
 175        a1 = (unsigned long)sp;
 176        sp_end = ALIGN(a1, THREAD_SIZE);
 177
 178        spill_registers();
 179
 180        while (a1 < sp_end) {
 181                struct stackframe frame;
 182
 183                sp = (unsigned long *)a1;
 184
 185                a0 = SPILL_SLOT(a1, 0);
 186                a1 = SPILL_SLOT(a1, 1);
 187
 188                if (a1 <= (unsigned long)sp)
 189                        break;
 190
 191                frame.pc = MAKE_PC_FROM_RA(a0, a1);
 192                frame.sp = a1;
 193
 194                if (fn(&frame, data))
 195                        return;
 196        }
 197}
 198
 199#ifdef CONFIG_STACKTRACE
 200
 201struct stack_trace_data {
 202        struct stack_trace *trace;
 203        unsigned skip;
 204};
 205
 206static int stack_trace_cb(struct stackframe *frame, void *data)
 207{
 208        struct stack_trace_data *trace_data = data;
 209        struct stack_trace *trace = trace_data->trace;
 210
 211        if (trace_data->skip) {
 212                --trace_data->skip;
 213                return 0;
 214        }
 215        if (!kernel_text_address(frame->pc))
 216                return 0;
 217
 218        trace->entries[trace->nr_entries++] = frame->pc;
 219        return trace->nr_entries >= trace->max_entries;
 220}
 221
 222void save_stack_trace_tsk(struct task_struct *task, struct stack_trace *trace)
 223{
 224        struct stack_trace_data trace_data = {
 225                .trace = trace,
 226                .skip = trace->skip,
 227        };
 228        walk_stackframe(stack_pointer(task), stack_trace_cb, &trace_data);
 229}
 230EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
 231
 232void save_stack_trace(struct stack_trace *trace)
 233{
 234        save_stack_trace_tsk(current, trace);
 235}
 236EXPORT_SYMBOL_GPL(save_stack_trace);
 237
 238#endif
 239
 240#ifdef CONFIG_FRAME_POINTER
 241
 242struct return_addr_data {
 243        unsigned long addr;
 244        unsigned skip;
 245};
 246
 247static int return_address_cb(struct stackframe *frame, void *data)
 248{
 249        struct return_addr_data *r = data;
 250
 251        if (r->skip) {
 252                --r->skip;
 253                return 0;
 254        }
 255        if (!kernel_text_address(frame->pc))
 256                return 0;
 257        r->addr = frame->pc;
 258        return 1;
 259}
 260
 261/*
 262 * level == 0 is for the return address from the caller of this function,
 263 * not from this function itself.
 264 */
 265unsigned long return_address(unsigned level)
 266{
 267        struct return_addr_data r = {
 268                .skip = level,
 269        };
 270        walk_stackframe(stack_pointer(NULL), return_address_cb, &r);
 271        return r.addr;
 272}
 273EXPORT_SYMBOL(return_address);
 274
 275#endif
 276