opal-tracepoints.c 1.6 KB

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