1 // SPDX-License-Identifier: GPL-2.0-only 1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 2 /* 3 * Stacktrace support for Hexagon !! 3 * Stack trace management functions 4 * 4 * 5 * Copyright (c) 2010-2011, The Linux Foundati !! 5 * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> 6 */ 6 */ 7 << 8 #include <linux/sched.h> 7 #include <linux/sched.h> >> 8 #include <linux/sched/debug.h> 9 #include <linux/sched/task_stack.h> 9 #include <linux/sched/task_stack.h> 10 #include <linux/stacktrace.h> 10 #include <linux/stacktrace.h> 11 #include <linux/thread_info.h> !! 11 #include <linux/export.h> 12 #include <linux/module.h> !! 12 #include <asm/stacktrace.h> 13 << 14 struct stackframe { << 15 unsigned long fp; << 16 unsigned long rets; << 17 }; << 18 13 19 /* 14 /* 20 * Save stack-backtrace addresses into a stack !! 15 * Save stack-backtrace addresses into a stack_trace buffer: 21 */ 16 */ 22 void save_stack_trace(struct stack_trace *trac !! 17 static void save_raw_context_stack(struct stack_trace *trace, >> 18 unsigned long reg29, int savesched) 23 { 19 { 24 unsigned long low, high; !! 20 unsigned long *sp = (unsigned long *)reg29; 25 unsigned long fp; !! 21 unsigned long addr; 26 struct stackframe *frame; !! 22 27 int skip = trace->skip; !! 23 while (!kstack_end(sp)) { 28 !! 24 addr = *sp++; 29 low = (unsigned long)task_stack_page(c !! 25 if (__kernel_text_address(addr) && 30 high = low + THREAD_SIZE; !! 26 (savesched || !in_sched_functions(addr))) { 31 fp = (unsigned long)__builtin_frame_ad !! 27 if (trace->skip > 0) 32 !! 28 trace->skip--; 33 while (fp >= low && fp <= (high - size !! 29 else 34 frame = (struct stackframe *)f !! 30 trace->entries[trace->nr_entries++] = addr; 35 << 36 if (skip) { << 37 skip--; << 38 } else { << 39 trace->entries[trace-> << 40 if (trace->nr_entries 31 if (trace->nr_entries >= trace->max_entries) 41 break; 32 break; 42 } 33 } >> 34 } >> 35 } 43 36 44 /* !! 37 static void save_context_stack(struct stack_trace *trace, 45 * The next frame must be at a !! 38 struct task_struct *tsk, struct pt_regs *regs, int savesched) 46 * current frame. !! 39 { 47 */ !! 40 unsigned long sp = regs->regs[29]; 48 low = fp + sizeof(*frame); !! 41 #ifdef CONFIG_KALLSYMS 49 fp = frame->fp; !! 42 unsigned long ra = regs->regs[31]; >> 43 unsigned long pc = regs->cp0_epc; >> 44 >> 45 if (raw_show_trace || !__kernel_text_address(pc)) { >> 46 unsigned long stack_page = >> 47 (unsigned long)task_stack_page(tsk); >> 48 if (stack_page && sp >= stack_page && >> 49 sp <= stack_page + THREAD_SIZE - 32) >> 50 save_raw_context_stack(trace, sp, savesched); >> 51 return; 50 } 52 } >> 53 do { >> 54 if (savesched || !in_sched_functions(pc)) { >> 55 if (trace->skip > 0) >> 56 trace->skip--; >> 57 else >> 58 trace->entries[trace->nr_entries++] = pc; >> 59 if (trace->nr_entries >= trace->max_entries) >> 60 break; >> 61 } >> 62 pc = unwind_stack(tsk, &sp, pc, &ra); >> 63 } while (pc); >> 64 #else >> 65 save_raw_context_stack(trace, sp, savesched); >> 66 #endif >> 67 } >> 68 >> 69 /* >> 70 * Save stack-backtrace addresses into a stack_trace buffer. >> 71 */ >> 72 void save_stack_trace(struct stack_trace *trace) >> 73 { >> 74 save_stack_trace_tsk(current, trace); 51 } 75 } 52 EXPORT_SYMBOL_GPL(save_stack_trace); 76 EXPORT_SYMBOL_GPL(save_stack_trace); >> 77 >> 78 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) >> 79 { >> 80 struct pt_regs dummyregs; >> 81 struct pt_regs *regs = &dummyregs; >> 82 >> 83 WARN_ON(trace->nr_entries || !trace->max_entries); >> 84 >> 85 if (tsk != current) { >> 86 regs->regs[29] = tsk->thread.reg29; >> 87 regs->regs[31] = 0; >> 88 regs->cp0_epc = tsk->thread.reg31; >> 89 } else >> 90 prepare_frametrace(regs); >> 91 save_context_stack(trace, tsk, regs, tsk == current); >> 92 } >> 93 EXPORT_SYMBOL_GPL(save_stack_trace_tsk); 53 94
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.