opal-tracepoints.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/percpu.h>
  3. #include <linux/jump_label.h>
  4. #include <asm/trace.h>
  5. #ifdef CONFIG_JUMP_LABEL
  6. struct static_key opal_tracepoint_key = STATIC_KEY_INIT;
  7. int opal_tracepoint_regfunc(void)
  8. {
  9. static_key_slow_inc(&opal_tracepoint_key);
  10. return 0;
  11. }
  12. void opal_tracepoint_unregfunc(void)
  13. {
  14. static_key_slow_dec(&opal_tracepoint_key);
  15. }
  16. #else
  17. /*
  18. * We optimise OPAL calls by placing opal_tracepoint_refcount
  19. * directly in the TOC so we can check if the opal tracepoints are
  20. * enabled via a single load.
  21. */
  22. /* NB: reg/unreg are called while guarded with the tracepoints_mutex */
  23. extern long opal_tracepoint_refcount;
  24. int opal_tracepoint_regfunc(void)
  25. {
  26. opal_tracepoint_refcount++;
  27. return 0;
  28. }
  29. void opal_tracepoint_unregfunc(void)
  30. {
  31. opal_tracepoint_refcount--;
  32. }
  33. #endif
  34. /*
  35. * Since the tracing code might execute OPAL calls we need to guard against
  36. * recursion.
  37. */
  38. static DEFINE_PER_CPU(unsigned int, opal_trace_depth);
  39. void __trace_opal_entry(unsigned long opcode, unsigned long *args)
  40. {
  41. unsigned long flags;
  42. unsigned int *depth;
  43. local_irq_save(flags);
  44. depth = this_cpu_ptr(&opal_trace_depth);
  45. if (*depth)
  46. goto out;
  47. (*depth)++;
  48. preempt_disable();
  49. trace_opal_entry(opcode, args);
  50. (*depth)--;
  51. out:
  52. local_irq_restore(flags);
  53. }
  54. void __trace_opal_exit(long opcode, unsigned long retval)
  55. {
  56. unsigned long flags;
  57. unsigned int *depth;
  58. local_irq_save(flags);
  59. depth = this_cpu_ptr(&opal_trace_depth);
  60. if (*depth)
  61. goto out;
  62. (*depth)++;
  63. trace_opal_exit(opcode, retval);
  64. preempt_enable();
  65. (*depth)--;
  66. out:
  67. local_irq_restore(flags);
  68. }