[PATCH 15/17] arm64: entry: move ARM64_ERRATUM_845719 workaround to C

Mark Rutland mark.rutland at arm.com
Wed Jan 8 10:56:32 PST 2020


To make the entry code less of a rats nest of overlapping labels and
shared state, and to make the code easier to debug and maintain, let's
move the workaround for ARM64_ERRATUM_845719 to C.

The workaround requires us to perform a write to CONTEXTIDR_EL1 at
AArch64 EL1 before retuning to an AArch32 EL0 task. There are no
additional requirements on the state of the CPU, or on subsequent
instructions prior to the ERET, so this can safely be performed in C
code.

As with the assembly version, we preserve the value of CONTEXTIDR if
CONFIG_PID_IN_CONTEXTIDR is selected.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: James Morse <james.morse at arm.com>
Cc: Marc Zyngier <maz at kernel.org>
Cc: Will Deacon <will at kernel.org>
---
 arch/arm64/kernel/entry-common.c | 17 +++++++++++++++++
 arch/arm64/kernel/entry.S        | 14 --------------
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index fa568284e73f..28b241cfd8f0 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -121,6 +121,21 @@ static void notrace el0_prepare_entry(struct pt_regs *regs)
 }
 NOKPROBE_SYMBOL(el0_prepare_entry);
 
+static void notrace workaround_arm64_erratum_845719(void)
+{
+	unsigned long val = 0;
+
+	if (!IS_ENABLED(CONFIG_ARM64_ERRATUM_845719) ||
+	    !cpus_have_const_cap(ARM64_WORKAROUND_845719) ||
+	    !is_compat_task())
+		return;
+
+	if (IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR))
+		val = read_sysreg(contextidr_el1);
+	write_sysreg(val, contextidr_el1);
+}
+NOKPROBE_SYMBOL(workaround_arm64_erratum_845719);
+
 static void notrace el0_prepare_return(struct pt_regs *regs)
 {
 	unsigned long flags;
@@ -138,6 +153,8 @@ static void notrace el0_prepare_return(struct pt_regs *regs)
 
 	user_enter();
 
+	workaround_arm64_erratum_845719();
+
 	stackleak_erase();
 }
 NOKPROBE_SYMBOL(el0_prepare_return);
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index d84718d272e9..a7340e551589 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -288,20 +288,6 @@ alternative_else_nop_endif
 	.if	\el == 0
 	ldr	x23, [sp, #S_SP]		// load return stack pointer
 	msr	sp_el0, x23
-	tst	x22, #PSR_MODE32_BIT		// native task?
-	b.eq	3f
-
-#ifdef CONFIG_ARM64_ERRATUM_845719
-alternative_if ARM64_WORKAROUND_845719
-#ifdef CONFIG_PID_IN_CONTEXTIDR
-	mrs	x29, contextidr_el1
-	msr	contextidr_el1, x29
-#else
-	msr contextidr_el1, xzr
-#endif
-alternative_else_nop_endif
-#endif
-3:
 #ifdef CONFIG_ARM64_ERRATUM_1418040
 alternative_if_not ARM64_WORKAROUND_1418040
 	b	4f
-- 
2.11.0




More information about the linux-arm-kernel mailing list