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@
This commit is contained in:
Ian Lepore 2014-04-27 20:16:51 +00:00
parent 824e4131a0
commit fa046341af
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=265024
2 changed files with 23 additions and 1 deletions

View File

@ -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();

View File

@ -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);