>> 1 // SPDX-License-Identifier: GPL-2.0-only 1 /* 2 /* 2 * Stack trace utility for OpenRISC !! 3 * Stack trace management functions 3 * 4 * 4 * Copyright (C) 2017 Stafford Horne <shorne@g !! 5 * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> 5 * << 6 * This file is licensed under the terms of th << 7 * version 2. This program is licensed "as is << 8 * kind, whether express or implied. << 9 * << 10 * Losely based on work from sh and powerpc. << 11 */ 6 */ 12 << 13 #include <linux/export.h> << 14 #include <linux/sched.h> 7 #include <linux/sched.h> 15 #include <linux/sched/debug.h> 8 #include <linux/sched/debug.h> 16 #include <linux/sched/task_stack.h> 9 #include <linux/sched/task_stack.h> 17 #include <linux/stacktrace.h> 10 #include <linux/stacktrace.h> 18 !! 11 #include <linux/export.h> 19 #include <asm/processor.h> !! 12 #include <asm/stacktrace.h> 20 #include <asm/unwinder.h> << 21 13 22 /* 14 /* 23 * Save stack-backtrace addresses into a stack !! 15 * Save stack-backtrace addresses into a stack_trace buffer: 24 */ 16 */ 25 static void !! 17 static void save_raw_context_stack(struct stack_trace *trace, 26 save_stack_address(void *data, unsigned long a !! 18 unsigned long reg29, int savesched) 27 { 19 { 28 struct stack_trace *trace = data; !! 20 unsigned long *sp = (unsigned long *)reg29; >> 21 unsigned long addr; 29 22 30 if (!reliable) !! 23 while (!kstack_end(sp)) { 31 return; !! 24 addr = *sp++; >> 25 if (__kernel_text_address(addr) && >> 26 (savesched || !in_sched_functions(addr))) { >> 27 if (trace->skip > 0) >> 28 trace->skip--; >> 29 else >> 30 trace->entries[trace->nr_entries++] = addr; >> 31 if (trace->nr_entries >= trace->max_entries) >> 32 break; >> 33 } >> 34 } >> 35 } 32 36 33 if (trace->skip > 0) { !! 37 static void save_context_stack(struct stack_trace *trace, 34 trace->skip--; !! 38 struct task_struct *tsk, struct pt_regs *regs, int savesched) >> 39 { >> 40 unsigned long sp = regs->regs[29]; >> 41 #ifdef CONFIG_KALLSYMS >> 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); 35 return; 51 return; 36 } 52 } 37 !! 53 do { 38 if (trace->nr_entries < trace->max_ent !! 54 if (savesched || !in_sched_functions(pc)) { 39 trace->entries[trace->nr_entri !! 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 40 } 67 } 41 68 >> 69 /* >> 70 * Save stack-backtrace addresses into a stack_trace buffer. >> 71 */ 42 void save_stack_trace(struct stack_trace *trac 72 void save_stack_trace(struct stack_trace *trace) 43 { 73 { 44 unwind_stack(trace, (unsigned long *) !! 74 save_stack_trace_tsk(current, trace); 45 } 75 } 46 EXPORT_SYMBOL_GPL(save_stack_trace); 76 EXPORT_SYMBOL_GPL(save_stack_trace); 47 77 48 static void << 49 save_stack_address_nosched(void *data, unsigne << 50 { << 51 struct stack_trace *trace = (struct st << 52 << 53 if (!reliable) << 54 return; << 55 << 56 if (in_sched_functions(addr)) << 57 return; << 58 << 59 if (trace->skip > 0) { << 60 trace->skip--; << 61 return; << 62 } << 63 << 64 if (trace->nr_entries < trace->max_ent << 65 trace->entries[trace->nr_entri << 66 } << 67 << 68 void save_stack_trace_tsk(struct task_struct * 78 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 69 { 79 { 70 unsigned long *sp = NULL; !! 80 struct pt_regs dummyregs; >> 81 struct pt_regs *regs = &dummyregs; 71 82 72 if (!try_get_task_stack(tsk)) !! 83 WARN_ON(trace->nr_entries || !trace->max_entries); 73 return; << 74 << 75 if (tsk == current) << 76 sp = (unsigned long *) &sp; << 77 else { << 78 unsigned long ksp; << 79 << 80 /* Locate stack from kernel co << 81 ksp = task_thread_info(tsk)->k << 82 ksp += STACK_FRAME_OVERHEAD; << 83 ksp += sizeof(struct pt_regs); << 84 << 85 sp = (unsigned long *) ksp; << 86 } << 87 84 88 unwind_stack(trace, sp, save_stack_add !! 85 if (tsk != current) { 89 !! 86 regs->regs[29] = tsk->thread.reg29; 90 put_task_stack(tsk); !! 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); 91 } 92 } 92 EXPORT_SYMBOL_GPL(save_stack_trace_tsk); 93 EXPORT_SYMBOL_GPL(save_stack_trace_tsk); 93 << 94 void << 95 save_stack_trace_regs(struct pt_regs *regs, st << 96 { << 97 unwind_stack(trace, (unsigned long *) << 98 save_stack_address_nosche << 99 } << 100 EXPORT_SYMBOL_GPL(save_stack_trace_regs); << 101 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.