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>
Этот коммит содержится в:

коммит произвёл
Paul Mundt

родитель
a5cf9e2444
Коммит
6d243dd370
@@ -25,6 +25,8 @@
|
||||
#include <asm/syscalls.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cachectl.h>
|
||||
|
||||
static inline long
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int err;
|
||||
|
@@ -139,7 +139,7 @@ ENTRY(sys_call_table)
|
||||
.long sys_clone /* 120 */
|
||||
.long sys_setdomainname
|
||||
.long sys_newuname
|
||||
.long sys_ni_syscall /* sys_modify_ldt */
|
||||
.long sys_cacheflush /* x86: sys_modify_ldt */
|
||||
.long sys_adjtimex
|
||||
.long sys_mprotect /* 125 */
|
||||
.long sys_sigprocmask
|
||||
|
@@ -143,7 +143,7 @@ sys_call_table:
|
||||
.long sys_clone /* 120 */
|
||||
.long sys_setdomainname
|
||||
.long sys_newuname
|
||||
.long sys_ni_syscall /* sys_modify_ldt */
|
||||
.long sys_cacheflush /* x86: sys_modify_ldt */
|
||||
.long sys_adjtimex
|
||||
.long sys_mprotect /* 125 */
|
||||
.long sys_sigprocmask
|
||||
|
Ссылка в новой задаче
Block a user