0046bcfe495a32bad1003e6662ffdbb6f1664acf
[pandora-kernel.git] / arch / powerpc / platforms / cell / spufs / run.c
1 #define DEBUG
2
3 #include <linux/wait.h>
4 #include <linux/ptrace.h>
5
6 #include <asm/spu.h>
7 #include <asm/spu_priv1.h>
8 #include <asm/io.h>
9 #include <asm/unistd.h>
10
11 #include "spufs.h"
12
13 /* interrupt-level stop callback function. */
14 void spufs_stop_callback(struct spu *spu, int irq)
15 {
16         struct spu_context *ctx = spu->ctx;
17
18         /*
19          * It should be impossible to preempt a context while an exception
20          * is being processed, since the context switch code is specially
21          * coded to deal with interrupts ... But, just in case, sanity check
22          * the context pointer.  It is OK to return doing nothing since
23          * the exception will be regenerated when the context is resumed.
24          */
25         if (ctx) {
26                 /* Copy exception arguments into module specific structure */
27                 switch(irq) {
28                 case 0 :
29                         ctx->csa.class_0_pending = spu->class_0_pending;
30                         ctx->csa.class_0_dsisr = spu->class_0_dsisr;
31                         ctx->csa.class_0_dar = spu->class_0_dar;
32                         break;
33                 case 1 :
34                         ctx->csa.class_1_dsisr = spu->class_1_dsisr;
35                         ctx->csa.class_1_dar = spu->class_1_dar;
36                         break;
37                 case 2 :
38                         break;
39                 }
40
41                 /* ensure that the exception status has hit memory before a
42                  * thread waiting on the context's stop queue is woken */
43                 smp_wmb();
44
45                 wake_up_all(&ctx->stop_wq);
46         }
47 }
48
49 int spu_stopped(struct spu_context *ctx, u32 *stat)
50 {
51         u64 dsisr;
52         u32 stopped;
53
54         stopped = SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP |
55                 SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP;
56
57 top:
58         *stat = ctx->ops->status_read(ctx);
59         if (*stat & stopped) {
60                 /*
61                  * If the spu hasn't finished stopping, we need to
62                  * re-read the register to get the stopped value.
63                  */
64                 if (*stat & SPU_STATUS_RUNNING)
65                         goto top;
66                 return 1;
67         }
68
69         if (test_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags))
70                 return 1;
71
72         dsisr = ctx->csa.class_0_dsisr;
73         if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))
74                 return 1;
75
76         dsisr = ctx->csa.class_1_dsisr;
77         if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))
78                 return 1;
79
80         if (ctx->csa.class_0_pending)
81                 return 1;
82
83         return 0;
84 }
85
86 static int spu_setup_isolated(struct spu_context *ctx)
87 {
88         int ret;
89         u64 __iomem *mfc_cntl;
90         u64 sr1;
91         u32 status;
92         unsigned long timeout;
93         const u32 status_loading = SPU_STATUS_RUNNING
94                 | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS;
95
96         ret = -ENODEV;
97         if (!isolated_loader)
98                 goto out;
99
100         /*
101          * We need to exclude userspace access to the context.
102          *
103          * To protect against memory access we invalidate all ptes
104          * and make sure the pagefault handlers block on the mutex.
105          */
106         spu_unmap_mappings(ctx);
107
108         mfc_cntl = &ctx->spu->priv2->mfc_control_RW;
109
110         /* purge the MFC DMA queue to ensure no spurious accesses before we
111          * enter kernel mode */
112         timeout = jiffies + HZ;
113         out_be64(mfc_cntl, MFC_CNTL_PURGE_DMA_REQUEST);
114         while ((in_be64(mfc_cntl) & MFC_CNTL_PURGE_DMA_STATUS_MASK)
115                         != MFC_CNTL_PURGE_DMA_COMPLETE) {
116                 if (time_after(jiffies, timeout)) {
117                         printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
118                                         __func__);
119                         ret = -EIO;
120                         goto out;
121                 }
122                 cond_resched();
123         }
124
125         /* put the SPE in kernel mode to allow access to the loader */
126         sr1 = spu_mfc_sr1_get(ctx->spu);
127         sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK;
128         spu_mfc_sr1_set(ctx->spu, sr1);
129
130         /* start the loader */
131         ctx->ops->signal1_write(ctx, (unsigned long)isolated_loader >> 32);
132         ctx->ops->signal2_write(ctx,
133                         (unsigned long)isolated_loader & 0xffffffff);
134
135         ctx->ops->runcntl_write(ctx,
136                         SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
137
138         ret = 0;
139         timeout = jiffies + HZ;
140         while (((status = ctx->ops->status_read(ctx)) & status_loading) ==
141                                 status_loading) {
142                 if (time_after(jiffies, timeout)) {
143                         printk(KERN_ERR "%s: timeout waiting for loader\n",
144                                         __func__);
145                         ret = -EIO;
146                         goto out_drop_priv;
147                 }
148                 cond_resched();
149         }
150
151         if (!(status & SPU_STATUS_RUNNING)) {
152                 /* If isolated LOAD has failed: run SPU, we will get a stop-and
153                  * signal later. */
154                 pr_debug("%s: isolated LOAD failed\n", __func__);
155                 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
156                 ret = -EACCES;
157                 goto out_drop_priv;
158         }
159
160         if (!(status & SPU_STATUS_ISOLATED_STATE)) {
161                 /* This isn't allowed by the CBEA, but check anyway */
162                 pr_debug("%s: SPU fell out of isolated mode?\n", __func__);
163                 ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
164                 ret = -EINVAL;
165                 goto out_drop_priv;
166         }
167
168 out_drop_priv:
169         /* Finished accessing the loader. Drop kernel mode */
170         sr1 |= MFC_STATE1_PROBLEM_STATE_MASK;
171         spu_mfc_sr1_set(ctx->spu, sr1);
172
173 out:
174         return ret;
175 }
176
177 static int spu_run_init(struct spu_context *ctx, u32 *npc)
178 {
179         unsigned long runcntl = SPU_RUNCNTL_RUNNABLE;
180         int ret;
181
182         spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
183
184         /*
185          * NOSCHED is synchronous scheduling with respect to the caller.
186          * The caller waits for the context to be loaded.
187          */
188         if (ctx->flags & SPU_CREATE_NOSCHED) {
189                 if (ctx->state == SPU_STATE_SAVED) {
190                         ret = spu_activate(ctx, 0);
191                         if (ret)
192                                 return ret;
193                 }
194         }
195
196         /*
197          * Apply special setup as required.
198          */
199         if (ctx->flags & SPU_CREATE_ISOLATE) {
200                 if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) {
201                         ret = spu_setup_isolated(ctx);
202                         if (ret)
203                                 return ret;
204                 }
205
206                 /*
207                  * If userspace has set the runcntrl register (eg, to
208                  * issue an isolated exit), we need to re-set it here
209                  */
210                 runcntl = ctx->ops->runcntl_read(ctx) &
211                         (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
212                 if (runcntl == 0)
213                         runcntl = SPU_RUNCNTL_RUNNABLE;
214         }
215
216         if (ctx->flags & SPU_CREATE_NOSCHED) {
217                 spuctx_switch_state(ctx, SPU_UTIL_USER);
218                 ctx->ops->runcntl_write(ctx, runcntl);
219         } else {
220                 unsigned long privcntl;
221
222                 if (test_thread_flag(TIF_SINGLESTEP))
223                         privcntl = SPU_PRIVCNTL_MODE_SINGLE_STEP;
224                 else
225                         privcntl = SPU_PRIVCNTL_MODE_NORMAL;
226
227                 ctx->ops->npc_write(ctx, *npc);
228                 ctx->ops->privcntl_write(ctx, privcntl);
229                 ctx->ops->runcntl_write(ctx, runcntl);
230
231                 if (ctx->state == SPU_STATE_SAVED) {
232                         ret = spu_activate(ctx, 0);
233                         if (ret)
234                                 return ret;
235                 } else {
236                         spuctx_switch_state(ctx, SPU_UTIL_USER);
237                 }
238         }
239
240         set_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags);
241         return 0;
242 }
243
244 static int spu_run_fini(struct spu_context *ctx, u32 *npc,
245                                u32 *status)
246 {
247         int ret = 0;
248
249         spu_del_from_rq(ctx);
250
251         *status = ctx->ops->status_read(ctx);
252         *npc = ctx->ops->npc_read(ctx);
253
254         spuctx_switch_state(ctx, SPU_UTIL_IDLE_LOADED);
255         clear_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags);
256         spu_release(ctx);
257
258         if (signal_pending(current))
259                 ret = -ERESTARTSYS;
260
261         return ret;
262 }
263
264 /*
265  * SPU syscall restarting is tricky because we violate the basic
266  * assumption that the signal handler is running on the interrupted
267  * thread. Here instead, the handler runs on PowerPC user space code,
268  * while the syscall was called from the SPU.
269  * This means we can only do a very rough approximation of POSIX
270  * signal semantics.
271  */
272 static int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret,
273                           unsigned int *npc)
274 {
275         int ret;
276
277         switch (*spu_ret) {
278         case -ERESTARTSYS:
279         case -ERESTARTNOINTR:
280                 /*
281                  * Enter the regular syscall restarting for
282                  * sys_spu_run, then restart the SPU syscall
283                  * callback.
284                  */
285                 *npc -= 8;
286                 ret = -ERESTARTSYS;
287                 break;
288         case -ERESTARTNOHAND:
289         case -ERESTART_RESTARTBLOCK:
290                 /*
291                  * Restart block is too hard for now, just return -EINTR
292                  * to the SPU.
293                  * ERESTARTNOHAND comes from sys_pause, we also return
294                  * -EINTR from there.
295                  * Assume that we need to be restarted ourselves though.
296                  */
297                 *spu_ret = -EINTR;
298                 ret = -ERESTARTSYS;
299                 break;
300         default:
301                 printk(KERN_WARNING "%s: unexpected return code %ld\n",
302                         __func__, *spu_ret);
303                 ret = 0;
304         }
305         return ret;
306 }
307
308 static int spu_process_callback(struct spu_context *ctx)
309 {
310         struct spu_syscall_block s;
311         u32 ls_pointer, npc;
312         void __iomem *ls;
313         long spu_ret;
314         int ret;
315
316         /* get syscall block from local store */
317         npc = ctx->ops->npc_read(ctx) & ~3;
318         ls = (void __iomem *)ctx->ops->get_ls(ctx);
319         ls_pointer = in_be32(ls + npc);
320         if (ls_pointer > (LS_SIZE - sizeof(s)))
321                 return -EFAULT;
322         memcpy_fromio(&s, ls + ls_pointer, sizeof(s));
323
324         /* do actual syscall without pinning the spu */
325         ret = 0;
326         spu_ret = -ENOSYS;
327         npc += 4;
328
329         if (s.nr_ret < __NR_syscalls) {
330                 spu_release(ctx);
331                 /* do actual system call from here */
332                 spu_ret = spu_sys_callback(&s);
333                 if (spu_ret <= -ERESTARTSYS) {
334                         ret = spu_handle_restartsys(ctx, &spu_ret, &npc);
335                 }
336                 mutex_lock(&ctx->state_mutex);
337                 if (ret == -ERESTARTSYS)
338                         return ret;
339         }
340
341         /* need to re-get the ls, as it may have changed when we released the
342          * spu */
343         ls = (void __iomem *)ctx->ops->get_ls(ctx);
344
345         /* write result, jump over indirect pointer */
346         memcpy_toio(ls + ls_pointer, &spu_ret, sizeof(spu_ret));
347         ctx->ops->npc_write(ctx, npc);
348         ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
349         return ret;
350 }
351
352 long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
353 {
354         int ret;
355         struct spu *spu;
356         u32 status;
357
358         if (mutex_lock_interruptible(&ctx->run_mutex))
359                 return -ERESTARTSYS;
360
361         ctx->event_return = 0;
362
363         ret = spu_acquire(ctx);
364         if (ret)
365                 goto out_unlock;
366
367         spu_enable_spu(ctx);
368
369         spu_update_sched_info(ctx);
370
371         ret = spu_run_init(ctx, npc);
372         if (ret) {
373                 spu_release(ctx);
374                 goto out;
375         }
376
377         do {
378                 ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status));
379                 if (unlikely(ret)) {
380                         /*
381                          * This is nasty: we need the state_mutex for all the
382                          * bookkeeping even if the syscall was interrupted by
383                          * a signal. ewww.
384                          */
385                         mutex_lock(&ctx->state_mutex);
386                         break;
387                 }
388                 spu = ctx->spu;
389                 if (unlikely(test_and_clear_bit(SPU_SCHED_NOTIFY_ACTIVE,
390                                                 &ctx->sched_flags))) {
391                         if (!(status & SPU_STATUS_STOPPED_BY_STOP)) {
392                                 spu_switch_notify(spu, ctx);
393                                 continue;
394                         }
395                 }
396
397                 spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
398
399                 if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
400                     (status >> SPU_STOP_STATUS_SHIFT == 0x2104)) {
401                         ret = spu_process_callback(ctx);
402                         if (ret)
403                                 break;
404                         status &= ~SPU_STATUS_STOPPED_BY_STOP;
405                 }
406                 ret = spufs_handle_class1(ctx);
407                 if (ret)
408                         break;
409
410                 ret = spufs_handle_class0(ctx);
411                 if (ret)
412                         break;
413
414                 if (signal_pending(current))
415                         ret = -ERESTARTSYS;
416         } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
417                                       SPU_STATUS_STOPPED_BY_HALT |
418                                        SPU_STATUS_SINGLE_STEP)));
419
420         spu_disable_spu(ctx);
421         ret = spu_run_fini(ctx, npc, &status);
422         spu_yield(ctx);
423
424         spu_switch_log_notify(NULL, ctx, SWITCH_LOG_EXIT, status);
425
426         if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
427             (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100))
428                 ctx->stats.libassist++;
429
430         if ((ret == 0) ||
431             ((ret == -ERESTARTSYS) &&
432              ((status & SPU_STATUS_STOPPED_BY_HALT) ||
433               (status & SPU_STATUS_SINGLE_STEP) ||
434               ((status & SPU_STATUS_STOPPED_BY_STOP) &&
435                (status >> SPU_STOP_STATUS_SHIFT != 0x2104)))))
436                 ret = status;
437
438         /* Note: we don't need to force_sig SIGTRAP on single-step
439          * since we have TIF_SINGLESTEP set, thus the kernel will do
440          * it upon return from the syscall anyawy
441          */
442         if (unlikely(status & SPU_STATUS_SINGLE_STEP))
443                 ret = -ERESTARTSYS;
444
445         else if (unlikely((status & SPU_STATUS_STOPPED_BY_STOP)
446             && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff)) {
447                 force_sig(SIGTRAP, current);
448                 ret = -ERESTARTSYS;
449         }
450
451 out:
452         *event = ctx->event_return;
453 out_unlock:
454         mutex_unlock(&ctx->run_mutex);
455         return ret;
456 }