^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) 2017 ARM Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #ifndef __ASM_DAIFFLAGS_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #define __ASM_DAIFFLAGS_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/irqflags.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/arch_gicv3.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/barrier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/cpufeature.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define DAIF_PROCCTX 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define DAIF_PROCCTX_NOIRQ PSR_I_BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define DAIF_ERRCTX (PSR_I_BIT | PSR_A_BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define DAIF_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* mask/save/unmask/restore all exceptions, including interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static inline void local_daif_mask(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) WARN_ON(system_has_prio_mask_debugging() &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) (read_sysreg_s(SYS_ICC_PMR_EL1) == (GIC_PRIO_IRQOFF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) GIC_PRIO_PSR_I_SET)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) "msr daifset, #0xf // local_daif_mask\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Don't really care for a dsb here, we don't intend to enable IRQs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if (system_uses_irq_prio_masking())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) trace_hardirqs_off();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static inline unsigned long local_daif_save_flags(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) flags = read_sysreg(daif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (system_uses_irq_prio_masking()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* If IRQs are masked with PMR, reflect it in the flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (read_sysreg_s(SYS_ICC_PMR_EL1) != GIC_PRIO_IRQON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) flags |= PSR_I_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return flags;
^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) static inline unsigned long local_daif_save(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) flags = local_daif_save_flags();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) local_daif_mask();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static inline void local_daif_restore(unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) bool irq_disabled = flags & PSR_I_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) WARN_ON(system_has_prio_mask_debugging() &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) !(read_sysreg(daif) & PSR_I_BIT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (!irq_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) trace_hardirqs_on();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (system_uses_irq_prio_masking()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) gic_write_pmr(GIC_PRIO_IRQON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) pmr_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) } else if (system_uses_irq_prio_masking()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) u64 pmr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (!(flags & PSR_A_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * If interrupts are disabled but we can take
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * asynchronous errors, we can take NMIs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) flags &= ~PSR_I_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) pmr = GIC_PRIO_IRQOFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) pmr = GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * There has been concern that the write to daif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * might be reordered before this write to PMR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * From the ARM ARM DDI 0487D.a, section D1.7.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * "Accessing PSTATE fields":
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * Writes to the PSTATE fields have side-effects on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * various aspects of the PE operation. All of these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * side-effects are guaranteed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * - Not to be visible to earlier instructions in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * the execution stream.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * - To be visible to later instructions in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * execution stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * Also, writes to PMR are self-synchronizing, so no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * interrupts with a lower priority than PMR is signaled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * to the PE after the write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * So we don't need additional synchronization here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) gic_write_pmr(pmr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) write_sysreg(flags, daif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (irq_disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) trace_hardirqs_off();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * Called by synchronous exception handlers to restore the DAIF bits that were
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * modified by taking an exception.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static inline void local_daif_inherit(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) unsigned long flags = regs->pstate & DAIF_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (interrupts_enabled(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) trace_hardirqs_on();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (system_uses_irq_prio_masking())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) gic_write_pmr(regs->pmr_save);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * We can't use local_daif_restore(regs->pstate) here as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * system_has_prio_mask_debugging() won't restore the I bit if it can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * use the pmr instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) write_sysreg(flags, daif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #endif