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