dect
/
linux-2.6
Archived
13
0
Fork 0

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:
Sonic Zhang 2010-09-06 10:16:04 +00:00 committed by Mike Frysinger
parent 73775b892e
commit 99a5b2878b
7 changed files with 44 additions and 3 deletions

View File

@ -1,4 +1,5 @@
include include/asm-generic/Kbuild.asm
header-y += bfin_sport.h
header-y += cachectl.h
header-y += fixed_code.h

View File

@ -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 */

View File

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

View File

@ -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 */

View File

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

View File

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

View File

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