|
Michal Suchanek |
49a18f |
From aec86b052df6541cc97c5fca44e5934cbea4963b Mon Sep 17 00:00:00 2001
|
|
Michal Suchanek |
49a18f |
From: Michael Ellerman <mpe@ellerman.id.au>
|
|
Michal Suchanek |
49a18f |
Date: Thu, 6 May 2021 14:49:59 +1000
|
|
Michal Suchanek |
49a18f |
Subject: [PATCH] powerpc/64s: Fix crashes when toggling entry flush barrier
|
|
Michal Suchanek |
49a18f |
|
|
Michal Suchanek |
70f4fd |
References: bsc#1177666 git-fixes bsc#1186460 ltc#192531
|
|
Michal Suchanek |
49a18f |
Patch-mainline: v5.13-rc2
|
|
Michal Suchanek |
49a18f |
Git-commit: aec86b052df6541cc97c5fca44e5934cbea4963b
|
|
Michal Suchanek |
49a18f |
|
|
Michal Suchanek |
49a18f |
The entry flush mitigation can be enabled/disabled at runtime via a
|
|
Michal Suchanek |
49a18f |
debugfs file (entry_flush), which causes the kernel to patch itself to
|
|
Michal Suchanek |
49a18f |
enable/disable the relevant mitigations.
|
|
Michal Suchanek |
49a18f |
|
|
Michal Suchanek |
49a18f |
However depending on which mitigation we're using, it may not be safe to
|
|
Michal Suchanek |
49a18f |
do that patching while other CPUs are active. For example the following
|
|
Michal Suchanek |
49a18f |
crash:
|
|
Michal Suchanek |
49a18f |
|
|
Michal Suchanek |
49a18f |
sleeper[15639]: segfault (11) at c000000000004c20 nip c000000000004c20 lr c000000000004c20
|
|
Michal Suchanek |
49a18f |
|
|
Michal Suchanek |
49a18f |
Shows that we returned to userspace with a corrupted LR that points into
|
|
Michal Suchanek |
49a18f |
the kernel, due to executing the partially patched call to the fallback
|
|
Michal Suchanek |
49a18f |
entry flush (ie. we missed the LR restore).
|
|
Michal Suchanek |
49a18f |
|
|
Michal Suchanek |
49a18f |
Fix it by doing the patching under stop machine. The CPUs that aren't
|
|
Michal Suchanek |
49a18f |
doing the patching will be spinning in the core of the stop machine
|
|
Michal Suchanek |
49a18f |
logic. That is currently sufficient for our purposes, because none of
|
|
Michal Suchanek |
49a18f |
the patching we do is to that code or anywhere in the vicinity.
|
|
Michal Suchanek |
49a18f |
|
|
Michal Suchanek |
49a18f |
Fixes: f79643787e0a ("powerpc/64s: flush L1D on kernel entry")
|
|
Michal Suchanek |
49a18f |
Cc: stable@vger.kernel.org # v5.10+
|
|
Michal Suchanek |
49a18f |
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
|
|
Michal Suchanek |
49a18f |
Link: https://lore.kernel.org/r/20210506044959.1298123-2-mpe@ellerman.id.au
|
|
Michal Suchanek |
49a18f |
Acked-by: Michal Suchanek <msuchanek@suse.de>
|
|
Michal Suchanek |
49a18f |
---
|
|
Michal Suchanek |
49a18f |
arch/powerpc/lib/feature-fixups.c | 16 +++++++++++++++-
|
|
Michal Suchanek |
49a18f |
1 file changed, 15 insertions(+), 1 deletion(-)
|
|
Michal Suchanek |
49a18f |
|
|
Michal Suchanek |
49a18f |
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
|
|
Michal Suchanek |
49a18f |
index 10083add8b33..0aefa6a4a259 100644
|
|
Michal Suchanek |
49a18f |
--- a/arch/powerpc/lib/feature-fixups.c
|
|
Michal Suchanek |
49a18f |
+++ b/arch/powerpc/lib/feature-fixups.c
|
|
Michal Suchanek |
49a18f |
@@ -299,8 +299,9 @@ void do_uaccess_flush_fixups(enum l1d_flush_type types)
|
|
Michal Suchanek |
49a18f |
: "unknown");
|
|
Michal Suchanek |
49a18f |
}
|
|
Michal Suchanek |
49a18f |
|
|
Michal Suchanek |
49a18f |
-void do_entry_flush_fixups(enum l1d_flush_type types)
|
|
Michal Suchanek |
49a18f |
+static int __do_entry_flush_fixups(void *data)
|
|
Michal Suchanek |
49a18f |
{
|
|
Michal Suchanek |
49a18f |
+ enum l1d_flush_type types = *(enum l1d_flush_type *)data;
|
|
Michal Suchanek |
49a18f |
unsigned int instrs[3], *dest;
|
|
Michal Suchanek |
49a18f |
long *start, *end;
|
|
Michal Suchanek |
49a18f |
int i;
|
|
Michal Suchanek |
49a18f |
@@ -369,6 +370,19 @@ void do_entry_flush_fixups(enum l1d_flush_type types)
|
|
Michal Suchanek |
49a18f |
: "ori type" :
|
|
Michal Suchanek |
49a18f |
(types & L1D_FLUSH_MTTRIG) ? "mttrig type"
|
|
Michal Suchanek |
49a18f |
: "unknown");
|
|
Michal Suchanek |
49a18f |
+
|
|
Michal Suchanek |
49a18f |
+ return 0;
|
|
Michal Suchanek |
49a18f |
+}
|
|
Michal Suchanek |
49a18f |
+
|
|
Michal Suchanek |
49a18f |
+void do_entry_flush_fixups(enum l1d_flush_type types)
|
|
Michal Suchanek |
49a18f |
+{
|
|
Michal Suchanek |
49a18f |
+ /*
|
|
Michal Suchanek |
49a18f |
+ * The call to the fallback flush can not be safely patched in/out while
|
|
Michal Suchanek |
49a18f |
+ * other CPUs are executing it. So call __do_entry_flush_fixups() on one
|
|
Michal Suchanek |
49a18f |
+ * CPU while all other CPUs spin in the stop machine core with interrupts
|
|
Michal Suchanek |
49a18f |
+ * hard disabled.
|
|
Michal Suchanek |
49a18f |
+ */
|
|
Michal Suchanek |
49a18f |
+ stop_machine(__do_entry_flush_fixups, &types, NULL);
|
|
Michal Suchanek |
49a18f |
}
|
|
Michal Suchanek |
49a18f |
|
|
Michal Suchanek |
49a18f |
void do_rfi_flush_fixups(enum l1d_flush_type types)
|
|
Michal Suchanek |
49a18f |
--
|
|
Michal Suchanek |
49a18f |
2.26.2
|
|
Michal Suchanek |
49a18f |
|