Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8cb7eff3 authored by Julien Thierry's avatar Julien Thierry Committed by Catalin Marinas
Browse files

arm64: daifflags: Include PMR in daifflags restore operations



The addition of PMR should not bypass the semantics of daifflags.

When DA_F are set, I bit is also set as no interrupts (even of higher
priority) is allowed.

When DA_F are cleared, I bit is cleared and interrupt enabling/disabling
goes through ICC_PMR_EL1.

Signed-off-by: default avatarJulien Thierry <julien.thierry@arm.com>
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Reviewed-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: James Morse <james.morse@arm.com>
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent 4a503217
Loading
Loading
Loading
Loading
+46 −4
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@

#include <linux/irqflags.h>

#include <asm/cpufeature.h>

#define DAIF_PROCCTX		0
#define DAIF_PROCCTX_NOIRQ	PSR_I_BIT

@@ -36,7 +38,13 @@ static inline unsigned long local_daif_save(void)
{
	unsigned long flags;

	flags = arch_local_save_flags();
	flags = read_sysreg(daif);

	if (system_uses_irq_prio_masking()) {
		/* If IRQs are masked with PMR, reflect it in the flags */
		if (read_sysreg_s(SYS_ICC_PMR_EL1) <= GIC_PRIO_IRQOFF)
			flags |= PSR_I_BIT;
	}

	local_daif_mask();

@@ -45,12 +53,46 @@ static inline unsigned long local_daif_save(void)

static inline void local_daif_restore(unsigned long flags)
{
	if (!arch_irqs_disabled_flags(flags))
	bool irq_disabled = flags & PSR_I_BIT;

	if (!irq_disabled) {
		trace_hardirqs_on();

	arch_local_irq_restore(flags);
		if (system_uses_irq_prio_masking())
			arch_local_irq_enable();
	} else if (!(flags & PSR_A_BIT)) {
		/*
		 * If interrupts are disabled but we can take
		 * asynchronous errors, we can take NMIs
		 */
		if (system_uses_irq_prio_masking()) {
			flags &= ~PSR_I_BIT;
			/*
			 * There has been concern that the write to daif
			 * might be reordered before this write to PMR.
			 * From the ARM ARM DDI 0487D.a, section D1.7.1
			 * "Accessing PSTATE fields":
			 *   Writes to the PSTATE fields have side-effects on
			 *   various aspects of the PE operation. All of these
			 *   side-effects are guaranteed:
			 *     - Not to be visible to earlier instructions in
			 *       the execution stream.
			 *     - To be visible to later instructions in the
			 *       execution stream
			 *
			 * Also, writes to PMR are self-synchronizing, so no
			 * interrupts with a lower priority than PMR is signaled
			 * to the PE after the write.
			 *
			 * So we don't need additional synchronization here.
			 */
			arch_local_irq_disable();
		}
	}

	write_sysreg(flags, daif);

	if (arch_irqs_disabled_flags(flags))
	if (irq_disabled)
		trace_hardirqs_off();
}