Commit 8848f066 authored by Marc Zyngier's avatar Marc Zyngier Committed by Will Deacon
Browse files

arm64: Add cpuidle context save/restore helpers



As we need to start doing some additional work on all idle
paths, let's introduce a set of macros that will perform
the work related to the GICv3 pseudo-NMI idle entry exit.

Stubs are introduced to 32bit ARM for compatibility.
As these helpers are currently unused, there is no functional
change.

Tested-by: default avatarValentin Schneider <valentin.schneider@arm.com>
Reviewed-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20210615111227.2454465-2-maz@kernel.org


Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent c4681547
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -49,4 +49,9 @@ extern int arm_cpuidle_suspend(int index);

extern int arm_cpuidle_init(int cpu);

struct arm_cpuidle_irq_context { };

#define arm_cpuidle_save_irq_context(c)		(void)c
#define arm_cpuidle_restore_irq_context(c)	(void)c

#endif
+35 −0
Original line number Diff line number Diff line
@@ -18,4 +18,39 @@ static inline int arm_cpuidle_suspend(int index)
	return -EOPNOTSUPP;
}
#endif

#ifdef CONFIG_ARM64_PSEUDO_NMI
#include <asm/arch_gicv3.h>

struct arm_cpuidle_irq_context {
	unsigned long pmr;
	unsigned long daif_bits;
};

#define arm_cpuidle_save_irq_context(__c)				\
	do {								\
		struct arm_cpuidle_irq_context *c = __c;		\
		if (system_uses_irq_prio_masking()) {			\
			c->daif_bits = read_sysreg(daif);		\
			write_sysreg(c->daif_bits | PSR_I_BIT | PSR_F_BIT, \
				     daif);				\
			c->pmr = gic_read_pmr();			\
			gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); \
		}							\
	} while (0)

#define arm_cpuidle_restore_irq_context(__c)				\
	do {								\
		struct arm_cpuidle_irq_context *c = __c;		\
		if (system_uses_irq_prio_masking()) {			\
			gic_write_pmr(c->pmr);				\
			write_sysreg(c->daif_bits, daif);		\
		}							\
	} while (0)
#else
struct arm_cpuidle_irq_context { };

#define arm_cpuidle_save_irq_context(c)		(void)c
#define arm_cpuidle_restore_irq_context(c)	(void)c
#endif
#endif