aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lepore <ian@FreeBSD.org>2014-04-27 20:16:51 +0000
committerIan Lepore <ian@FreeBSD.org>2014-04-27 20:16:51 +0000
commitfa046341af27c9b3ab166fb2828e5dd44503cc99 (patch)
tree399eff5fb954f5989d4ea00019ab828dcd86f4bf
parent824e4131a01b6b1277343ef3c1807c120f97b23c (diff)
downloadsrc-fa046341af27c9b3ab166fb2828e5dd44503cc99.tar.gz
src-fa046341af27c9b3ab166fb2828e5dd44503cc99.zip
Flush and invalidate caches on each CPU as part of handling IPI_STOP.
Flushing the caches is required before doing a panic dump, but ARM doesn't provide a flavor of flush that gets broadcast to other cores. However, all cores except one are stopped before doing a dump, so this works around the lack of a global flush/invalidate by doing it locally on each CPU as part of stopping. Discussed with: cognet@
Notes
Notes: svn path=/head/; revision=265024
-rw-r--r--sys/arm/arm/minidump_machdep.c10
-rw-r--r--sys/arm/arm/mp_machdep.c14
2 files changed, 23 insertions, 1 deletions
diff --git a/sys/arm/arm/minidump_machdep.c b/sys/arm/arm/minidump_machdep.c
index 69c82f84c26d..85ea2827c25c 100644
--- a/sys/arm/arm/minidump_machdep.c
+++ b/sys/arm/arm/minidump_machdep.c
@@ -210,7 +210,15 @@ minidumpsys(struct dumperinfo *di)
int i, k, bit, error;
char *addr;
- /* Flush cache */
+ /*
+ * Flush caches. Note that in the SMP case this operates only on the
+ * current CPU's L1 cache. Before we reach this point, code in either
+ * the system shutdown or kernel debugger has called stop_cpus() to stop
+ * all cores other than this one. Part of the ARM handling of
+ * stop_cpus() is to call wbinv_all() on that core's local L1 cache. So
+ * by time we get to here, all that remains is to flush the L1 for the
+ * current CPU, then the L2.
+ */
cpu_idcache_wbinv_all();
cpu_l2cache_wbinv_all();
diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c
index 141f2db0401a..6b16ad3fb26b 100644
--- a/sys/arm/arm/mp_machdep.c
+++ b/sys/arm/arm/mp_machdep.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <machine/cpu.h>
+#include <machine/cpufunc.h>
#include <machine/smp.h>
#include <machine/pcb.h>
#include <machine/pte.h>
@@ -286,6 +287,19 @@ ipi_handler(void *arg)
savectx(&stoppcbs[cpu]);
+ /*
+ * CPUs are stopped when entering the debugger and at
+ * system shutdown, both events which can precede a
+ * panic dump. For the dump to be correct, all caches
+ * must be flushed and invalidated, but on ARM there's
+ * no way to broadcast a wbinv_all to other cores.
+ * Instead, we have each core do the local wbinv_all as
+ * part of stopping the core. The core requesting the
+ * stop will do the l2 cache flush after all other cores
+ * have done their l1 flushes and stopped.
+ */
+ cpu_idcache_wbinv_all();
+
/* Indicate we are stopped */
CPU_SET_ATOMIC(cpu, &stopped_cpus);