13e4196a5SMax Filippov /* 25fdf377dSMax Filippov * Kernel and userspace stack tracing. 33e4196a5SMax Filippov * 43e4196a5SMax Filippov * This file is subject to the terms and conditions of the GNU General Public 53e4196a5SMax Filippov * License. See the file "COPYING" in the main directory of this archive 63e4196a5SMax Filippov * for more details. 73e4196a5SMax Filippov * 83e4196a5SMax Filippov * Copyright (C) 2001 - 2013 Tensilica Inc. 95fdf377dSMax Filippov * Copyright (C) 2015 Cadence Design Systems Inc. 103e4196a5SMax Filippov */ 113e4196a5SMax Filippov #include <linux/export.h> 123e4196a5SMax Filippov #include <linux/sched.h> 133e4196a5SMax Filippov #include <linux/stacktrace.h> 143e4196a5SMax Filippov 153e4196a5SMax Filippov #include <asm/stacktrace.h> 163e4196a5SMax Filippov #include <asm/traps.h> 177c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 185fdf377dSMax Filippov 195fdf377dSMax Filippov #if IS_ENABLED(CONFIG_OPROFILE) || IS_ENABLED(CONFIG_PERF_EVENTS) 205fdf377dSMax Filippov 215fdf377dSMax Filippov /* Address of common_exception_return, used to check the 225fdf377dSMax Filippov * transition from kernel to user space. 235fdf377dSMax Filippov */ 245fdf377dSMax Filippov extern int common_exception_return; 255fdf377dSMax Filippov 265fdf377dSMax Filippov /* A struct that maps to the part of the frame containing the a0 and 275fdf377dSMax Filippov * a1 registers. 285fdf377dSMax Filippov */ 295fdf377dSMax Filippov struct frame_start { 305fdf377dSMax Filippov unsigned long a0; 315fdf377dSMax Filippov unsigned long a1; 325fdf377dSMax Filippov }; 335fdf377dSMax Filippov 345fdf377dSMax Filippov void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth, 355fdf377dSMax Filippov int (*ufn)(struct stackframe *frame, void *data), 365fdf377dSMax Filippov void *data) 375fdf377dSMax Filippov { 385fdf377dSMax Filippov unsigned long windowstart = regs->windowstart; 395fdf377dSMax Filippov unsigned long windowbase = regs->windowbase; 405fdf377dSMax Filippov unsigned long a0 = regs->areg[0]; 415fdf377dSMax Filippov unsigned long a1 = regs->areg[1]; 425fdf377dSMax Filippov unsigned long pc = regs->pc; 435fdf377dSMax Filippov struct stackframe frame; 445fdf377dSMax Filippov int index; 455fdf377dSMax Filippov 465fdf377dSMax Filippov if (!depth--) 475fdf377dSMax Filippov return; 485fdf377dSMax Filippov 495fdf377dSMax Filippov frame.pc = pc; 505fdf377dSMax Filippov frame.sp = a1; 515fdf377dSMax Filippov 525fdf377dSMax Filippov if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data)) 535fdf377dSMax Filippov return; 545fdf377dSMax Filippov 555fdf377dSMax Filippov /* Two steps: 565fdf377dSMax Filippov * 575fdf377dSMax Filippov * 1. Look through the register window for the 585fdf377dSMax Filippov * previous PCs in the call trace. 595fdf377dSMax Filippov * 605fdf377dSMax Filippov * 2. Look on the stack. 615fdf377dSMax Filippov */ 625fdf377dSMax Filippov 635fdf377dSMax Filippov /* Step 1. */ 645fdf377dSMax Filippov /* Rotate WINDOWSTART to move the bit corresponding to 655fdf377dSMax Filippov * the current window to the bit #0. 665fdf377dSMax Filippov */ 675fdf377dSMax Filippov windowstart = (windowstart << WSBITS | windowstart) >> windowbase; 685fdf377dSMax Filippov 695fdf377dSMax Filippov /* Look for bits that are set, they correspond to 705fdf377dSMax Filippov * valid windows. 715fdf377dSMax Filippov */ 725fdf377dSMax Filippov for (index = WSBITS - 1; (index > 0) && depth; depth--, index--) 735fdf377dSMax Filippov if (windowstart & (1 << index)) { 745fdf377dSMax Filippov /* Get the PC from a0 and a1. */ 755fdf377dSMax Filippov pc = MAKE_PC_FROM_RA(a0, pc); 765fdf377dSMax Filippov /* Read a0 and a1 from the 775fdf377dSMax Filippov * corresponding position in AREGs. 785fdf377dSMax Filippov */ 795fdf377dSMax Filippov a0 = regs->areg[index * 4]; 805fdf377dSMax Filippov a1 = regs->areg[index * 4 + 1]; 815fdf377dSMax Filippov 825fdf377dSMax Filippov frame.pc = pc; 835fdf377dSMax Filippov frame.sp = a1; 845fdf377dSMax Filippov 855fdf377dSMax Filippov if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data)) 865fdf377dSMax Filippov return; 875fdf377dSMax Filippov } 885fdf377dSMax Filippov 895fdf377dSMax Filippov /* Step 2. */ 905fdf377dSMax Filippov /* We are done with the register window, we need to 915fdf377dSMax Filippov * look through the stack. 925fdf377dSMax Filippov */ 935fdf377dSMax Filippov if (!depth) 945fdf377dSMax Filippov return; 955fdf377dSMax Filippov 965fdf377dSMax Filippov /* Start from the a1 register. */ 975fdf377dSMax Filippov /* a1 = regs->areg[1]; */ 985fdf377dSMax Filippov while (a0 != 0 && depth--) { 995fdf377dSMax Filippov struct frame_start frame_start; 1005fdf377dSMax Filippov /* Get the location for a1, a0 for the 1015fdf377dSMax Filippov * previous frame from the current a1. 1025fdf377dSMax Filippov */ 1035fdf377dSMax Filippov unsigned long *psp = (unsigned long *)a1; 1045fdf377dSMax Filippov 1055fdf377dSMax Filippov psp -= 4; 1065fdf377dSMax Filippov 1075fdf377dSMax Filippov /* Check if the region is OK to access. */ 1085fdf377dSMax Filippov if (!access_ok(VERIFY_READ, psp, sizeof(frame_start))) 1095fdf377dSMax Filippov return; 1105fdf377dSMax Filippov /* Copy a1, a0 from user space stack frame. */ 1115fdf377dSMax Filippov if (__copy_from_user_inatomic(&frame_start, psp, 1125fdf377dSMax Filippov sizeof(frame_start))) 1135fdf377dSMax Filippov return; 1145fdf377dSMax Filippov 1155fdf377dSMax Filippov pc = MAKE_PC_FROM_RA(a0, pc); 1165fdf377dSMax Filippov a0 = frame_start.a0; 1175fdf377dSMax Filippov a1 = frame_start.a1; 1185fdf377dSMax Filippov 1195fdf377dSMax Filippov frame.pc = pc; 1205fdf377dSMax Filippov frame.sp = a1; 1215fdf377dSMax Filippov 1225fdf377dSMax Filippov if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data)) 1235fdf377dSMax Filippov return; 1245fdf377dSMax Filippov } 1255fdf377dSMax Filippov } 1265fdf377dSMax Filippov EXPORT_SYMBOL(xtensa_backtrace_user); 1275fdf377dSMax Filippov 1285fdf377dSMax Filippov void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth, 1295fdf377dSMax Filippov int (*kfn)(struct stackframe *frame, void *data), 1305fdf377dSMax Filippov int (*ufn)(struct stackframe *frame, void *data), 1315fdf377dSMax Filippov void *data) 1325fdf377dSMax Filippov { 1335fdf377dSMax Filippov unsigned long pc = regs->depc > VALID_DOUBLE_EXCEPTION_ADDRESS ? 1345fdf377dSMax Filippov regs->depc : regs->pc; 1355fdf377dSMax Filippov unsigned long sp_start, sp_end; 1365fdf377dSMax Filippov unsigned long a0 = regs->areg[0]; 1375fdf377dSMax Filippov unsigned long a1 = regs->areg[1]; 1385fdf377dSMax Filippov 1395fdf377dSMax Filippov sp_start = a1 & ~(THREAD_SIZE - 1); 1405fdf377dSMax Filippov sp_end = sp_start + THREAD_SIZE; 1415fdf377dSMax Filippov 1425fdf377dSMax Filippov /* Spill the register window to the stack first. */ 1435fdf377dSMax Filippov spill_registers(); 1445fdf377dSMax Filippov 1455fdf377dSMax Filippov /* Read the stack frames one by one and create the PC 1465fdf377dSMax Filippov * from the a0 and a1 registers saved there. 1475fdf377dSMax Filippov */ 1485fdf377dSMax Filippov while (a1 > sp_start && a1 < sp_end && depth--) { 1495fdf377dSMax Filippov struct stackframe frame; 1505fdf377dSMax Filippov unsigned long *psp = (unsigned long *)a1; 1515fdf377dSMax Filippov 1525fdf377dSMax Filippov frame.pc = pc; 1535fdf377dSMax Filippov frame.sp = a1; 1545fdf377dSMax Filippov 1555fdf377dSMax Filippov if (kernel_text_address(pc) && kfn(&frame, data)) 1565fdf377dSMax Filippov return; 1575fdf377dSMax Filippov 1585fdf377dSMax Filippov if (pc == (unsigned long)&common_exception_return) { 1595fdf377dSMax Filippov regs = (struct pt_regs *)a1; 1605fdf377dSMax Filippov if (user_mode(regs)) { 1615fdf377dSMax Filippov if (ufn == NULL) 1625fdf377dSMax Filippov return; 1635fdf377dSMax Filippov xtensa_backtrace_user(regs, depth, ufn, data); 1645fdf377dSMax Filippov return; 1655fdf377dSMax Filippov } 1665fdf377dSMax Filippov a0 = regs->areg[0]; 1675fdf377dSMax Filippov a1 = regs->areg[1]; 1685fdf377dSMax Filippov continue; 1695fdf377dSMax Filippov } 1705fdf377dSMax Filippov 1715fdf377dSMax Filippov sp_start = a1; 1725fdf377dSMax Filippov 1735fdf377dSMax Filippov pc = MAKE_PC_FROM_RA(a0, pc); 1745fdf377dSMax Filippov a0 = *(psp - 4); 1755fdf377dSMax Filippov a1 = *(psp - 3); 1765fdf377dSMax Filippov } 1775fdf377dSMax Filippov } 1785fdf377dSMax Filippov EXPORT_SYMBOL(xtensa_backtrace_kernel); 1795fdf377dSMax Filippov 1805fdf377dSMax Filippov #endif 1813e4196a5SMax Filippov 1823e4196a5SMax Filippov void walk_stackframe(unsigned long *sp, 1833e4196a5SMax Filippov int (*fn)(struct stackframe *frame, void *data), 1843e4196a5SMax Filippov void *data) 1853e4196a5SMax Filippov { 1863e4196a5SMax Filippov unsigned long a0, a1; 1873e4196a5SMax Filippov unsigned long sp_end; 1883e4196a5SMax Filippov 1893e4196a5SMax Filippov a1 = (unsigned long)sp; 1903e4196a5SMax Filippov sp_end = ALIGN(a1, THREAD_SIZE); 1913e4196a5SMax Filippov 1923e4196a5SMax Filippov spill_registers(); 1933e4196a5SMax Filippov 1943e4196a5SMax Filippov while (a1 < sp_end) { 1953e4196a5SMax Filippov struct stackframe frame; 1963e4196a5SMax Filippov 1973e4196a5SMax Filippov sp = (unsigned long *)a1; 1983e4196a5SMax Filippov 1993e4196a5SMax Filippov a0 = *(sp - 4); 2003e4196a5SMax Filippov a1 = *(sp - 3); 2013e4196a5SMax Filippov 2023e4196a5SMax Filippov if (a1 <= (unsigned long)sp) 2033e4196a5SMax Filippov break; 2043e4196a5SMax Filippov 2053e4196a5SMax Filippov frame.pc = MAKE_PC_FROM_RA(a0, a1); 2063e4196a5SMax Filippov frame.sp = a1; 2073e4196a5SMax Filippov 2083e4196a5SMax Filippov if (fn(&frame, data)) 2093e4196a5SMax Filippov return; 2103e4196a5SMax Filippov } 2113e4196a5SMax Filippov } 2123e4196a5SMax Filippov 2133e4196a5SMax Filippov #ifdef CONFIG_STACKTRACE 2143e4196a5SMax Filippov 2153e4196a5SMax Filippov struct stack_trace_data { 2163e4196a5SMax Filippov struct stack_trace *trace; 2173e4196a5SMax Filippov unsigned skip; 2183e4196a5SMax Filippov }; 2193e4196a5SMax Filippov 2203e4196a5SMax Filippov static int stack_trace_cb(struct stackframe *frame, void *data) 2213e4196a5SMax Filippov { 2223e4196a5SMax Filippov struct stack_trace_data *trace_data = data; 2233e4196a5SMax Filippov struct stack_trace *trace = trace_data->trace; 2243e4196a5SMax Filippov 2253e4196a5SMax Filippov if (trace_data->skip) { 2263e4196a5SMax Filippov --trace_data->skip; 2273e4196a5SMax Filippov return 0; 2283e4196a5SMax Filippov } 2293e4196a5SMax Filippov if (!kernel_text_address(frame->pc)) 2303e4196a5SMax Filippov return 0; 2313e4196a5SMax Filippov 2323e4196a5SMax Filippov trace->entries[trace->nr_entries++] = frame->pc; 2333e4196a5SMax Filippov return trace->nr_entries >= trace->max_entries; 2343e4196a5SMax Filippov } 2353e4196a5SMax Filippov 2363e4196a5SMax Filippov void save_stack_trace_tsk(struct task_struct *task, struct stack_trace *trace) 2373e4196a5SMax Filippov { 2383e4196a5SMax Filippov struct stack_trace_data trace_data = { 2393e4196a5SMax Filippov .trace = trace, 2403e4196a5SMax Filippov .skip = trace->skip, 2413e4196a5SMax Filippov }; 2423e4196a5SMax Filippov walk_stackframe(stack_pointer(task), stack_trace_cb, &trace_data); 2433e4196a5SMax Filippov } 2443e4196a5SMax Filippov EXPORT_SYMBOL_GPL(save_stack_trace_tsk); 2453e4196a5SMax Filippov 2463e4196a5SMax Filippov void save_stack_trace(struct stack_trace *trace) 2473e4196a5SMax Filippov { 2483e4196a5SMax Filippov save_stack_trace_tsk(current, trace); 2493e4196a5SMax Filippov } 2503e4196a5SMax Filippov EXPORT_SYMBOL_GPL(save_stack_trace); 2513e4196a5SMax Filippov 2523e4196a5SMax Filippov #endif 2533ae908c9SMax Filippov 2543ae908c9SMax Filippov #ifdef CONFIG_FRAME_POINTER 2553ae908c9SMax Filippov 2563ae908c9SMax Filippov struct return_addr_data { 2573ae908c9SMax Filippov unsigned long addr; 2583ae908c9SMax Filippov unsigned skip; 2593ae908c9SMax Filippov }; 2603ae908c9SMax Filippov 2613ae908c9SMax Filippov static int return_address_cb(struct stackframe *frame, void *data) 2623ae908c9SMax Filippov { 2633ae908c9SMax Filippov struct return_addr_data *r = data; 2643ae908c9SMax Filippov 2653ae908c9SMax Filippov if (r->skip) { 2663ae908c9SMax Filippov --r->skip; 2673ae908c9SMax Filippov return 0; 2683ae908c9SMax Filippov } 2693ae908c9SMax Filippov if (!kernel_text_address(frame->pc)) 2703ae908c9SMax Filippov return 0; 2713ae908c9SMax Filippov r->addr = frame->pc; 2723ae908c9SMax Filippov return 1; 2733ae908c9SMax Filippov } 2743ae908c9SMax Filippov 2753ae908c9SMax Filippov unsigned long return_address(unsigned level) 2763ae908c9SMax Filippov { 2773ae908c9SMax Filippov struct return_addr_data r = { 2783ae908c9SMax Filippov .skip = level + 1, 2793ae908c9SMax Filippov }; 2803ae908c9SMax Filippov walk_stackframe(stack_pointer(NULL), return_address_cb, &r); 2813ae908c9SMax Filippov return r.addr; 2823ae908c9SMax Filippov } 2833ae908c9SMax Filippov EXPORT_SYMBOL(return_address); 2843ae908c9SMax Filippov 2853ae908c9SMax Filippov #endif 286