Skip to content

Commit

Permalink
arm: Disable outer (L2) cache in kexec
Browse files Browse the repository at this point in the history
kexec does not disable the outer cache before disabling the inner
caches in cpu_proc_fin(). So L2 is enabled across the kexec jump. When
the new kernel enables chaches again, it randomly crashes.

Disabling L2 before calling cpu_proc_fin() cures the problem.

Disabling L2 requires the following new functions: flush_all(),
inv_all() and disable(). Add them to outer_cache_fns and call them
from the kexec code.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Linus Walleij <linus.walleij@stericsson.com>
  • Loading branch information
Thomas Gleixner authored and Santosh Shilimkar committed Oct 26, 2010
1 parent 9a6655e commit ae360a7
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 0 deletions.
24 changes: 24 additions & 0 deletions arch/arm/include/asm/outercache.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ struct outer_cache_fns {
void (*inv_range)(unsigned long, unsigned long);
void (*clean_range)(unsigned long, unsigned long);
void (*flush_range)(unsigned long, unsigned long);
void (*flush_all)(void);
void (*inv_all)(void);
void (*disable)(void);
#ifdef CONFIG_OUTER_CACHE_SYNC
void (*sync)(void);
#endif
Expand All @@ -50,6 +53,24 @@ static inline void outer_flush_range(unsigned long start, unsigned long end)
outer_cache.flush_range(start, end);
}

static inline void outer_flush_all(void)
{
if (outer_cache.flush_all)
outer_cache.flush_all();
}

static inline void outer_inv_all(void)
{
if (outer_cache.inv_all)
outer_cache.inv_all();
}

static inline void outer_disable(void)
{
if (outer_cache.disable)
outer_cache.disable();
}

#else

static inline void outer_inv_range(unsigned long start, unsigned long end)
Expand All @@ -58,6 +79,9 @@ static inline void outer_clean_range(unsigned long start, unsigned long end)
{ }
static inline void outer_flush_range(unsigned long start, unsigned long end)
{ }
static inline void outer_flush_all(void) { }
static inline void outer_inv_all(void) { }
static inline void outer_disable(void) { }

#endif

Expand Down
3 changes: 3 additions & 0 deletions arch/arm/kernel/machine_kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ void machine_kexec(struct kimage *image)
local_fiq_disable();
setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
flush_cache_all();
outer_flush_all();
outer_disable();
cpu_proc_fin();
outer_inv_all();
flush_cache_all();
cpu_reset(reboot_code_buffer_phys);
}

0 comments on commit ae360a7

Please sign in to comment.