diff options
author | Sonic Zhang <sonic.zhang@analog.com> | 2010-09-06 10:16:04 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2010-10-22 03:48:59 -0400 |
commit | 99a5b2878b56d24919eb7e646f2d8e02f63a6efc (patch) | |
tree | 5db99463ad9f68e383aa54c9d102f91f5b890091 /arch/blackfin/kernel | |
parent | 73775b892ee70bdc0dbd6aeeebb50894d062f9a1 (diff) |
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>
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/ptrace.c | 4 | ||||
-rw-r--r-- | arch/blackfin/kernel/sys_bfin.c | 15 |
2 files changed, 17 insertions, 2 deletions
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index d890c1e35ec..b3583935413 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -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; diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c index bdc1e2f0da3..89448ed7065 100644 --- a/arch/blackfin/kernel/sys_bfin.c +++ b/arch/blackfin/kernel/sys_bfin.c @@ -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; +} |