backtrace.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /**
  2. * arch/s390/oprofile/backtrace.c
  3. *
  4. * S390 Version
  5. * Copyright (C) 2005 IBM Corporation, IBM Deutschland Entwicklung GmbH.
  6. * Author(s): Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
  7. */
  8. #include <linux/oprofile.h>
  9. #include <asm/processor.h> /* for struct stack_frame */
  10. static unsigned long
  11. __show_trace(unsigned int *depth, unsigned long sp,
  12. unsigned long low, unsigned long high)
  13. {
  14. struct stack_frame *sf;
  15. struct pt_regs *regs;
  16. while (*depth) {
  17. sp = sp & PSW_ADDR_INSN;
  18. if (sp < low || sp > high - sizeof(*sf))
  19. return sp;
  20. sf = (struct stack_frame *) sp;
  21. (*depth)--;
  22. oprofile_add_trace(sf->gprs[8] & PSW_ADDR_INSN);
  23. /* Follow the backchain. */
  24. while (*depth) {
  25. low = sp;
  26. sp = sf->back_chain & PSW_ADDR_INSN;
  27. if (!sp)
  28. break;
  29. if (sp <= low || sp > high - sizeof(*sf))
  30. return sp;
  31. sf = (struct stack_frame *) sp;
  32. (*depth)--;
  33. oprofile_add_trace(sf->gprs[8] & PSW_ADDR_INSN);
  34. }
  35. if (*depth == 0)
  36. break;
  37. /* Zero backchain detected, check for interrupt frame. */
  38. sp = (unsigned long) (sf + 1);
  39. if (sp <= low || sp > high - sizeof(*regs))
  40. return sp;
  41. regs = (struct pt_regs *) sp;
  42. (*depth)--;
  43. oprofile_add_trace(sf->gprs[8] & PSW_ADDR_INSN);
  44. low = sp;
  45. sp = regs->gprs[15];
  46. }
  47. return sp;
  48. }
  49. void s390_backtrace(struct pt_regs * const regs, unsigned int depth)
  50. {
  51. unsigned long head;
  52. struct stack_frame* head_sf;
  53. if (user_mode (regs))
  54. return;
  55. head = regs->gprs[15];
  56. head_sf = (struct stack_frame*)head;
  57. if (!head_sf->back_chain)
  58. return;
  59. head = head_sf->back_chain;
  60. head = __show_trace(&depth, head, S390_lowcore.async_stack - ASYNC_SIZE,
  61. S390_lowcore.async_stack);
  62. __show_trace(&depth, head, S390_lowcore.thread_info,
  63. S390_lowcore.thread_info + THREAD_SIZE);
  64. }