irqflags.h 5.28 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
 * include/linux/irqflags.h
 *
 * IRQ flags tracing: follow the state of the hardirq and softirq flags and
 * provide callbacks for transitions between ON and OFF states.
 *
 * This file gets included from lowlevel asm headers too, to provide
 * wrapped versions of the local_irq_*() APIs, based on the
 * raw_local_irq_*() macros from the lowlevel headers.
 */
#ifndef _LINUX_TRACE_IRQFLAGS_H
#define _LINUX_TRACE_IRQFLAGS_H

15
#include <linux/typecheck.h>
David Howells's avatar
David Howells committed
16
#include <asm/irqflags.h>
17

18
19
20
#ifdef CONFIG_TRACE_IRQFLAGS
  extern void trace_softirqs_on(unsigned long ip);
  extern void trace_softirqs_off(unsigned long ip);
21
22
  extern void trace_hardirqs_on(void);
  extern void trace_hardirqs_off(void);
23
24
25
26
# define trace_hardirq_context(p)	((p)->hardirq_context)
# define trace_softirq_context(p)	((p)->softirq_context)
# define trace_hardirqs_enabled(p)	((p)->hardirqs_enabled)
# define trace_softirqs_enabled(p)	((p)->softirqs_enabled)
27
28
29
# define trace_hardirq_enter()			\
do {						\
	current->hardirq_context++;		\
30
	crossrelease_hist_start(XHLOCK_HARD);	\
31
32
33
34
35
36
37
38
39
} while (0)
# define trace_hardirq_exit()			\
do {						\
	current->hardirq_context--;		\
	crossrelease_hist_end(XHLOCK_HARD);	\
} while (0)
# define lockdep_softirq_enter()		\
do {						\
	current->softirq_context++;		\
40
	crossrelease_hist_start(XHLOCK_SOFT);	\
41
42
43
44
45
46
} while (0)
# define lockdep_softirq_exit()			\
do {						\
	current->softirq_context--;		\
	crossrelease_hist_end(XHLOCK_SOFT);	\
} while (0)
47
48
49
50
51
52
53
54
55
56
57
58
# define INIT_TRACE_IRQFLAGS	.softirqs_enabled = 1,
#else
# define trace_hardirqs_on()		do { } while (0)
# define trace_hardirqs_off()		do { } while (0)
# define trace_softirqs_on(ip)		do { } while (0)
# define trace_softirqs_off(ip)		do { } while (0)
# define trace_hardirq_context(p)	0
# define trace_softirq_context(p)	0
# define trace_hardirqs_enabled(p)	0
# define trace_softirqs_enabled(p)	0
# define trace_hardirq_enter()		do { } while (0)
# define trace_hardirq_exit()		do { } while (0)
59
60
# define lockdep_softirq_enter()	do { } while (0)
# define lockdep_softirq_exit()		do { } while (0)
61
62
63
# define INIT_TRACE_IRQFLAGS
#endif

64
65
#if defined(CONFIG_IRQSOFF_TRACER) || \
	defined(CONFIG_PREEMPT_TRACER)
66
67
68
69
70
71
72
 extern void stop_critical_timings(void);
 extern void start_critical_timings(void);
#else
# define stop_critical_timings() do { } while (0)
# define start_critical_timings() do { } while (0)
#endif

David Howells's avatar
David Howells committed
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
 * Wrap the arch provided IRQ routines to provide appropriate checks.
 */
#define raw_local_irq_disable()		arch_local_irq_disable()
#define raw_local_irq_enable()		arch_local_irq_enable()
#define raw_local_irq_save(flags)			\
	do {						\
		typecheck(unsigned long, flags);	\
		flags = arch_local_irq_save();		\
	} while (0)
#define raw_local_irq_restore(flags)			\
	do {						\
		typecheck(unsigned long, flags);	\
		arch_local_irq_restore(flags);		\
	} while (0)
#define raw_local_save_flags(flags)			\
	do {						\
		typecheck(unsigned long, flags);	\
		flags = arch_local_save_flags();	\
	} while (0)
#define raw_irqs_disabled_flags(flags)			\
	({						\
		typecheck(unsigned long, flags);	\
		arch_irqs_disabled_flags(flags);	\
	})
#define raw_irqs_disabled()		(arch_irqs_disabled())
#define raw_safe_halt()			arch_safe_halt()
100

David Howells's avatar
David Howells committed
101
102
103
104
/*
 * The local_irq_*() APIs are equal to the raw_local_irq*()
 * if !TRACE_IRQFLAGS.
 */
105
#ifdef CONFIG_TRACE_IRQFLAGS
106
107
108
109
#define local_irq_enable() \
	do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
#define local_irq_disable() \
	do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
110
111
112
113
114
#define local_irq_save(flags)				\
	do {						\
		raw_local_irq_save(flags);		\
		trace_hardirqs_off();			\
	} while (0)
115

116
117
118
119
120
121
122
123
124
125

#define local_irq_restore(flags)			\
	do {						\
		if (raw_irqs_disabled_flags(flags)) {	\
			raw_local_irq_restore(flags);	\
			trace_hardirqs_off();		\
		} else {				\
			trace_hardirqs_on();		\
			raw_local_irq_restore(flags);	\
		}					\
126
	} while (0)
David Howells's avatar
David Howells committed
127
128
129
130
131

#define safe_halt()				\
	do {					\
		trace_hardirqs_on();		\
		raw_safe_halt();		\
132
	} while (0)
133
134


135
#else /* !CONFIG_TRACE_IRQFLAGS */
David Howells's avatar
David Howells committed
136
137
138
139
140
141
142
143
144
145

#define local_irq_enable()	do { raw_local_irq_enable(); } while (0)
#define local_irq_disable()	do { raw_local_irq_disable(); } while (0)
#define local_irq_save(flags)					\
	do {							\
		raw_local_irq_save(flags);			\
	} while (0)
#define local_irq_restore(flags) do { raw_local_irq_restore(flags); } while (0)
#define safe_halt()		do { raw_safe_halt(); } while (0)

146
147
#endif /* CONFIG_TRACE_IRQFLAGS */

148
#ifdef CONFIG_IPIPE
149
#define local_irq_enable_full()		local_irq_enable()
150
151
152
153
154
155
156
157
158
159
#define local_irq_disable_full()		\
	do {					\
		local_irq_disable();		\
		hard_local_irq_disable();	\
	} while (0)
#else
#define local_irq_enable_full()		local_irq_enable()
#define local_irq_disable_full()	local_irq_disable()
#endif

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#define local_save_flags(flags)	raw_local_save_flags(flags)

/*
 * Some architectures don't define arch_irqs_disabled(), so even if either
 * definition would be fine we need to use different ones for the time being
 * to avoid build issues.
 */
#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
#define irqs_disabled()					\
	({						\
		unsigned long _flags;			\
		raw_local_save_flags(_flags);		\
		raw_irqs_disabled_flags(_flags);	\
	})
#else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */
#define irqs_disabled()	raw_irqs_disabled()
176
#endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */
177

178
179
#define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags)

180
#endif