1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef _LINUX_KCOV_H |
3 | #define _LINUX_KCOV_H |
4 | |
5 | #include <linux/sched.h> |
6 | #include <uapi/linux/kcov.h> |
7 | |
8 | struct task_struct; |
9 | |
10 | #ifdef CONFIG_KCOV |
11 | |
12 | enum kcov_mode { |
13 | /* Coverage collection is not enabled yet. */ |
14 | KCOV_MODE_DISABLED = 0, |
15 | /* KCOV was initialized, but tracing mode hasn't been chosen yet. */ |
16 | KCOV_MODE_INIT = 1, |
17 | /* |
18 | * Tracing coverage collection mode. |
19 | * Covered PCs are collected in a per-task buffer. |
20 | */ |
21 | KCOV_MODE_TRACE_PC = 2, |
22 | /* Collecting comparison operands mode. */ |
23 | KCOV_MODE_TRACE_CMP = 3, |
24 | }; |
25 | |
26 | #define KCOV_IN_CTXSW (1 << 30) |
27 | |
28 | void kcov_task_init(struct task_struct *t); |
29 | void kcov_task_exit(struct task_struct *t); |
30 | |
31 | #define kcov_prepare_switch(t) \ |
32 | do { \ |
33 | (t)->kcov_mode |= KCOV_IN_CTXSW; \ |
34 | } while (0) |
35 | |
36 | #define kcov_finish_switch(t) \ |
37 | do { \ |
38 | (t)->kcov_mode &= ~KCOV_IN_CTXSW; \ |
39 | } while (0) |
40 | |
41 | /* See Documentation/dev-tools/kcov.rst for usage details. */ |
42 | void kcov_remote_start(u64 handle); |
43 | void kcov_remote_stop(void); |
44 | u64 kcov_common_handle(void); |
45 | |
46 | static inline void kcov_remote_start_common(u64 id) |
47 | { |
48 | kcov_remote_start(handle: kcov_remote_handle(KCOV_SUBSYSTEM_COMMON, inst: id)); |
49 | } |
50 | |
51 | static inline void kcov_remote_start_usb(u64 id) |
52 | { |
53 | kcov_remote_start(handle: kcov_remote_handle(KCOV_SUBSYSTEM_USB, inst: id)); |
54 | } |
55 | |
56 | /* |
57 | * The softirq flavor of kcov_remote_*() functions is introduced as a temporary |
58 | * work around for kcov's lack of nested remote coverage sections support in |
59 | * task context. Adding support for nested sections is tracked in: |
60 | * https://bugzilla.kernel.org/show_bug.cgi?id=210337 |
61 | */ |
62 | |
63 | static inline void kcov_remote_start_usb_softirq(u64 id) |
64 | { |
65 | if (in_serving_softirq()) |
66 | kcov_remote_start_usb(id); |
67 | } |
68 | |
69 | static inline void kcov_remote_stop_softirq(void) |
70 | { |
71 | if (in_serving_softirq()) |
72 | kcov_remote_stop(); |
73 | } |
74 | |
75 | #ifdef CONFIG_64BIT |
76 | typedef unsigned long kcov_u64; |
77 | #else |
78 | typedef unsigned long long kcov_u64; |
79 | #endif |
80 | |
81 | void __sanitizer_cov_trace_pc(void); |
82 | void __sanitizer_cov_trace_cmp1(u8 arg1, u8 arg2); |
83 | void __sanitizer_cov_trace_cmp2(u16 arg1, u16 arg2); |
84 | void __sanitizer_cov_trace_cmp4(u32 arg1, u32 arg2); |
85 | void __sanitizer_cov_trace_cmp8(kcov_u64 arg1, kcov_u64 arg2); |
86 | void __sanitizer_cov_trace_const_cmp1(u8 arg1, u8 arg2); |
87 | void __sanitizer_cov_trace_const_cmp2(u16 arg1, u16 arg2); |
88 | void __sanitizer_cov_trace_const_cmp4(u32 arg1, u32 arg2); |
89 | void __sanitizer_cov_trace_const_cmp8(kcov_u64 arg1, kcov_u64 arg2); |
90 | void __sanitizer_cov_trace_switch(kcov_u64 val, void *cases); |
91 | |
92 | #else |
93 | |
94 | static inline void kcov_task_init(struct task_struct *t) {} |
95 | static inline void kcov_task_exit(struct task_struct *t) {} |
96 | static inline void kcov_prepare_switch(struct task_struct *t) {} |
97 | static inline void kcov_finish_switch(struct task_struct *t) {} |
98 | static inline void kcov_remote_start(u64 handle) {} |
99 | static inline void kcov_remote_stop(void) {} |
100 | static inline u64 kcov_common_handle(void) |
101 | { |
102 | return 0; |
103 | } |
104 | static inline void kcov_remote_start_common(u64 id) {} |
105 | static inline void kcov_remote_start_usb(u64 id) {} |
106 | static inline void kcov_remote_start_usb_softirq(u64 id) {} |
107 | static inline void kcov_remote_stop_softirq(void) {} |
108 | |
109 | #endif /* CONFIG_KCOV */ |
110 | #endif /* _LINUX_KCOV_H */ |
111 | |