^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2012 ARM Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #ifndef __ASM_IRQFLAGS_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #define __ASM_IRQFLAGS_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/alternative.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/barrier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/sysreg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Aarch64 has flags for masking: Debug, Asynchronous (serror), Interrupts and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * FIQ exceptions, in the 'daif' register. We mask and unmask them in 'dai'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * order:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Masking debug exceptions causes all other exceptions to be masked too/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Masking SError masks irq, but not debug exceptions. Masking irqs has no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * side effects for other flags. Keeping to this order makes it easier for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * entry.S to know which exceptions should be unmasked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * FIQ is never expected, but we mask it when we disable debug exceptions, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * unmask it at all other times.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * CPU interrupt mask handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static inline void arch_local_irq_enable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (system_has_prio_mask_debugging()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) asm volatile(ALTERNATIVE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) "msr daifclr, #2 // arch_local_irq_enable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) __msr_s(SYS_ICC_PMR_EL1, "%0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) ARM64_HAS_IRQ_PRIO_MASKING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) : "r" ((unsigned long) GIC_PRIO_IRQON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) pmr_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static inline void arch_local_irq_disable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (system_has_prio_mask_debugging()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) asm volatile(ALTERNATIVE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) "msr daifset, #2 // arch_local_irq_disable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) __msr_s(SYS_ICC_PMR_EL1, "%0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) ARM64_HAS_IRQ_PRIO_MASKING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) : "r" ((unsigned long) GIC_PRIO_IRQOFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * Save the current interrupt enable state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static inline unsigned long arch_local_save_flags(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) asm volatile(ALTERNATIVE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) "mrs %0, daif",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) __mrs_s("%0", SYS_ICC_PMR_EL1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ARM64_HAS_IRQ_PRIO_MASKING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) : "=&r" (flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static inline int arch_irqs_disabled_flags(unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) asm volatile(ALTERNATIVE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) "and %w0, %w1, #" __stringify(PSR_I_BIT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) "eor %w0, %w1, #" __stringify(GIC_PRIO_IRQON),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ARM64_HAS_IRQ_PRIO_MASKING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) : "=&r" (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) : "r" ((int) flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static inline int arch_irqs_disabled(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return arch_irqs_disabled_flags(arch_local_save_flags());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static inline unsigned long arch_local_irq_save(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) flags = arch_local_save_flags();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * There are too many states with IRQs disabled, just keep the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * state if interrupts are already disabled/masked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (!arch_irqs_disabled_flags(flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) arch_local_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * restore saved IRQ state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static inline void arch_local_irq_restore(unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) asm volatile(ALTERNATIVE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) "msr daif, %0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) __msr_s(SYS_ICC_PMR_EL1, "%0"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ARM64_HAS_IRQ_PRIO_MASKING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) : "r" (flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) pmr_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #endif /* __ASM_IRQFLAGS_H */