sh: Add sys_cacheflush() call for SH CPUs.
Adds a system call to allow user code to flush code from the cache. You can use instructions for the data side, but the iside can only be done by a flush ROM which really only works with a direct mapped cache. The later SH4's have 2 way Iside, so this call allows a portable way to flush the cache. Signed-off-by: Stuart Menefy <stuart.menefy@st.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
parent
a5cf9e2444
commit
6d243dd370
|
@ -1,6 +1,6 @@
|
||||||
include include/asm-generic/Kbuild.asm
|
include include/asm-generic/Kbuild.asm
|
||||||
|
|
||||||
header-y += cpu-features.h
|
header-y += cachectl.h cpu-features.h
|
||||||
|
|
||||||
unifdef-y += unistd_32.h
|
unifdef-y += unistd_32.h
|
||||||
unifdef-y += unistd_64.h
|
unifdef-y += unistd_64.h
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef _SH_CACHECTL_H
|
||||||
|
#define _SH_CACHECTL_H
|
||||||
|
|
||||||
|
/* Definitions for the cacheflush system call. */
|
||||||
|
|
||||||
|
#define CACHEFLUSH_D_INVAL 0x1 /* invalidate (without write back) */
|
||||||
|
#define CACHEFLUSH_D_WB 0x2 /* write back (without invalidate) */
|
||||||
|
#define CACHEFLUSH_D_PURGE 0x3 /* writeback and invalidate */
|
||||||
|
|
||||||
|
#define CACHEFLUSH_I 0x4
|
||||||
|
|
||||||
|
#endif /* _SH_CACHECTL_H */
|
|
@ -132,7 +132,7 @@
|
||||||
#define __NR_clone 120
|
#define __NR_clone 120
|
||||||
#define __NR_setdomainname 121
|
#define __NR_setdomainname 121
|
||||||
#define __NR_uname 122
|
#define __NR_uname 122
|
||||||
#define __NR_modify_ldt 123
|
#define __NR_cacheflush 123
|
||||||
#define __NR_adjtimex 124
|
#define __NR_adjtimex 124
|
||||||
#define __NR_mprotect 125
|
#define __NR_mprotect 125
|
||||||
#define __NR_sigprocmask 126
|
#define __NR_sigprocmask 126
|
||||||
|
|
|
@ -137,7 +137,7 @@
|
||||||
#define __NR_clone 120
|
#define __NR_clone 120
|
||||||
#define __NR_setdomainname 121
|
#define __NR_setdomainname 121
|
||||||
#define __NR_uname 122
|
#define __NR_uname 122
|
||||||
#define __NR_modify_ldt 123
|
#define __NR_cacheflush 123
|
||||||
#define __NR_adjtimex 124
|
#define __NR_adjtimex 124
|
||||||
#define __NR_mprotect 125
|
#define __NR_mprotect 125
|
||||||
#define __NR_sigprocmask 126
|
#define __NR_sigprocmask 126
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include <asm/syscalls.h>
|
#include <asm/syscalls.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/cachectl.h>
|
||||||
|
|
||||||
static inline long
|
static inline long
|
||||||
do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
|
do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
|
||||||
|
@ -179,6 +181,47 @@ asmlinkage int sys_ipc(uint call, int first, int second,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sys_cacheflush -- flush (part of) the processor cache. */
|
||||||
|
asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op)
|
||||||
|
{
|
||||||
|
struct vm_area_struct *vma;
|
||||||
|
|
||||||
|
if ((op < 0) || (op > (CACHEFLUSH_D_PURGE|CACHEFLUSH_I)))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify that the specified address region actually belongs
|
||||||
|
* to this process.
|
||||||
|
*/
|
||||||
|
if (addr + len < addr)
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
down_read(¤t->mm->mmap_sem);
|
||||||
|
vma = find_vma (current->mm, addr);
|
||||||
|
if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) {
|
||||||
|
up_read(¤t->mm->mmap_sem);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (op & CACHEFLUSH_D_PURGE) {
|
||||||
|
case CACHEFLUSH_D_INVAL:
|
||||||
|
__flush_invalidate_region((void *)addr, len);
|
||||||
|
break;
|
||||||
|
case CACHEFLUSH_D_WB:
|
||||||
|
__flush_wback_region((void *)addr, len);
|
||||||
|
break;
|
||||||
|
case CACHEFLUSH_D_PURGE:
|
||||||
|
__flush_purge_region((void *)addr, len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op & CACHEFLUSH_I)
|
||||||
|
flush_cache_all();
|
||||||
|
|
||||||
|
up_read(¤t->mm->mmap_sem);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
asmlinkage int sys_uname(struct old_utsname __user *name)
|
asmlinkage int sys_uname(struct old_utsname __user *name)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
|
@ -139,7 +139,7 @@ ENTRY(sys_call_table)
|
||||||
.long sys_clone /* 120 */
|
.long sys_clone /* 120 */
|
||||||
.long sys_setdomainname
|
.long sys_setdomainname
|
||||||
.long sys_newuname
|
.long sys_newuname
|
||||||
.long sys_ni_syscall /* sys_modify_ldt */
|
.long sys_cacheflush /* x86: sys_modify_ldt */
|
||||||
.long sys_adjtimex
|
.long sys_adjtimex
|
||||||
.long sys_mprotect /* 125 */
|
.long sys_mprotect /* 125 */
|
||||||
.long sys_sigprocmask
|
.long sys_sigprocmask
|
||||||
|
|
|
@ -143,7 +143,7 @@ sys_call_table:
|
||||||
.long sys_clone /* 120 */
|
.long sys_clone /* 120 */
|
||||||
.long sys_setdomainname
|
.long sys_setdomainname
|
||||||
.long sys_newuname
|
.long sys_newuname
|
||||||
.long sys_ni_syscall /* sys_modify_ldt */
|
.long sys_cacheflush /* x86: sys_modify_ldt */
|
||||||
.long sys_adjtimex
|
.long sys_adjtimex
|
||||||
.long sys_mprotect /* 125 */
|
.long sys_mprotect /* 125 */
|
||||||
.long sys_sigprocmask
|
.long sys_sigprocmask
|
||||||
|
|
Reference in New Issue