mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
sh: Optimized flush_icache_range() implementation.
Add implementation of flush_icache_range() suitable for signal handler and kprobes. Remove flush_cache_sigtramp() and change signal.c to use flush_icache_range(). Signed-off-by: Chris Smith <chris.smith@st.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
parent
3611ee7acc
commit
09b5a10c19
3 changed files with 34 additions and 36 deletions
|
@ -398,10 +398,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||||
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
|
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
|
||||||
current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
|
current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
|
||||||
|
|
||||||
flush_cache_sigtramp(regs->pr);
|
flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode));
|
||||||
|
|
||||||
if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
|
|
||||||
flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -486,10 +483,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||||
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
|
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
|
||||||
current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
|
current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
|
||||||
|
|
||||||
flush_cache_sigtramp(regs->pr);
|
flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode));
|
||||||
|
|
||||||
if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
|
|
||||||
flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
|
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
|
||||||
* Copyright (C) 2001 - 2007 Paul Mundt
|
* Copyright (C) 2001 - 2007 Paul Mundt
|
||||||
* Copyright (C) 2003 Richard Curnow
|
* Copyright (C) 2003 Richard Curnow
|
||||||
|
* Copyright (c) 2007 STMicroelectronics (R&D) Ltd.
|
||||||
*
|
*
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
* License. See the file "COPYING" in the main directory of this archive
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
|
@ -22,6 +23,7 @@
|
||||||
* entirety.
|
* entirety.
|
||||||
*/
|
*/
|
||||||
#define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */
|
#define MAX_DCACHE_PAGES 64 /* XXX: Tune for ways */
|
||||||
|
#define MAX_ICACHE_PAGES 32
|
||||||
|
|
||||||
static void __flush_dcache_segment_1way(unsigned long start,
|
static void __flush_dcache_segment_1way(unsigned long start,
|
||||||
unsigned long extent);
|
unsigned long extent);
|
||||||
|
@ -178,42 +180,45 @@ void __flush_invalidate_region(void *start, int size)
|
||||||
/*
|
/*
|
||||||
* Write back the range of D-cache, and purge the I-cache.
|
* Write back the range of D-cache, and purge the I-cache.
|
||||||
*
|
*
|
||||||
* Called from kernel/module.c:sys_init_module and routine for a.out format.
|
* Called from kernel/module.c:sys_init_module and routine for a.out format,
|
||||||
|
* signal handler code and kprobes code
|
||||||
*/
|
*/
|
||||||
void flush_icache_range(unsigned long start, unsigned long end)
|
void flush_icache_range(unsigned long start, unsigned long end)
|
||||||
{
|
{
|
||||||
flush_cache_all();
|
int icacheaddr;
|
||||||
}
|
unsigned long flags, v;
|
||||||
|
|
||||||
/*
|
|
||||||
* Write back the D-cache and purge the I-cache for signal trampoline.
|
|
||||||
* .. which happens to be the same behavior as flush_icache_range().
|
|
||||||
* So, we simply flush out a line.
|
|
||||||
*/
|
|
||||||
void __uses_jump_to_uncached flush_cache_sigtramp(unsigned long addr)
|
|
||||||
{
|
|
||||||
unsigned long v, index;
|
|
||||||
unsigned long flags;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
v = addr & ~(L1_CACHE_BYTES-1);
|
/* If there are too many pages then just blow the caches */
|
||||||
asm volatile("ocbwb %0"
|
if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
|
||||||
: /* no output */
|
flush_cache_all();
|
||||||
: "m" (__m(v)));
|
} else {
|
||||||
|
/* selectively flush d-cache then invalidate the i-cache */
|
||||||
index = CACHE_IC_ADDRESS_ARRAY |
|
/* this is inefficient, so only use for small ranges */
|
||||||
(v & boot_cpu_data.icache.entry_mask);
|
start &= ~(L1_CACHE_BYTES-1);
|
||||||
|
end += L1_CACHE_BYTES-1;
|
||||||
|
end &= ~(L1_CACHE_BYTES-1);
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
jump_to_uncached();
|
jump_to_uncached();
|
||||||
|
|
||||||
for (i = 0; i < boot_cpu_data.icache.ways;
|
for (v = start; v < end; v+=L1_CACHE_BYTES) {
|
||||||
i++, index += boot_cpu_data.icache.way_incr)
|
asm volatile("ocbwb %0"
|
||||||
ctrl_outl(0, index); /* Clear out Valid-bit */
|
: /* no output */
|
||||||
|
: "m" (__m(v)));
|
||||||
|
|
||||||
|
icacheaddr = CACHE_IC_ADDRESS_ARRAY | (
|
||||||
|
v & cpu_data->icache.entry_mask);
|
||||||
|
|
||||||
|
for (i = 0; i < cpu_data->icache.ways;
|
||||||
|
i++, icacheaddr += cpu_data->icache.way_incr)
|
||||||
|
/* Clear i-cache line valid-bit */
|
||||||
|
ctrl_outl(0, icacheaddr);
|
||||||
|
}
|
||||||
|
|
||||||
back_to_cached();
|
back_to_cached();
|
||||||
wmb();
|
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void flush_cache_4096(unsigned long start,
|
static inline void flush_cache_4096(unsigned long start,
|
||||||
|
|
|
@ -30,7 +30,6 @@ void flush_dcache_page(struct page *pg);
|
||||||
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
||||||
|
|
||||||
void flush_icache_range(unsigned long start, unsigned long end);
|
void flush_icache_range(unsigned long start, unsigned long end);
|
||||||
void flush_cache_sigtramp(unsigned long addr);
|
|
||||||
void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
|
void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
|
||||||
unsigned long addr, int len);
|
unsigned long addr, int len);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue