diff options
author | Stuart Menefy <stuart.menefy@st.com> | 2009-08-24 05:16:56 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-08-24 05:16:56 -0400 |
commit | 6d243dd37002bcee54841852ab1b8606fd457851 (patch) | |
tree | 9c8e55d065116647615a86e3eb0c783fe98cc83e /arch/sh | |
parent | a5cf9e2444ec15de5407696ff21c32dd21ca0a8d (diff) |
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>
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/include/asm/Kbuild | 2 | ||||
-rw-r--r-- | arch/sh/include/asm/cachectl.h | 12 | ||||
-rw-r--r-- | arch/sh/include/asm/unistd_32.h | 2 | ||||
-rw-r--r-- | arch/sh/include/asm/unistd_64.h | 2 | ||||
-rw-r--r-- | arch/sh/kernel/sys_sh.c | 43 | ||||
-rw-r--r-- | arch/sh/kernel/syscalls_32.S | 2 | ||||
-rw-r--r-- | arch/sh/kernel/syscalls_64.S | 2 |
7 files changed, 60 insertions, 5 deletions
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild index 43910cdf78a5..e121c30f797d 100644 --- a/arch/sh/include/asm/Kbuild +++ b/arch/sh/include/asm/Kbuild | |||
@@ -1,6 +1,6 @@ | |||
1 | include include/asm-generic/Kbuild.asm | 1 | include include/asm-generic/Kbuild.asm |
2 | 2 | ||
3 | header-y += cpu-features.h | 3 | header-y += cachectl.h cpu-features.h |
4 | 4 | ||
5 | unifdef-y += unistd_32.h | 5 | unifdef-y += unistd_32.h |
6 | unifdef-y += unistd_64.h | 6 | 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 index 000000000000..305dd7082a66 --- /dev/null +++ b/arch/sh/include/asm/cachectl.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef _SH_CACHECTL_H | ||
2 | #define _SH_CACHECTL_H | ||
3 | |||
4 | /* Definitions for the cacheflush system call. */ | ||
5 | |||
6 | #define CACHEFLUSH_D_INVAL 0x1 /* invalidate (without write back) */ | ||
7 | #define CACHEFLUSH_D_WB 0x2 /* write back (without invalidate) */ | ||
8 | #define CACHEFLUSH_D_PURGE 0x3 /* writeback and invalidate */ | ||
9 | |||
10 | #define CACHEFLUSH_I 0x4 | ||
11 | |||
12 | #endif /* _SH_CACHECTL_H */ | ||
diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h index 61d6ad93d786..925dd40d9d55 100644 --- a/arch/sh/include/asm/unistd_32.h +++ b/arch/sh/include/asm/unistd_32.h | |||
@@ -132,7 +132,7 @@ | |||
132 | #define __NR_clone 120 | 132 | #define __NR_clone 120 |
133 | #define __NR_setdomainname 121 | 133 | #define __NR_setdomainname 121 |
134 | #define __NR_uname 122 | 134 | #define __NR_uname 122 |
135 | #define __NR_modify_ldt 123 | 135 | #define __NR_cacheflush 123 |
136 | #define __NR_adjtimex 124 | 136 | #define __NR_adjtimex 124 |
137 | #define __NR_mprotect 125 | 137 | #define __NR_mprotect 125 |
138 | #define __NR_sigprocmask 126 | 138 | #define __NR_sigprocmask 126 |
diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h index a751699afda3..2b84bc916bc5 100644 --- a/arch/sh/include/asm/unistd_64.h +++ b/arch/sh/include/asm/unistd_64.h | |||
@@ -137,7 +137,7 @@ | |||
137 | #define __NR_clone 120 | 137 | #define __NR_clone 120 |
138 | #define __NR_setdomainname 121 | 138 | #define __NR_setdomainname 121 |
139 | #define __NR_uname 122 | 139 | #define __NR_uname 122 |
140 | #define __NR_modify_ldt 123 | 140 | #define __NR_cacheflush 123 |
141 | #define __NR_adjtimex 124 | 141 | #define __NR_adjtimex 124 |
142 | #define __NR_mprotect 125 | 142 | #define __NR_mprotect 125 |
143 | #define __NR_sigprocmask 126 | 143 | #define __NR_sigprocmask 126 |
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c index 90d00e47264d..ec65dd8842b1 100644 --- a/arch/sh/kernel/sys_sh.c +++ b/arch/sh/kernel/sys_sh.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <asm/syscalls.h> | 25 | #include <asm/syscalls.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/unistd.h> | 27 | #include <asm/unistd.h> |
28 | #include <asm/cacheflush.h> | ||
29 | #include <asm/cachectl.h> | ||
28 | 30 | ||
29 | static inline long | 31 | static inline long |
30 | do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, | 32 | 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, | |||
179 | return -EINVAL; | 181 | return -EINVAL; |
180 | } | 182 | } |
181 | 183 | ||
184 | /* sys_cacheflush -- flush (part of) the processor cache. */ | ||
185 | asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op) | ||
186 | { | ||
187 | struct vm_area_struct *vma; | ||
188 | |||
189 | if ((op < 0) || (op > (CACHEFLUSH_D_PURGE|CACHEFLUSH_I))) | ||
190 | return -EINVAL; | ||
191 | |||
192 | /* | ||
193 | * Verify that the specified address region actually belongs | ||
194 | * to this process. | ||
195 | */ | ||
196 | if (addr + len < addr) | ||
197 | return -EFAULT; | ||
198 | |||
199 | down_read(¤t->mm->mmap_sem); | ||
200 | vma = find_vma (current->mm, addr); | ||
201 | if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) { | ||
202 | up_read(¤t->mm->mmap_sem); | ||
203 | return -EFAULT; | ||
204 | } | ||
205 | |||
206 | switch (op & CACHEFLUSH_D_PURGE) { | ||
207 | case CACHEFLUSH_D_INVAL: | ||
208 | __flush_invalidate_region((void *)addr, len); | ||
209 | break; | ||
210 | case CACHEFLUSH_D_WB: | ||
211 | __flush_wback_region((void *)addr, len); | ||
212 | break; | ||
213 | case CACHEFLUSH_D_PURGE: | ||
214 | __flush_purge_region((void *)addr, len); | ||
215 | break; | ||
216 | } | ||
217 | |||
218 | if (op & CACHEFLUSH_I) | ||
219 | flush_cache_all(); | ||
220 | |||
221 | up_read(¤t->mm->mmap_sem); | ||
222 | return 0; | ||
223 | } | ||
224 | |||
182 | asmlinkage int sys_uname(struct old_utsname __user *name) | 225 | asmlinkage int sys_uname(struct old_utsname __user *name) |
183 | { | 226 | { |
184 | int err; | 227 | int err; |
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index f9e21fa2f592..16ba225ede89 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S | |||
@@ -139,7 +139,7 @@ ENTRY(sys_call_table) | |||
139 | .long sys_clone /* 120 */ | 139 | .long sys_clone /* 120 */ |
140 | .long sys_setdomainname | 140 | .long sys_setdomainname |
141 | .long sys_newuname | 141 | .long sys_newuname |
142 | .long sys_ni_syscall /* sys_modify_ldt */ | 142 | .long sys_cacheflush /* x86: sys_modify_ldt */ |
143 | .long sys_adjtimex | 143 | .long sys_adjtimex |
144 | .long sys_mprotect /* 125 */ | 144 | .long sys_mprotect /* 125 */ |
145 | .long sys_sigprocmask | 145 | .long sys_sigprocmask |
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index bf420b616ae0..af6fb7410c21 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S | |||
@@ -143,7 +143,7 @@ sys_call_table: | |||
143 | .long sys_clone /* 120 */ | 143 | .long sys_clone /* 120 */ |
144 | .long sys_setdomainname | 144 | .long sys_setdomainname |
145 | .long sys_newuname | 145 | .long sys_newuname |
146 | .long sys_ni_syscall /* sys_modify_ldt */ | 146 | .long sys_cacheflush /* x86: sys_modify_ldt */ |
147 | .long sys_adjtimex | 147 | .long sys_adjtimex |
148 | .long sys_mprotect /* 125 */ | 148 | .long sys_mprotect /* 125 */ |
149 | .long sys_sigprocmask | 149 | .long sys_sigprocmask |