diff options
| -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 | ||||
| -rw-r--r-- | include/asm-powerpc/spu.h | 9 |
4 files changed, 452 insertions, 3 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) |
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index 38bacf2f6e0c..b5c90d6fdceb 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h | |||
| @@ -149,6 +149,14 @@ int spu_irq_class_0_bottom(struct spu *spu); | |||
| 149 | int spu_irq_class_1_bottom(struct spu *spu); | 149 | int spu_irq_class_1_bottom(struct spu *spu); |
| 150 | void spu_irq_setaffinity(struct spu *spu, int cpu); | 150 | void spu_irq_setaffinity(struct spu *spu, int cpu); |
| 151 | 151 | ||
| 152 | /* system callbacks from the SPU */ | ||
| 153 | struct spu_syscall_block { | ||
| 154 | u64 nr_ret; | ||
| 155 | u64 parm[6]; | ||
| 156 | }; | ||
| 157 | extern long spu_sys_callback(struct spu_syscall_block *s); | ||
| 158 | |||
| 159 | /* syscalls implemented in spufs */ | ||
| 152 | extern struct spufs_calls { | 160 | extern struct spufs_calls { |
| 153 | asmlinkage long (*create_thread)(const char __user *name, | 161 | asmlinkage long (*create_thread)(const char __user *name, |
| 154 | unsigned int flags, mode_t mode); | 162 | unsigned int flags, mode_t mode); |
| @@ -399,7 +407,6 @@ struct spu_priv1 { | |||
| 399 | #define SPU_GET_REVISION_BITS(vr) (vr & SPU_REVISION_BITS) | 407 | #define SPU_GET_REVISION_BITS(vr) (vr & SPU_REVISION_BITS) |
| 400 | u8 pad_0x28_0x100[0x100 - 0x28]; /* 0x28 */ | 408 | u8 pad_0x28_0x100[0x100 - 0x28]; /* 0x28 */ |
| 401 | 409 | ||
| 402 | |||
| 403 | /* Interrupt Area */ | 410 | /* Interrupt Area */ |
| 404 | u64 int_mask_RW[3]; /* 0x100 */ | 411 | u64 int_mask_RW[3]; /* 0x100 */ |
| 405 | #define CLASS0_ENABLE_DMA_ALIGNMENT_INTR 0x1L | 412 | #define CLASS0_ENABLE_DMA_ALIGNMENT_INTR 0x1L |
