Messages in this thread Patch in this message | | | Date | Mon, 28 Jan 2019 10:37:18 +0000 | From | Marc Zyngier <> | Subject | Re: [PATCH v9 13/26] arm64: daifflags: Include PMR in daifflags restore operations |
| |
On Mon, 21 Jan 2019 15:33:32 +0000, Julien Thierry <julien.thierry@arm.com> wrote: > > 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: Julien Thierry <julien.thierry@arm.com> > Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> > Cc: Catalin Marinas <catalin.marinas@arm.com> > Cc: Will Deacon <will.deacon@arm.com> > Cc: James Morse <james.morse@arm.com> > --- > arch/arm64/include/asm/daifflags.h | 31 +++++++++++++++++++++++++++---- > 1 file changed, 27 insertions(+), 4 deletions(-) > > diff --git a/arch/arm64/include/asm/daifflags.h b/arch/arm64/include/asm/daifflags.h > index 546bc39..1fd390e 100644 > --- a/arch/arm64/include/asm/daifflags.h > +++ b/arch/arm64/include/asm/daifflags.h > @@ -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,27 @@ 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; > + arch_local_irq_disable(); > + } > + } > + > + write_sysreg(flags, daif);
After much head scratching, I finally came to the conclusion that the above is safe, as a write to PSTATE is guaranteed not to be visible to instructions before it in program order (and the write to PMR is itself self-synchronising). I guess that a reference to the ARM ARM is in order here (no pun intended...).
> > - if (arch_irqs_disabled_flags(flags)) > + if (irq_disabled) > trace_hardirqs_off(); > } > > -- > 1.9.1 >
With the above,
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
M.
-- Jazz is not dead, it just smell funny.
| |