Blackfin: add new cacheflush syscall
Flushing caches sometimes requires anomaly workarounds which require supervisor-only insns. Normally we don't need to flush caches from userspace so this isn't a problem, but when gcc generates trampolines on the stack, we do. So add a new syscall for gcc to use modeled after the mips version. Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
This commit is contained in:
parent
73775b892e
commit
99a5b2878b
|
@ -1,4 +1,5 @@
|
|||
include include/asm-generic/Kbuild.asm
|
||||
|
||||
header-y += bfin_sport.h
|
||||
header-y += cachectl.h
|
||||
header-y += fixed_code.h
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* based on the mips/cachectl.h
|
||||
*
|
||||
* Copyright 2010 Analog Devices Inc.
|
||||
* Copyright (C) 1994, 1995, 1996 by Ralf Baechle
|
||||
*
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#ifndef _ASM_CACHECTL
|
||||
#define _ASM_CACHECTL
|
||||
|
||||
/*
|
||||
* Options for cacheflush system call
|
||||
*/
|
||||
#define ICACHE (1<<0) /* flush instruction cache */
|
||||
#define DCACHE (1<<1) /* writeback and flush data cache */
|
||||
#define BCACHE (ICACHE|DCACHE) /* flush both caches */
|
||||
|
||||
#endif /* _ASM_CACHECTL */
|
|
@ -113,6 +113,9 @@ extern void user_disable_single_step(struct task_struct *child);
|
|||
/* common code demands this function */
|
||||
#define ptrace_disable(child) user_disable_single_step(child)
|
||||
|
||||
extern int is_user_addr_valid(struct task_struct *child,
|
||||
unsigned long start, unsigned long len);
|
||||
|
||||
/*
|
||||
* Get the address of the live pt_regs for the specified task.
|
||||
* These are saved onto the top kernel stack when the process
|
||||
|
|
|
@ -392,8 +392,9 @@
|
|||
#define __NR_fanotify_init 371
|
||||
#define __NR_fanotify_mark 372
|
||||
#define __NR_prlimit64 373
|
||||
#define __NR_cacheflush 374
|
||||
|
||||
#define __NR_syscall 374
|
||||
#define __NR_syscall 375
|
||||
#define NR_syscalls __NR_syscall
|
||||
|
||||
/* Old optional stuff no one actually uses */
|
||||
|
|
|
@ -114,8 +114,8 @@ put_reg(struct task_struct *task, long regno, unsigned long data)
|
|||
/*
|
||||
* check that an address falls within the bounds of the target process's memory mappings
|
||||
*/
|
||||
static inline int is_user_addr_valid(struct task_struct *child,
|
||||
unsigned long start, unsigned long len)
|
||||
int
|
||||
is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
struct sram_list_struct *sraml;
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/dma.h>
|
||||
#include <asm/cachectl.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags)
|
||||
{
|
||||
|
@ -70,3 +72,16 @@ asmlinkage int sys_bfin_spinlock(int *p)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, len, int, op)
|
||||
{
|
||||
if (is_user_addr_valid(current, addr, len) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (op & DCACHE)
|
||||
blackfin_dcache_flush_range(addr, addr + len);
|
||||
if (op & ICACHE)
|
||||
blackfin_icache_flush_range(addr, addr + len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1737,6 +1737,7 @@ ENTRY(_sys_call_table)
|
|||
.long _sys_fanotify_init
|
||||
.long _sys_fanotify_mark
|
||||
.long _sys_prlimit64
|
||||
.long _sys_cacheflush
|
||||
|
||||
.rept NR_syscalls-(.-_sys_call_table)/4
|
||||
.long _sys_ni_syscall
|
||||
|
|
Loading…
Reference in New Issue