Merge tag 'trace-v4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux...
[cascardo/linux.git] / arch / mips / include / asm / irqflags.h
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
7  * Copyright (C) 1996 by Paul M. Antoine
8  * Copyright (C) 1999 Silicon Graphics
9  * Copyright (C) 2000 MIPS Technologies, Inc.
10  */
11 #ifndef _ASM_IRQFLAGS_H
12 #define _ASM_IRQFLAGS_H
13
14 #ifndef __ASSEMBLY__
15
16 #include <linux/compiler.h>
17 #include <linux/stringify.h>
18 #include <asm/compiler.h>
19 #include <asm/hazards.h>
20
21 #if defined(CONFIG_CPU_MIPSR2) || defined (CONFIG_CPU_MIPSR6)
22
23 static inline void arch_local_irq_disable(void)
24 {
25         __asm__ __volatile__(
26         "       .set    push                                            \n"
27         "       .set    noat                                            \n"
28         "       di                                                      \n"
29         "       " __stringify(__irq_disable_hazard) "                   \n"
30         "       .set    pop                                             \n"
31         : /* no outputs */
32         : /* no inputs */
33         : "memory");
34 }
35
36 static inline unsigned long arch_local_irq_save(void)
37 {
38         unsigned long flags;
39
40         asm __volatile__(
41         "       .set    push                                            \n"
42         "       .set    reorder                                         \n"
43         "       .set    noat                                            \n"
44 #if defined(CONFIG_CPU_LOONGSON3)
45         "       mfc0    %[flags], $12                                   \n"
46         "       di                                                      \n"
47 #else
48         "       di      %[flags]                                        \n"
49 #endif
50         "       andi    %[flags], 1                                     \n"
51         "       " __stringify(__irq_disable_hazard) "                   \n"
52         "       .set    pop                                             \n"
53         : [flags] "=r" (flags)
54         : /* no inputs */
55         : "memory");
56
57         return flags;
58 }
59
60 static inline void arch_local_irq_restore(unsigned long flags)
61 {
62         unsigned long __tmp1;
63
64         __asm__ __volatile__(
65         "       .set    push                                            \n"
66         "       .set    noreorder                                       \n"
67         "       .set    noat                                            \n"
68 #if defined(CONFIG_IRQ_MIPS_CPU)
69         /*
70          * Slow, but doesn't suffer from a relatively unlikely race
71          * condition we're having since days 1.
72          */
73         "       beqz    %[flags], 1f                                    \n"
74         "       di                                                      \n"
75         "       ei                                                      \n"
76         "1:                                                             \n"
77 #else
78         /*
79          * Fast, dangerous.  Life is fun, life is good.
80          */
81         "       mfc0    $1, $12                                         \n"
82         "       ins     $1, %[flags], 0, 1                              \n"
83         "       mtc0    $1, $12                                         \n"
84 #endif
85         "       " __stringify(__irq_disable_hazard) "                   \n"
86         "       .set    pop                                             \n"
87         : [flags] "=r" (__tmp1)
88         : "0" (flags)
89         : "memory");
90 }
91
92 #else
93 /* Functions that require preempt_{dis,en}able() are in mips-atomic.c */
94 void arch_local_irq_disable(void);
95 unsigned long arch_local_irq_save(void);
96 void arch_local_irq_restore(unsigned long flags);
97 #endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
98
99 static inline void arch_local_irq_enable(void)
100 {
101         __asm__ __volatile__(
102         "       .set    push                                            \n"
103         "       .set    reorder                                         \n"
104         "       .set    noat                                            \n"
105 #if   defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
106         "       ei                                                      \n"
107 #else
108         "       mfc0    $1,$12                                          \n"
109         "       ori     $1,0x1f                                         \n"
110         "       xori    $1,0x1e                                         \n"
111         "       mtc0    $1,$12                                          \n"
112 #endif
113         "       " __stringify(__irq_enable_hazard) "                    \n"
114         "       .set    pop                                             \n"
115         : /* no outputs */
116         : /* no inputs */
117         : "memory");
118 }
119
120 static inline unsigned long arch_local_save_flags(void)
121 {
122         unsigned long flags;
123
124         asm __volatile__(
125         "       .set    push                                            \n"
126         "       .set    reorder                                         \n"
127         "       mfc0    %[flags], $12                                   \n"
128         "       .set    pop                                             \n"
129         : [flags] "=r" (flags));
130
131         return flags;
132 }
133
134
135 static inline int arch_irqs_disabled_flags(unsigned long flags)
136 {
137         return !(flags & 1);
138 }
139
140 #endif /* #ifndef __ASSEMBLY__ */
141
142 /*
143  * Do the CPU's IRQ-state tracing from assembly code.
144  */
145 #ifdef CONFIG_TRACE_IRQFLAGS
146 /* Reload some registers clobbered by trace_hardirqs_on */
147 #ifdef CONFIG_64BIT
148 # define TRACE_IRQS_RELOAD_REGS                                         \
149         LONG_L  $11, PT_R11(sp);                                        \
150         LONG_L  $10, PT_R10(sp);                                        \
151         LONG_L  $9, PT_R9(sp);                                          \
152         LONG_L  $8, PT_R8(sp);                                          \
153         LONG_L  $7, PT_R7(sp);                                          \
154         LONG_L  $6, PT_R6(sp);                                          \
155         LONG_L  $5, PT_R5(sp);                                          \
156         LONG_L  $4, PT_R4(sp);                                          \
157         LONG_L  $2, PT_R2(sp)
158 #else
159 # define TRACE_IRQS_RELOAD_REGS                                         \
160         LONG_L  $7, PT_R7(sp);                                          \
161         LONG_L  $6, PT_R6(sp);                                          \
162         LONG_L  $5, PT_R5(sp);                                          \
163         LONG_L  $4, PT_R4(sp);                                          \
164         LONG_L  $2, PT_R2(sp)
165 #endif
166 # define TRACE_IRQS_ON                                                  \
167         CLI;    /* make sure trace_hardirqs_on() is called in kernel level */ \
168         jal     trace_hardirqs_on
169 # define TRACE_IRQS_ON_RELOAD                                           \
170         TRACE_IRQS_ON;                                                  \
171         TRACE_IRQS_RELOAD_REGS
172 # define TRACE_IRQS_OFF                                                 \
173         jal     trace_hardirqs_off
174 #else
175 # define TRACE_IRQS_ON
176 # define TRACE_IRQS_ON_RELOAD
177 # define TRACE_IRQS_OFF
178 #endif
179
180 #endif /* _ASM_IRQFLAGS_H */