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