Commit dd8b74f0 authored by Mark Brown's avatar Mark Brown Committed by Jie Liu
Browse files

arm64/nmi: Manage masking for superpriority interrupts along with DAIF

kunpeng inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I90N2C
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc.git/commit/?h=arm64-nmi&id=ce8c28fbdd6cac9405640e5fb50ccacfa3b49ce0



----------------------------------------------------------------------

As we do for pseudo NMIs add code to our DAIF management which keeps
superpriority interrupts unmasked when we have asynchronous exceptions
enabled. Since superpriority interrupts are not masked through DAIF like
pseduo NMIs are we also need to modify the assembler macros for managing
DAIF to ensure that the masking is done in the assembly code. At present
users of the assembly macros always mask pseudo NMIs.

There is a difference to the actual handling between pseudo NMIs
and superpriority interrupts in the assembly save_and_disable_irq and
restore_irq macros, these cover both interrupts and FIQs using DAIF
without regard for the use of pseudo NMIs so also mask those but are not
updated here to mask superpriority interrupts. Given the names it is not
clear that the behaviour with pseudo NMIs is particularly intentional,
and in any case these macros are only used in the implementation of
alternatives for software PAN while hardware PAN has been mandatory
since v8.1 so it is not anticipated that practical systems with support
for FEAT_NMI will ever execute the affected code.

This should be a conservative set of masked regions, we may be able to
relax this in future, but this should represent a good starting point.

Signed-off-by: default avatarMark Brown <broonie@kernel.org>
Signed-off-by: default avatarJie Liu <liujie375@h-partners.com>
parent 032d8169
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -51,11 +51,13 @@ alternative_else_nop_endif
	.endm

	.macro disable_daif
	disable_allint
	msr	daifset, #0xf
	.endm

	.macro enable_daif
	msr	daifclr, #0xf
	enable_allint
	.endm

/*
+20 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include <asm/arch_gicv3.h>
#include <asm/barrier.h>
#include <asm/cpufeature.h>
#include <asm/nmi.h>
#include <asm/ptrace.h>

#define DAIF_PROCCTX		0
@@ -35,6 +36,9 @@ static inline void local_daif_mask(void)
	if (system_uses_irq_prio_masking())
		gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);

	if (system_uses_nmi())
		_allint_set();

	trace_hardirqs_off();
}

@@ -116,6 +120,14 @@ static inline void local_daif_restore(unsigned long flags)

	write_sysreg(flags, daif);

	/* If we can take asynchronous errors we can take NMIs */
	if (system_uses_nmi()) {
		if (flags & PSR_A_BIT)
			_allint_set();
		else
			_allint_clear();
	}

	if (irq_disabled)
		trace_hardirqs_off();
}
@@ -140,6 +152,14 @@ static inline void local_daif_inherit(struct pt_regs *regs)
	 * use the pmr instead.
	 */
	write_sysreg(flags, daif);

	/* The ALLINT field is at the same position in pstate and ALLINT */
	if (system_uses_nmi()) {
		if (regs->pstate & ALLINT_ALLINT)
			_allint_set();
		else
			_allint_clear();
	}
}

#endif