diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/platforms/cell/Makefile | 10 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spu_callbacks.c | 345 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/run.c | 91 |
3 files changed, 444 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 3b998a393e3f..e570bad06394 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile | |||
@@ -6,5 +6,11 @@ obj-$(CONFIG_SPU_FS) += spu-base.o spufs/ | |||
6 | 6 | ||
7 | spu-base-y += spu_base.o spu_priv1.o | 7 | spu-base-y += spu_base.o spu_priv1.o |
8 | 8 | ||
9 | builtin-spufs-$(CONFIG_SPU_FS) += spu_syscalls.o | 9 | # needed only when building loadable spufs.ko |
10 | obj-y += $(builtin-spufs-m) | 10 | spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o |
11 | obj-y += $(spufs-modular-m) | ||
12 | |||
13 | # always needed in kernel | ||
14 | spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o | ||
15 | obj-y += $(spufs-builtin-y) $(spufs-builtin-m) | ||
16 | |||
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c new file mode 100644 index 000000000000..3a4245c926ad --- /dev/null +++ b/arch/powerpc/platforms/cell/spu_callbacks.c | |||
@@ -0,0 +1,345 @@ | |||
1 | /* | ||
2 | * System call callback functions for SPUs | ||
3 | */ | ||
4 | |||
5 | #define DEBUG | ||
6 | |||
7 | #include <linux/kallsyms.h> | ||
8 | #include <linux/module.h> | ||
9 | #include <linux/syscalls.h> | ||
10 | |||
11 | #include <asm/spu.h> | ||
12 | #include <asm/syscalls.h> | ||
13 | #include <asm/unistd.h> | ||
14 | |||
15 | /* | ||
16 | * This table defines the system calls that an SPU can call. | ||
17 | * It is currently a subset of the 64 bit powerpc system calls, | ||
18 | * with the exact semantics. | ||
19 | * | ||
20 | * The reasons for disabling some of the system calls are: | ||
21 | * 1. They interact with the way SPU syscalls are handled | ||
22 | * and we can't let them execute ever: | ||
23 | * restart_syscall, exit, for, execve, ptrace, ... | ||
24 | * 2. They are deprecated and replaced by other means: | ||
25 | * uselib, pciconfig_*, sysfs, ... | ||
26 | * 3. They are somewhat interacting with the system in a way | ||
27 | * we don't want an SPU to: | ||
28 | * reboot, init_module, mount, kexec_load | ||
29 | * 4. They are optional and we can't rely on them being | ||
30 | * linked into the kernel. Unfortunately, the cond_syscall | ||
31 | * helper does not work here as it does not add the necessary | ||
32 | * opd symbols: | ||
33 | * mbind, mq_open, ipc, ... | ||
34 | */ | ||
35 | |||
36 | void *spu_syscall_table[] = { | ||
37 | [__NR_restart_syscall] sys_ni_syscall, /* sys_restart_syscall */ | ||
38 | [__NR_exit] sys_ni_syscall, /* sys_exit */ | ||
39 | [__NR_fork] sys_ni_syscall, /* ppc_fork */ | ||
40 | [__NR_read] sys_read, | ||
41 | [__NR_write] sys_write, | ||
42 | [__NR_open] sys_open, | ||
43 | [__NR_close] sys_close, | ||
44 | [__NR_waitpid] sys_waitpid, | ||
45 | [__NR_creat] sys_creat, | ||
46 | [__NR_link] sys_link, | ||
47 | [__NR_unlink] sys_unlink, | ||
48 | [__NR_execve] sys_ni_syscall, /* sys_execve */ | ||
49 | [__NR_chdir] sys_chdir, | ||
50 | [__NR_time] sys_time, | ||
51 | [__NR_mknod] sys_mknod, | ||
52 | [__NR_chmod] sys_chmod, | ||
53 | [__NR_lchown] sys_lchown, | ||
54 | [__NR_break] sys_ni_syscall, | ||
55 | [__NR_oldstat] sys_ni_syscall, | ||
56 | [__NR_lseek] sys_lseek, | ||
57 | [__NR_getpid] sys_getpid, | ||
58 | [__NR_mount] sys_ni_syscall, /* sys_mount */ | ||
59 | [__NR_umount] sys_ni_syscall, | ||
60 | [__NR_setuid] sys_setuid, | ||
61 | [__NR_getuid] sys_getuid, | ||
62 | [__NR_stime] sys_stime, | ||
63 | [__NR_ptrace] sys_ni_syscall, /* sys_ptrace */ | ||
64 | [__NR_alarm] sys_alarm, | ||
65 | [__NR_oldfstat] sys_ni_syscall, | ||
66 | [__NR_pause] sys_ni_syscall, /* sys_pause */ | ||
67 | [__NR_utime] sys_ni_syscall, /* sys_utime */ | ||
68 | [__NR_stty] sys_ni_syscall, | ||
69 | [__NR_gtty] sys_ni_syscall, | ||
70 | [__NR_access] sys_access, | ||
71 | [__NR_nice] sys_nice, | ||
72 | [__NR_ftime] sys_ni_syscall, | ||
73 | [__NR_sync] sys_sync, | ||
74 | [__NR_kill] sys_kill, | ||
75 | [__NR_rename] sys_rename, | ||
76 | [__NR_mkdir] sys_mkdir, | ||
77 | [__NR_rmdir] sys_rmdir, | ||
78 | [__NR_dup] sys_dup, | ||
79 | [__NR_pipe] sys_pipe, | ||
80 | [__NR_times] sys_times, | ||
81 | [__NR_prof] sys_ni_syscall, | ||
82 | [__NR_brk] sys_brk, | ||
83 | [__NR_setgid] sys_setgid, | ||
84 | [__NR_getgid] sys_getgid, | ||
85 | [__NR_signal] sys_ni_syscall, /* sys_signal */ | ||
86 | [__NR_geteuid] sys_geteuid, | ||
87 | [__NR_getegid] sys_getegid, | ||
88 | [__NR_acct] sys_ni_syscall, /* sys_acct */ | ||
89 | [__NR_umount2] sys_ni_syscall, /* sys_umount */ | ||
90 | [__NR_lock] sys_ni_syscall, | ||
91 | [__NR_ioctl] sys_ioctl, | ||
92 | [__NR_fcntl] sys_fcntl, | ||
93 | [__NR_mpx] sys_ni_syscall, | ||
94 | [__NR_setpgid] sys_setpgid, | ||
95 | [__NR_ulimit] sys_ni_syscall, | ||
96 | [__NR_oldolduname] sys_ni_syscall, | ||
97 | [__NR_umask] sys_umask, | ||
98 | [__NR_chroot] sys_chroot, | ||
99 | [__NR_ustat] sys_ni_syscall, /* sys_ustat */ | ||
100 | [__NR_dup2] sys_dup2, | ||
101 | [__NR_getppid] sys_getppid, | ||
102 | [__NR_getpgrp] sys_getpgrp, | ||
103 | [__NR_setsid] sys_setsid, | ||
104 | [__NR_sigaction] sys_ni_syscall, | ||
105 | [__NR_sgetmask] sys_sgetmask, | ||
106 | [__NR_ssetmask] sys_ssetmask, | ||
107 | [__NR_setreuid] sys_setreuid, | ||
108 | [__NR_setregid] sys_setregid, | ||
109 | [__NR_sigsuspend] sys_ni_syscall, | ||
110 | [__NR_sigpending] sys_ni_syscall, | ||
111 | [__NR_sethostname] sys_sethostname, | ||
112 | [__NR_setrlimit] sys_setrlimit, | ||
113 | [__NR_getrlimit] sys_ni_syscall, | ||
114 | [__NR_getrusage] sys_getrusage, | ||
115 | [__NR_gettimeofday] sys_gettimeofday, | ||
116 | [__NR_settimeofday] sys_settimeofday, | ||
117 | [__NR_getgroups] sys_getgroups, | ||
118 | [__NR_setgroups] sys_setgroups, | ||
119 | [__NR_select] sys_ni_syscall, | ||
120 | [__NR_symlink] sys_symlink, | ||
121 | [__NR_oldlstat] sys_ni_syscall, | ||
122 | [__NR_readlink] sys_readlink, | ||
123 | [__NR_uselib] sys_ni_syscall, /* sys_uselib */ | ||
124 | [__NR_swapon] sys_ni_syscall, /* sys_swapon */ | ||
125 | [__NR_reboot] sys_ni_syscall, /* sys_reboot */ | ||
126 | [__NR_readdir] sys_ni_syscall, | ||
127 | [__NR_mmap] sys_mmap, | ||
128 | [__NR_munmap] sys_munmap, | ||
129 | [__NR_truncate] sys_truncate, | ||
130 | [__NR_ftruncate] sys_ftruncate, | ||
131 | [__NR_fchmod] sys_fchmod, | ||
132 | [__NR_fchown] sys_fchown, | ||
133 | [__NR_getpriority] sys_getpriority, | ||
134 | [__NR_setpriority] sys_setpriority, | ||
135 | [__NR_profil] sys_ni_syscall, | ||
136 | [__NR_statfs] sys_ni_syscall, /* sys_statfs */ | ||
137 | [__NR_fstatfs] sys_ni_syscall, /* sys_fstatfs */ | ||
138 | [__NR_ioperm] sys_ni_syscall, | ||
139 | [__NR_socketcall] sys_socketcall, | ||
140 | [__NR_syslog] sys_syslog, | ||
141 | [__NR_setitimer] sys_setitimer, | ||
142 | [__NR_getitimer] sys_getitimer, | ||
143 | [__NR_stat] sys_newstat, | ||
144 | [__NR_lstat] sys_newlstat, | ||
145 | [__NR_fstat] sys_newfstat, | ||
146 | [__NR_olduname] sys_ni_syscall, | ||
147 | [__NR_iopl] sys_ni_syscall, | ||
148 | [__NR_vhangup] sys_vhangup, | ||
149 | [__NR_idle] sys_ni_syscall, | ||
150 | [__NR_vm86] sys_ni_syscall, | ||
151 | [__NR_wait4] sys_wait4, | ||
152 | [__NR_swapoff] sys_ni_syscall, /* sys_swapoff */ | ||
153 | [__NR_sysinfo] sys_sysinfo, | ||
154 | [__NR_ipc] sys_ni_syscall, /* sys_ipc */ | ||
155 | [__NR_fsync] sys_fsync, | ||
156 | [__NR_sigreturn] sys_ni_syscall, | ||
157 | [__NR_clone] sys_ni_syscall, /* ppc_clone */ | ||
158 | [__NR_setdomainname] sys_setdomainname, | ||
159 | [__NR_uname] ppc_newuname, | ||
160 | [__NR_modify_ldt] sys_ni_syscall, | ||
161 | [__NR_adjtimex] sys_adjtimex, | ||
162 | [__NR_mprotect] sys_mprotect, | ||
163 | [__NR_sigprocmask] sys_ni_syscall, | ||
164 | [__NR_create_module] sys_ni_syscall, | ||
165 | [__NR_init_module] sys_ni_syscall, /* sys_init_module */ | ||
166 | [__NR_delete_module] sys_ni_syscall, /* sys_delete_module */ | ||
167 | [__NR_get_kernel_syms] sys_ni_syscall, | ||
168 | [__NR_quotactl] sys_ni_syscall, /* sys_quotactl */ | ||
169 | [__NR_getpgid] sys_getpgid, | ||
170 | [__NR_fchdir] sys_fchdir, | ||
171 | [__NR_bdflush] sys_bdflush, | ||
172 | [__NR_sysfs] sys_ni_syscall, /* sys_sysfs */ | ||
173 | [__NR_personality] ppc64_personality, | ||
174 | [__NR_afs_syscall] sys_ni_syscall, | ||
175 | [__NR_setfsuid] sys_setfsuid, | ||
176 | [__NR_setfsgid] sys_setfsgid, | ||
177 | [__NR__llseek] sys_llseek, | ||
178 | [__NR_getdents] sys_getdents, | ||
179 | [__NR__newselect] sys_select, | ||
180 | [__NR_flock] sys_flock, | ||
181 | [__NR_msync] sys_msync, | ||
182 | [__NR_readv] sys_readv, | ||
183 | [__NR_writev] sys_writev, | ||
184 | [__NR_getsid] sys_getsid, | ||
185 | [__NR_fdatasync] sys_fdatasync, | ||
186 | [__NR__sysctl] sys_ni_syscall, /* sys_sysctl */ | ||
187 | [__NR_mlock] sys_mlock, | ||
188 | [__NR_munlock] sys_munlock, | ||
189 | [__NR_mlockall] sys_mlockall, | ||
190 | [__NR_munlockall] sys_munlockall, | ||
191 | [__NR_sched_setparam] sys_sched_setparam, | ||
192 | [__NR_sched_getparam] sys_sched_getparam, | ||
193 | [__NR_sched_setscheduler] sys_sched_setscheduler, | ||
194 | [__NR_sched_getscheduler] sys_sched_getscheduler, | ||
195 | [__NR_sched_yield] sys_sched_yield, | ||
196 | [__NR_sched_get_priority_max] sys_sched_get_priority_max, | ||
197 | [__NR_sched_get_priority_min] sys_sched_get_priority_min, | ||
198 | [__NR_sched_rr_get_interval] sys_sched_rr_get_interval, | ||
199 | [__NR_nanosleep] sys_nanosleep, | ||
200 | [__NR_mremap] sys_mremap, | ||
201 | [__NR_setresuid] sys_setresuid, | ||
202 | [__NR_getresuid] sys_getresuid, | ||
203 | [__NR_query_module] sys_ni_syscall, | ||
204 | [__NR_poll] sys_poll, | ||
205 | [__NR_nfsservctl] sys_ni_syscall, /* sys_nfsservctl */ | ||
206 | [__NR_setresgid] sys_setresgid, | ||
207 | [__NR_getresgid] sys_getresgid, | ||
208 | [__NR_prctl] sys_prctl, | ||
209 | [__NR_rt_sigreturn] sys_ni_syscall, /* ppc64_rt_sigreturn */ | ||
210 | [__NR_rt_sigaction] sys_ni_syscall, /* sys_rt_sigaction */ | ||
211 | [__NR_rt_sigprocmask] sys_ni_syscall, /* sys_rt_sigprocmask */ | ||
212 | [__NR_rt_sigpending] sys_ni_syscall, /* sys_rt_sigpending */ | ||
213 | [__NR_rt_sigtimedwait] sys_ni_syscall, /* sys_rt_sigtimedwait */ | ||
214 | [__NR_rt_sigqueueinfo] sys_ni_syscall, /* sys_rt_sigqueueinfo */ | ||
215 | [__NR_rt_sigsuspend] sys_ni_syscall, /* sys_rt_sigsuspend */ | ||
216 | [__NR_pread64] sys_pread64, | ||
217 | [__NR_pwrite64] sys_pwrite64, | ||
218 | [__NR_chown] sys_chown, | ||
219 | [__NR_getcwd] sys_getcwd, | ||
220 | [__NR_capget] sys_capget, | ||
221 | [__NR_capset] sys_capset, | ||
222 | [__NR_sigaltstack] sys_ni_syscall, /* sys_sigaltstack */ | ||
223 | [__NR_sendfile] sys_sendfile64, | ||
224 | [__NR_getpmsg] sys_ni_syscall, | ||
225 | [__NR_putpmsg] sys_ni_syscall, | ||
226 | [__NR_vfork] sys_ni_syscall, /* ppc_vfork */ | ||
227 | [__NR_ugetrlimit] sys_getrlimit, | ||
228 | [__NR_readahead] sys_readahead, | ||
229 | [192] sys_ni_syscall, | ||
230 | [193] sys_ni_syscall, | ||
231 | [194] sys_ni_syscall, | ||
232 | [195] sys_ni_syscall, | ||
233 | [196] sys_ni_syscall, | ||
234 | [197] sys_ni_syscall, | ||
235 | [__NR_pciconfig_read] sys_ni_syscall, /* sys_pciconfig_read */ | ||
236 | [__NR_pciconfig_write] sys_ni_syscall, /* sys_pciconfig_write */ | ||
237 | [__NR_pciconfig_iobase] sys_ni_syscall, /* sys_pciconfig_iobase */ | ||
238 | [__NR_multiplexer] sys_ni_syscall, | ||
239 | [__NR_getdents64] sys_getdents64, | ||
240 | [__NR_pivot_root] sys_pivot_root, | ||
241 | [204] sys_ni_syscall, | ||
242 | [__NR_madvise] sys_madvise, | ||
243 | [__NR_mincore] sys_mincore, | ||
244 | [__NR_gettid] sys_gettid, | ||
245 | [__NR_tkill] sys_tkill, | ||
246 | [__NR_setxattr] sys_setxattr, | ||
247 | [__NR_lsetxattr] sys_lsetxattr, | ||
248 | [__NR_fsetxattr] sys_fsetxattr, | ||
249 | [__NR_getxattr] sys_getxattr, | ||
250 | [__NR_lgetxattr] sys_lgetxattr, | ||
251 | [__NR_fgetxattr] sys_fgetxattr, | ||
252 | [__NR_listxattr] sys_listxattr, | ||
253 | [__NR_llistxattr] sys_llistxattr, | ||
254 | [__NR_flistxattr] sys_flistxattr, | ||
255 | [__NR_removexattr] sys_removexattr, | ||
256 | [__NR_lremovexattr] sys_lremovexattr, | ||
257 | [__NR_fremovexattr] sys_fremovexattr, | ||
258 | [__NR_futex] sys_futex, | ||
259 | [__NR_sched_setaffinity] sys_sched_setaffinity, | ||
260 | [__NR_sched_getaffinity] sys_sched_getaffinity, | ||
261 | [__NR_tuxcall] sys_ni_syscall, | ||
262 | [226] sys_ni_syscall, | ||
263 | [__NR_io_setup] sys_io_setup, | ||
264 | [__NR_io_destroy] sys_io_destroy, | ||
265 | [__NR_io_getevents] sys_io_getevents, | ||
266 | [__NR_io_submit] sys_io_submit, | ||
267 | [__NR_io_cancel] sys_io_cancel, | ||
268 | [__NR_set_tid_address] sys_ni_syscall, /* sys_set_tid_address */ | ||
269 | [__NR_fadvise64] sys_fadvise64, | ||
270 | [__NR_exit_group] sys_ni_syscall, /* sys_exit_group */ | ||
271 | [__NR_lookup_dcookie] sys_ni_syscall, /* sys_lookup_dcookie */ | ||
272 | [__NR_epoll_create] sys_epoll_create, | ||
273 | [__NR_epoll_ctl] sys_epoll_ctl, | ||
274 | [__NR_epoll_wait] sys_epoll_wait, | ||
275 | [__NR_remap_file_pages] sys_remap_file_pages, | ||
276 | [__NR_timer_create] sys_timer_create, | ||
277 | [__NR_timer_settime] sys_timer_settime, | ||
278 | [__NR_timer_gettime] sys_timer_gettime, | ||
279 | [__NR_timer_getoverrun] sys_timer_getoverrun, | ||
280 | [__NR_timer_delete] sys_timer_delete, | ||
281 | [__NR_clock_settime] sys_clock_settime, | ||
282 | [__NR_clock_gettime] sys_clock_gettime, | ||
283 | [__NR_clock_getres] sys_clock_getres, | ||
284 | [__NR_clock_nanosleep] sys_clock_nanosleep, | ||
285 | [__NR_swapcontext] sys_ni_syscall, /* ppc64_swapcontext */ | ||
286 | [__NR_tgkill] sys_tgkill, | ||
287 | [__NR_utimes] sys_utimes, | ||
288 | [__NR_statfs64] sys_statfs64, | ||
289 | [__NR_fstatfs64] sys_fstatfs64, | ||
290 | [254] sys_ni_syscall, | ||
291 | [__NR_rtas] ppc_rtas, | ||
292 | [256] sys_ni_syscall, | ||
293 | [257] sys_ni_syscall, | ||
294 | [258] sys_ni_syscall, | ||
295 | [__NR_mbind] sys_ni_syscall, /* sys_mbind */ | ||
296 | [__NR_get_mempolicy] sys_ni_syscall, /* sys_get_mempolicy */ | ||
297 | [__NR_set_mempolicy] sys_ni_syscall, /* sys_set_mempolicy */ | ||
298 | [__NR_mq_open] sys_ni_syscall, /* sys_mq_open */ | ||
299 | [__NR_mq_unlink] sys_ni_syscall, /* sys_mq_unlink */ | ||
300 | [__NR_mq_timedsend] sys_ni_syscall, /* sys_mq_timedsend */ | ||
301 | [__NR_mq_timedreceive] sys_ni_syscall, /* sys_mq_timedreceive */ | ||
302 | [__NR_mq_notify] sys_ni_syscall, /* sys_mq_notify */ | ||
303 | [__NR_mq_getsetattr] sys_ni_syscall, /* sys_mq_getsetattr */ | ||
304 | [__NR_kexec_load] sys_ni_syscall, /* sys_kexec_load */ | ||
305 | [__NR_add_key] sys_ni_syscall, /* sys_add_key */ | ||
306 | [__NR_request_key] sys_ni_syscall, /* sys_request_key */ | ||
307 | [__NR_keyctl] sys_ni_syscall, /* sys_keyctl */ | ||
308 | [__NR_waitid] sys_ni_syscall, /* sys_waitid */ | ||
309 | [__NR_ioprio_set] sys_ni_syscall, /* sys_ioprio_set */ | ||
310 | [__NR_ioprio_get] sys_ni_syscall, /* sys_ioprio_get */ | ||
311 | [__NR_inotify_init] sys_ni_syscall, /* sys_inotify_init */ | ||
312 | [__NR_inotify_add_watch] sys_ni_syscall, /* sys_inotify_add_watch */ | ||
313 | [__NR_inotify_rm_watch] sys_ni_syscall, /* sys_inotify_rm_watch */ | ||
314 | [__NR_spu_run] sys_ni_syscall, /* sys_spu_run */ | ||
315 | [__NR_spu_create] sys_ni_syscall, /* sys_spu_create */ | ||
316 | [__NR_pselect6] sys_ni_syscall, /* sys_pselect */ | ||
317 | [__NR_ppoll] sys_ni_syscall, /* sys_ppoll */ | ||
318 | [__NR_unshare] sys_unshare, | ||
319 | }; | ||
320 | |||
321 | long spu_sys_callback(struct spu_syscall_block *s) | ||
322 | { | ||
323 | long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6); | ||
324 | |||
325 | BUILD_BUG_ON(ARRAY_SIZE(spu_syscall_table) != __NR_syscalls); | ||
326 | |||
327 | syscall = spu_syscall_table[s->nr_ret]; | ||
328 | |||
329 | if (s->nr_ret >= __NR_syscalls) { | ||
330 | pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret); | ||
331 | return -ENOSYS; | ||
332 | } | ||
333 | |||
334 | #ifdef DEBUG | ||
335 | print_symbol(KERN_DEBUG "SPU-syscall %s:", (unsigned long)syscall); | ||
336 | printk("syscall%ld(%lx, %lx, %lx, %lx, %lx, %lx)\n", | ||
337 | s->nr_ret, | ||
338 | s->parm[0], s->parm[1], s->parm[2], | ||
339 | s->parm[3], s->parm[4], s->parm[5]); | ||
340 | #endif | ||
341 | |||
342 | return syscall(s->parm[0], s->parm[1], s->parm[2], | ||
343 | s->parm[3], s->parm[4], s->parm[5]); | ||
344 | } | ||
345 | EXPORT_SYMBOL_GPL(spu_sys_callback); | ||
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 18ea8866c61a..c04e078c0fe5 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -76,6 +76,90 @@ static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc, | |||
76 | return 0; | 76 | return 0; |
77 | } | 77 | } |
78 | 78 | ||
79 | /* | ||
80 | * SPU syscall restarting is tricky because we violate the basic | ||
81 | * assumption that the signal handler is running on the interrupted | ||
82 | * thread. Here instead, the handler runs on PowerPC user space code, | ||
83 | * while the syscall was called from the SPU. | ||
84 | * This means we can only do a very rough approximation of POSIX | ||
85 | * signal semantics. | ||
86 | */ | ||
87 | int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret, | ||
88 | unsigned int *npc) | ||
89 | { | ||
90 | int ret; | ||
91 | |||
92 | switch (*spu_ret) { | ||
93 | case -ERESTARTSYS: | ||
94 | case -ERESTARTNOINTR: | ||
95 | /* | ||
96 | * Enter the regular syscall restarting for | ||
97 | * sys_spu_run, then restart the SPU syscall | ||
98 | * callback. | ||
99 | */ | ||
100 | *npc -= 8; | ||
101 | ret = -ERESTARTSYS; | ||
102 | break; | ||
103 | case -ERESTARTNOHAND: | ||
104 | case -ERESTART_RESTARTBLOCK: | ||
105 | /* | ||
106 | * Restart block is too hard for now, just return -EINTR | ||
107 | * to the SPU. | ||
108 | * ERESTARTNOHAND comes from sys_pause, we also return | ||
109 | * -EINTR from there. | ||
110 | * Assume that we need to be restarted ourselves though. | ||
111 | */ | ||
112 | *spu_ret = -EINTR; | ||
113 | ret = -ERESTARTSYS; | ||
114 | break; | ||
115 | default: | ||
116 | printk(KERN_WARNING "%s: unexpected return code %ld\n", | ||
117 | __FUNCTION__, *spu_ret); | ||
118 | ret = 0; | ||
119 | } | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | int spu_process_callback(struct spu_context *ctx) | ||
124 | { | ||
125 | struct spu_syscall_block s; | ||
126 | u32 ls_pointer, npc; | ||
127 | char *ls; | ||
128 | long spu_ret; | ||
129 | int ret; | ||
130 | |||
131 | /* get syscall block from local store */ | ||
132 | npc = ctx->ops->npc_read(ctx); | ||
133 | ls = ctx->ops->get_ls(ctx); | ||
134 | ls_pointer = *(u32*)(ls + npc); | ||
135 | if (ls_pointer > (LS_SIZE - sizeof(s))) | ||
136 | return -EFAULT; | ||
137 | memcpy(&s, ls + ls_pointer, sizeof (s)); | ||
138 | |||
139 | /* do actual syscall without pinning the spu */ | ||
140 | ret = 0; | ||
141 | spu_ret = -ENOSYS; | ||
142 | npc += 4; | ||
143 | |||
144 | if (s.nr_ret < __NR_syscalls) { | ||
145 | spu_release(ctx); | ||
146 | /* do actual system call from here */ | ||
147 | spu_ret = spu_sys_callback(&s); | ||
148 | if (spu_ret <= -ERESTARTSYS) { | ||
149 | ret = spu_handle_restartsys(ctx, &spu_ret, &npc); | ||
150 | } | ||
151 | spu_acquire(ctx); | ||
152 | if (ret == -ERESTARTSYS) | ||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | /* write result, jump over indirect pointer */ | ||
157 | memcpy(ls + ls_pointer, &spu_ret, sizeof (spu_ret)); | ||
158 | ctx->ops->npc_write(ctx, npc); | ||
159 | ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); | ||
160 | return ret; | ||
161 | } | ||
162 | |||
79 | static inline int spu_process_events(struct spu_context *ctx) | 163 | static inline int spu_process_events(struct spu_context *ctx) |
80 | { | 164 | { |
81 | struct spu *spu = ctx->spu; | 165 | struct spu *spu = ctx->spu; |
@@ -107,6 +191,13 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, | |||
107 | ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status)); | 191 | ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status)); |
108 | if (unlikely(ret)) | 192 | if (unlikely(ret)) |
109 | break; | 193 | break; |
194 | if ((*status & SPU_STATUS_STOPPED_BY_STOP) && | ||
195 | (*status >> SPU_STOP_STATUS_SHIFT == 0x2104)) { | ||
196 | ret = spu_process_callback(ctx); | ||
197 | if (ret) | ||
198 | break; | ||
199 | *status &= ~SPU_STATUS_STOPPED_BY_STOP; | ||
200 | } | ||
110 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { | 201 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { |
111 | ret = spu_reacquire_runnable(ctx, npc, status); | 202 | ret = spu_reacquire_runnable(ctx, npc, status); |
112 | if (ret) | 203 | if (ret) |