ftrace.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright (C) 2008 Imagination Technologies Ltd.
  3. * Licensed under the GPL
  4. *
  5. * Dynamic ftrace support.
  6. */
  7. #include <linux/ftrace.h>
  8. #include <linux/io.h>
  9. #include <linux/uaccess.h>
  10. #include <asm/cacheflush.h>
  11. #define D04_MOVT_TEMPLATE 0x02200005
  12. #define D04_CALL_TEMPLATE 0xAC200005
  13. #define D1RTP_MOVT_TEMPLATE 0x03200005
  14. #define D1RTP_CALL_TEMPLATE 0xAC200006
  15. static const unsigned long NOP[2] = {0xa0fffffe, 0xa0fffffe};
  16. static unsigned long movt_and_call_insn[2];
  17. static unsigned char *ftrace_nop_replace(void)
  18. {
  19. return (char *)&NOP[0];
  20. }
  21. static unsigned char *ftrace_call_replace(unsigned long pc, unsigned long addr)
  22. {
  23. unsigned long hi16, low16;
  24. hi16 = (addr & 0xffff0000) >> 13;
  25. low16 = (addr & 0x0000ffff) << 3;
  26. /*
  27. * The compiler makes the call to mcount_wrapper()
  28. * (Meta's wrapper around mcount()) through the register
  29. * D0.4. So whenever we're patching one of those compiler-generated
  30. * calls we also need to go through D0.4. Otherwise use D1RtP.
  31. */
  32. if (pc == (unsigned long)&ftrace_call) {
  33. writel(D1RTP_MOVT_TEMPLATE | hi16, &movt_and_call_insn[0]);
  34. writel(D1RTP_CALL_TEMPLATE | low16, &movt_and_call_insn[1]);
  35. } else {
  36. writel(D04_MOVT_TEMPLATE | hi16, &movt_and_call_insn[0]);
  37. writel(D04_CALL_TEMPLATE | low16, &movt_and_call_insn[1]);
  38. }
  39. return (unsigned char *)&movt_and_call_insn[0];
  40. }
  41. static int ftrace_modify_code(unsigned long pc, unsigned char *old_code,
  42. unsigned char *new_code)
  43. {
  44. unsigned char replaced[MCOUNT_INSN_SIZE];
  45. /*
  46. * Note: Due to modules and __init, code can
  47. * disappear and change, we need to protect against faulting
  48. * as well as code changing.
  49. *
  50. * No real locking needed, this code is run through
  51. * kstop_machine.
  52. */
  53. /* read the text we want to modify */
  54. if (probe_kernel_read(replaced, (void *)pc, MCOUNT_INSN_SIZE))
  55. return -EFAULT;
  56. /* Make sure it is what we expect it to be */
  57. if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0)
  58. return -EINVAL;
  59. /* replace the text with the new text */
  60. if (probe_kernel_write((void *)pc, new_code, MCOUNT_INSN_SIZE))
  61. return -EPERM;
  62. flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
  63. return 0;
  64. }
  65. int ftrace_update_ftrace_func(ftrace_func_t func)
  66. {
  67. int ret;
  68. unsigned long pc;
  69. unsigned char old[MCOUNT_INSN_SIZE], *new;
  70. pc = (unsigned long)&ftrace_call;
  71. memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
  72. new = ftrace_call_replace(pc, (unsigned long)func);
  73. ret = ftrace_modify_code(pc, old, new);
  74. return ret;
  75. }
  76. int ftrace_make_nop(struct module *mod,
  77. struct dyn_ftrace *rec, unsigned long addr)
  78. {
  79. unsigned char *new, *old;
  80. unsigned long ip = rec->ip;
  81. old = ftrace_call_replace(ip, addr);
  82. new = ftrace_nop_replace();
  83. return ftrace_modify_code(ip, old, new);
  84. }
  85. int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
  86. {
  87. unsigned char *new, *old;
  88. unsigned long ip = rec->ip;
  89. old = ftrace_nop_replace();
  90. new = ftrace_call_replace(ip, addr);
  91. return ftrace_modify_code(ip, old, new);
  92. }
  93. /* run from kstop_machine */
  94. int __init ftrace_dyn_arch_init(void)
  95. {
  96. return 0;
  97. }