1 /* SPDX-License-Identifier: GPL-2.0-only */ 1 2 /* 3 * Copyright (C) 2012 ARM Ltd. 4 */ 5 #ifndef __ASM_IRQFLAGS_H 6 #define __ASM_IRQFLAGS_H 7 8 #include <asm/barrier.h> 9 #include <asm/ptrace.h> 10 #include <asm/sysreg.h> 11 12 /* 13 * Aarch64 has flags for masking: Debug, Async 14 * FIQ exceptions, in the 'daif' register. We 15 * order: 16 * Masking debug exceptions causes all other e 17 * Masking SError masks IRQ/FIQ, but not debug 18 * always masked and unmasked together, and ha 19 * flags. Keeping to this order makes it easie 20 * exceptions should be unmasked. 21 */ 22 23 static __always_inline void __daif_local_irq_e 24 { 25 barrier(); 26 asm volatile("msr daifclr, #3"); 27 barrier(); 28 } 29 30 static __always_inline void __pmr_local_irq_en 31 { 32 if (IS_ENABLED(CONFIG_ARM64_DEBUG_PRIO 33 u32 pmr = read_sysreg_s(SYS_IC 34 WARN_ON_ONCE(pmr != GIC_PRIO_I 35 } 36 37 barrier(); 38 write_sysreg_s(GIC_PRIO_IRQON, SYS_ICC 39 pmr_sync(); 40 barrier(); 41 } 42 43 static inline void arch_local_irq_enable(void) 44 { 45 if (system_uses_irq_prio_masking()) { 46 __pmr_local_irq_enable(); 47 } else { 48 __daif_local_irq_enable(); 49 } 50 } 51 52 static __always_inline void __daif_local_irq_d 53 { 54 barrier(); 55 asm volatile("msr daifset, #3"); 56 barrier(); 57 } 58 59 static __always_inline void __pmr_local_irq_di 60 { 61 if (IS_ENABLED(CONFIG_ARM64_DEBUG_PRIO 62 u32 pmr = read_sysreg_s(SYS_IC 63 WARN_ON_ONCE(pmr != GIC_PRIO_I 64 } 65 66 barrier(); 67 write_sysreg_s(GIC_PRIO_IRQOFF, SYS_IC 68 barrier(); 69 } 70 71 static inline void arch_local_irq_disable(void 72 { 73 if (system_uses_irq_prio_masking()) { 74 __pmr_local_irq_disable(); 75 } else { 76 __daif_local_irq_disable(); 77 } 78 } 79 80 static __always_inline unsigned long __daif_lo 81 { 82 return read_sysreg(daif); 83 } 84 85 static __always_inline unsigned long __pmr_loc 86 { 87 return read_sysreg_s(SYS_ICC_PMR_EL1); 88 } 89 90 /* 91 * Save the current interrupt enable state. 92 */ 93 static inline unsigned long arch_local_save_fl 94 { 95 if (system_uses_irq_prio_masking()) { 96 return __pmr_local_save_flags( 97 } else { 98 return __daif_local_save_flags 99 } 100 } 101 102 static __always_inline bool __daif_irqs_disabl 103 { 104 return flags & PSR_I_BIT; 105 } 106 107 static __always_inline bool __pmr_irqs_disable 108 { 109 return flags != GIC_PRIO_IRQON; 110 } 111 112 static inline bool arch_irqs_disabled_flags(un 113 { 114 if (system_uses_irq_prio_masking()) { 115 return __pmr_irqs_disabled_fla 116 } else { 117 return __daif_irqs_disabled_fl 118 } 119 } 120 121 static __always_inline bool __daif_irqs_disabl 122 { 123 return __daif_irqs_disabled_flags(__da 124 } 125 126 static __always_inline bool __pmr_irqs_disable 127 { 128 return __pmr_irqs_disabled_flags(__pmr 129 } 130 131 static inline bool arch_irqs_disabled(void) 132 { 133 if (system_uses_irq_prio_masking()) { 134 return __pmr_irqs_disabled(); 135 } else { 136 return __daif_irqs_disabled(); 137 } 138 } 139 140 static __always_inline unsigned long __daif_lo 141 { 142 unsigned long flags = __daif_local_sav 143 144 __daif_local_irq_disable(); 145 146 return flags; 147 } 148 149 static __always_inline unsigned long __pmr_loc 150 { 151 unsigned long flags = __pmr_local_save 152 153 /* 154 * There are too many states with IRQs 155 * state if interrupts are already dis 156 */ 157 if (!__pmr_irqs_disabled_flags(flags)) 158 __pmr_local_irq_disable(); 159 160 return flags; 161 } 162 163 static inline unsigned long arch_local_irq_sav 164 { 165 if (system_uses_irq_prio_masking()) { 166 return __pmr_local_irq_save(); 167 } else { 168 return __daif_local_irq_save() 169 } 170 } 171 172 static __always_inline void __daif_local_irq_r 173 { 174 barrier(); 175 write_sysreg(flags, daif); 176 barrier(); 177 } 178 179 static __always_inline void __pmr_local_irq_re 180 { 181 barrier(); 182 write_sysreg_s(flags, SYS_ICC_PMR_EL1) 183 pmr_sync(); 184 barrier(); 185 } 186 187 /* 188 * restore saved IRQ state 189 */ 190 static inline void arch_local_irq_restore(unsi 191 { 192 if (system_uses_irq_prio_masking()) { 193 __pmr_local_irq_restore(flags) 194 } else { 195 __daif_local_irq_restore(flags 196 } 197 } 198 199 #endif /* __ASM_IRQFLAGS_H */ 200
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.