Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / arch / arm64 / include / asm / irqflags.h
blobd4d7451c2c129f47216d51200d29297610122112
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3 * Copyright (C) 2012 ARM Ltd.
4 */
5 #ifndef __ASM_IRQFLAGS_H
6 #define __ASM_IRQFLAGS_H
8 #include <asm/barrier.h>
9 #include <asm/ptrace.h>
10 #include <asm/sysreg.h>
13 * Aarch64 has flags for masking: Debug, Asynchronous (serror), Interrupts and
14 * FIQ exceptions, in the 'daif' register. We mask and unmask them in 'daif'
15 * order:
16 * Masking debug exceptions causes all other exceptions to be masked too/
17 * Masking SError masks IRQ/FIQ, but not debug exceptions. IRQ and FIQ are
18 * always masked and unmasked together, and have no side effects for other
19 * flags. Keeping to this order makes it easier for entry.S to know which
20 * exceptions should be unmasked.
23 static __always_inline void __daif_local_irq_enable(void)
25 barrier();
26 asm volatile("msr daifclr, #3");
27 barrier();
30 static __always_inline void __pmr_local_irq_enable(void)
32 if (IS_ENABLED(CONFIG_ARM64_DEBUG_PRIORITY_MASKING)) {
33 u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
34 WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
37 barrier();
38 write_sysreg_s(GIC_PRIO_IRQON, SYS_ICC_PMR_EL1);
39 pmr_sync();
40 barrier();
43 static inline void arch_local_irq_enable(void)
45 if (system_uses_irq_prio_masking()) {
46 __pmr_local_irq_enable();
47 } else {
48 __daif_local_irq_enable();
52 static __always_inline void __daif_local_irq_disable(void)
54 barrier();
55 asm volatile("msr daifset, #3");
56 barrier();
59 static __always_inline void __pmr_local_irq_disable(void)
61 if (IS_ENABLED(CONFIG_ARM64_DEBUG_PRIORITY_MASKING)) {
62 u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
63 WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
66 barrier();
67 write_sysreg_s(GIC_PRIO_IRQOFF, SYS_ICC_PMR_EL1);
68 barrier();
71 static inline void arch_local_irq_disable(void)
73 if (system_uses_irq_prio_masking()) {
74 __pmr_local_irq_disable();
75 } else {
76 __daif_local_irq_disable();
80 static __always_inline unsigned long __daif_local_save_flags(void)
82 return read_sysreg(daif);
85 static __always_inline unsigned long __pmr_local_save_flags(void)
87 return read_sysreg_s(SYS_ICC_PMR_EL1);
91 * Save the current interrupt enable state.
93 static inline unsigned long arch_local_save_flags(void)
95 if (system_uses_irq_prio_masking()) {
96 return __pmr_local_save_flags();
97 } else {
98 return __daif_local_save_flags();
102 static __always_inline bool __daif_irqs_disabled_flags(unsigned long flags)
104 return flags & PSR_I_BIT;
107 static __always_inline bool __pmr_irqs_disabled_flags(unsigned long flags)
109 return flags != GIC_PRIO_IRQON;
112 static inline bool arch_irqs_disabled_flags(unsigned long flags)
114 if (system_uses_irq_prio_masking()) {
115 return __pmr_irqs_disabled_flags(flags);
116 } else {
117 return __daif_irqs_disabled_flags(flags);
121 static __always_inline bool __daif_irqs_disabled(void)
123 return __daif_irqs_disabled_flags(__daif_local_save_flags());
126 static __always_inline bool __pmr_irqs_disabled(void)
128 return __pmr_irqs_disabled_flags(__pmr_local_save_flags());
131 static inline bool arch_irqs_disabled(void)
133 if (system_uses_irq_prio_masking()) {
134 return __pmr_irqs_disabled();
135 } else {
136 return __daif_irqs_disabled();
140 static __always_inline unsigned long __daif_local_irq_save(void)
142 unsigned long flags = __daif_local_save_flags();
144 __daif_local_irq_disable();
146 return flags;
149 static __always_inline unsigned long __pmr_local_irq_save(void)
151 unsigned long flags = __pmr_local_save_flags();
154 * There are too many states with IRQs disabled, just keep the current
155 * state if interrupts are already disabled/masked.
157 if (!__pmr_irqs_disabled_flags(flags))
158 __pmr_local_irq_disable();
160 return flags;
163 static inline unsigned long arch_local_irq_save(void)
165 if (system_uses_irq_prio_masking()) {
166 return __pmr_local_irq_save();
167 } else {
168 return __daif_local_irq_save();
172 static __always_inline void __daif_local_irq_restore(unsigned long flags)
174 barrier();
175 write_sysreg(flags, daif);
176 barrier();
179 static __always_inline void __pmr_local_irq_restore(unsigned long flags)
181 barrier();
182 write_sysreg_s(flags, SYS_ICC_PMR_EL1);
183 pmr_sync();
184 barrier();
188 * restore saved IRQ state
190 static inline void arch_local_irq_restore(unsigned long flags)
192 if (system_uses_irq_prio_masking()) {
193 __pmr_local_irq_restore(flags);
194 } else {
195 __daif_local_irq_restore(flags);
199 #endif /* __ASM_IRQFLAGS_H */