sh: Add sys_cacheflush() call for SH CPUs.
authorStuart Menefy <stuart.menefy@st.com>
Mon, 24 Aug 2009 09:16:56 +0000 (18:16 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Mon, 24 Aug 2009 09:16:56 +0000 (18:16 +0900)
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>
arch/sh/include/asm/Kbuild
arch/sh/include/asm/cachectl.h [new file with mode: 0644]
arch/sh/include/asm/unistd_32.h
arch/sh/include/asm/unistd_64.h
arch/sh/kernel/sys_sh.c
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/syscalls_64.S

index 43910cd..e121c30 100644 (file)
@@ -1,6 +1,6 @@
 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_64.h
diff --git a/arch/sh/include/asm/cachectl.h b/arch/sh/include/asm/cachectl.h
new file mode 100644 (file)
index 0000000..305dd70
--- /dev/null
@@ -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 */
index 61d6ad9..925dd40 100644 (file)
 #define __NR_clone             120
 #define __NR_setdomainname     121
 #define __NR_uname             122
-#define __NR_modify_ldt                123
+#define __NR_cacheflush                123
 #define __NR_adjtimex          124
 #define __NR_mprotect          125
 #define __NR_sigprocmask       126
index a751699..2b84bc9 100644 (file)
 #define __NR_clone             120
 #define __NR_setdomainname     121
 #define __NR_uname             122
-#define __NR_modify_ldt                123
+#define __NR_cacheflush                123
 #define __NR_adjtimex          124
 #define __NR_mprotect          125
 #define __NR_sigprocmask       126
index 90d00e4..ec65dd8 100644 (file)
@@ -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(&current->mm->mmap_sem);
+       vma = find_vma (current->mm, addr);
+       if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) {
+               up_read(&current->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(&current->mm->mmap_sem);
+       return 0;
+}
+
 asmlinkage int sys_uname(struct old_utsname __user *name)
 {
        int err;
index f9e21fa..16ba225 100644 (file)
@@ -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
index bf420b6..af6fb74 100644 (file)
@@ -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