stacktrace.c 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2005-2017 Andes Technology Corporation
  3. #include <linux/sched/debug.h>
  4. #include <linux/sched/task_stack.h>
  5. #include <linux/stacktrace.h>
  6. #include <linux/ftrace.h>
  7. void save_stack_trace(struct stack_trace *trace)
  8. {
  9. save_stack_trace_tsk(current, trace);
  10. }
  11. EXPORT_SYMBOL_GPL(save_stack_trace);
  12. void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
  13. {
  14. unsigned long *fpn;
  15. int skip = trace->skip;
  16. int savesched;
  17. int graph_idx = 0;
  18. if (tsk == current) {
  19. __asm__ __volatile__("\tori\t%0, $fp, #0\n":"=r"(fpn));
  20. savesched = 1;
  21. } else {
  22. fpn = (unsigned long *)thread_saved_fp(tsk);
  23. savesched = 0;
  24. }
  25. while (!kstack_end(fpn) && !((unsigned long)fpn & 0x3)
  26. && (fpn >= (unsigned long *)TASK_SIZE)) {
  27. unsigned long lpp, fpp;
  28. lpp = fpn[LP_OFFSET];
  29. fpp = fpn[FP_OFFSET];
  30. if (!__kernel_text_address(lpp))
  31. break;
  32. else
  33. lpp = ftrace_graph_ret_addr(tsk, &graph_idx, lpp, NULL);
  34. if (savesched || !in_sched_functions(lpp)) {
  35. if (skip) {
  36. skip--;
  37. } else {
  38. trace->entries[trace->nr_entries++] = lpp;
  39. if (trace->nr_entries >= trace->max_entries)
  40. break;
  41. }
  42. }
  43. fpn = (unsigned long *)fpp;
  44. }
  45. }
  46. EXPORT_SYMBOL_GPL(save_stack_trace_tsk);