[PATCH] spufs: Improved SPU preemptability.
[linux-2.6] / arch / powerpc / platforms / cell / spufs / file.c
1 /*
2  * SPU file system -- file contents
3  *
4  * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
5  *
6  * Author: Arnd Bergmann <arndb@de.ibm.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include <linux/fs.h>
24 #include <linux/ioctl.h>
25 #include <linux/module.h>
26 #include <linux/pagemap.h>
27 #include <linux/poll.h>
28 #include <linux/ptrace.h>
29
30 #include <asm/io.h>
31 #include <asm/semaphore.h>
32 #include <asm/spu.h>
33 #include <asm/uaccess.h>
34
35 #include "spufs.h"
36
37
38 static int
39 spufs_mem_open(struct inode *inode, struct file *file)
40 {
41         struct spufs_inode_info *i = SPUFS_I(inode);
42         file->private_data = i->i_ctx;
43         file->f_mapping = i->i_ctx->local_store;
44         return 0;
45 }
46
47 static ssize_t
48 spufs_mem_read(struct file *file, char __user *buffer,
49                                 size_t size, loff_t *pos)
50 {
51         struct spu_context *ctx = file->private_data;
52         char *local_store;
53         int ret;
54
55         spu_acquire(ctx);
56
57         local_store = ctx->ops->get_ls(ctx);
58         ret = simple_read_from_buffer(buffer, size, pos, local_store, LS_SIZE);
59
60         spu_release(ctx);
61         return ret;
62 }
63
64 static ssize_t
65 spufs_mem_write(struct file *file, const char __user *buffer,
66                                         size_t size, loff_t *pos)
67 {
68         struct spu_context *ctx = file->private_data;
69         char *local_store;
70         int ret;
71
72         size = min_t(ssize_t, LS_SIZE - *pos, size);
73         if (size <= 0)
74                 return -EFBIG;
75         *pos += size;
76
77         spu_acquire(ctx);
78
79         local_store = ctx->ops->get_ls(ctx);
80         ret = copy_from_user(local_store + *pos - size,
81                              buffer, size) ? -EFAULT : size;
82
83         spu_release(ctx);
84         return ret;
85 }
86
87 #ifdef CONFIG_SPARSEMEM
88 static struct page *
89 spufs_mem_mmap_nopage(struct vm_area_struct *vma,
90                       unsigned long address, int *type)
91 {
92         struct page *page = NOPAGE_SIGBUS;
93
94         struct spu_context *ctx = vma->vm_file->private_data;
95         unsigned long offset = address - vma->vm_start;
96         offset += vma->vm_pgoff << PAGE_SHIFT;
97
98         spu_acquire(ctx);
99
100         if (ctx->state == SPU_STATE_SAVED)
101                 page = vmalloc_to_page(ctx->csa.lscsa->ls + offset);
102         else
103                 page = pfn_to_page((ctx->spu->local_store_phys + offset)
104                                    >> PAGE_SHIFT);
105
106         spu_release(ctx);
107
108         if (type)
109                 *type = VM_FAULT_MINOR;
110
111         page_cache_get(page);
112         return page;
113 }
114
115 static struct vm_operations_struct spufs_mem_mmap_vmops = {
116         .nopage = spufs_mem_mmap_nopage,
117 };
118
119 static int
120 spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
121 {
122         if (!(vma->vm_flags & VM_SHARED))
123                 return -EINVAL;
124
125         /* FIXME: */
126         vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
127                                      | _PAGE_NO_CACHE);
128
129         vma->vm_ops = &spufs_mem_mmap_vmops;
130         return 0;
131 }
132 #endif
133
134 static struct file_operations spufs_mem_fops = {
135         .open    = spufs_mem_open,
136         .read    = spufs_mem_read,
137         .write   = spufs_mem_write,
138         .llseek  = generic_file_llseek,
139 #ifdef CONFIG_SPARSEMEM
140         .mmap    = spufs_mem_mmap,
141 #endif
142 };
143
144 static int
145 spufs_regs_open(struct inode *inode, struct file *file)
146 {
147         struct spufs_inode_info *i = SPUFS_I(inode);
148         file->private_data = i->i_ctx;
149         return 0;
150 }
151
152 static ssize_t
153 spufs_regs_read(struct file *file, char __user *buffer,
154                 size_t size, loff_t *pos)
155 {
156         struct spu_context *ctx = file->private_data;
157         struct spu_lscsa *lscsa = ctx->csa.lscsa;
158         int ret;
159
160         spu_acquire_saved(ctx);
161
162         ret = simple_read_from_buffer(buffer, size, pos,
163                                       lscsa->gprs, sizeof lscsa->gprs);
164
165         spu_release(ctx);
166         return ret;
167 }
168
169 static ssize_t
170 spufs_regs_write(struct file *file, const char __user *buffer,
171                  size_t size, loff_t *pos)
172 {
173         struct spu_context *ctx = file->private_data;
174         struct spu_lscsa *lscsa = ctx->csa.lscsa;
175         int ret;
176
177         size = min_t(ssize_t, sizeof lscsa->gprs - *pos, size);
178         if (size <= 0)
179                 return -EFBIG;
180         *pos += size;
181
182         spu_acquire_saved(ctx);
183
184         ret = copy_from_user(lscsa->gprs + *pos - size,
185                              buffer, size) ? -EFAULT : size;
186
187         spu_release(ctx);
188         return ret;
189 }
190
191 static struct file_operations spufs_regs_fops = {
192         .open    = spufs_regs_open,
193         .read    = spufs_regs_read,
194         .write   = spufs_regs_write,
195         .llseek  = generic_file_llseek,
196 };
197
198 static ssize_t
199 spufs_fpcr_read(struct file *file, char __user * buffer,
200                 size_t size, loff_t * pos)
201 {
202         struct spu_context *ctx = file->private_data;
203         struct spu_lscsa *lscsa = ctx->csa.lscsa;
204         int ret;
205
206         spu_acquire_saved(ctx);
207
208         ret = simple_read_from_buffer(buffer, size, pos,
209                                       &lscsa->fpcr, sizeof(lscsa->fpcr));
210
211         spu_release(ctx);
212         return ret;
213 }
214
215 static ssize_t
216 spufs_fpcr_write(struct file *file, const char __user * buffer,
217                  size_t size, loff_t * pos)
218 {
219         struct spu_context *ctx = file->private_data;
220         struct spu_lscsa *lscsa = ctx->csa.lscsa;
221         int ret;
222
223         size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
224         if (size <= 0)
225                 return -EFBIG;
226         *pos += size;
227
228         spu_acquire_saved(ctx);
229
230         ret = copy_from_user((char *)&lscsa->fpcr + *pos - size,
231                              buffer, size) ? -EFAULT : size;
232
233         spu_release(ctx);
234         return ret;
235 }
236
237 static struct file_operations spufs_fpcr_fops = {
238         .open = spufs_regs_open,
239         .read = spufs_fpcr_read,
240         .write = spufs_fpcr_write,
241         .llseek = generic_file_llseek,
242 };
243
244 /* generic open function for all pipe-like files */
245 static int spufs_pipe_open(struct inode *inode, struct file *file)
246 {
247         struct spufs_inode_info *i = SPUFS_I(inode);
248         file->private_data = i->i_ctx;
249
250         return nonseekable_open(inode, file);
251 }
252
253 static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
254                         size_t len, loff_t *pos)
255 {
256         struct spu_context *ctx = file->private_data;
257         u32 mbox_data;
258         int ret;
259
260         if (len < 4)
261                 return -EINVAL;
262
263         spu_acquire(ctx);
264         ret = ctx->ops->mbox_read(ctx, &mbox_data);
265         spu_release(ctx);
266
267         if (!ret)
268                 return -EAGAIN;
269
270         if (copy_to_user(buf, &mbox_data, sizeof mbox_data))
271                 return -EFAULT;
272
273         return 4;
274 }
275
276 static struct file_operations spufs_mbox_fops = {
277         .open   = spufs_pipe_open,
278         .read   = spufs_mbox_read,
279 };
280
281 static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
282                         size_t len, loff_t *pos)
283 {
284         struct spu_context *ctx = file->private_data;
285         u32 mbox_stat;
286
287         if (len < 4)
288                 return -EINVAL;
289
290         spu_acquire(ctx);
291
292         mbox_stat = ctx->ops->mbox_stat_read(ctx) & 0xff;
293
294         spu_release(ctx);
295
296         if (copy_to_user(buf, &mbox_stat, sizeof mbox_stat))
297                 return -EFAULT;
298
299         return 4;
300 }
301
302 static struct file_operations spufs_mbox_stat_fops = {
303         .open   = spufs_pipe_open,
304         .read   = spufs_mbox_stat_read,
305 };
306
307 /*
308  * spufs_wait
309  *      Same as wait_event_interruptible(), except that here
310  *      we need to call spu_release(ctx) before sleeping, and
311  *      then spu_acquire(ctx) when awoken.
312  */
313
314 #define spufs_wait(wq, condition)                                       \
315 ({                                                                      \
316         int __ret = 0;                                                  \
317         DEFINE_WAIT(__wait);                                            \
318         for (;;) {                                                      \
319                 prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE);    \
320                 if (condition)                                          \
321                         break;                                          \
322                 if (!signal_pending(current)) {                         \
323                         spu_release(ctx);                               \
324                         schedule();                                     \
325                         spu_acquire(ctx);                               \
326                         continue;                                       \
327                 }                                                       \
328                 __ret = -ERESTARTSYS;                                   \
329                 break;                                                  \
330         }                                                               \
331         finish_wait(&(wq), &__wait);                                    \
332         __ret;                                                          \
333 })
334
335 /* low-level ibox access function */
336 size_t spu_ibox_read(struct spu_context *ctx, u32 *data)
337 {
338         return ctx->ops->ibox_read(ctx, data);
339 }
340
341 static int spufs_ibox_fasync(int fd, struct file *file, int on)
342 {
343         struct spu_context *ctx = file->private_data;
344
345         return fasync_helper(fd, file, on, &ctx->ibox_fasync);
346 }
347
348 /* interrupt-level ibox callback function. */
349 void spufs_ibox_callback(struct spu *spu)
350 {
351         struct spu_context *ctx = spu->ctx;
352
353         wake_up_all(&ctx->ibox_wq);
354         kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN);
355 }
356
357 static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
358                         size_t len, loff_t *pos)
359 {
360         struct spu_context *ctx = file->private_data;
361         u32 ibox_data;
362         ssize_t ret;
363
364         if (len < 4)
365                 return -EINVAL;
366
367         spu_acquire(ctx);
368
369         ret = 0;
370         if (file->f_flags & O_NONBLOCK) {
371                 if (!spu_ibox_read(ctx, &ibox_data))
372                         ret = -EAGAIN;
373         } else {
374                 ret = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
375         }
376
377         spu_release(ctx);
378
379         if (ret)
380                 return ret;
381
382         ret = 4;
383         if (copy_to_user(buf, &ibox_data, sizeof ibox_data))
384                 ret = -EFAULT;
385
386         return ret;
387 }
388
389 static unsigned int spufs_ibox_poll(struct file *file, poll_table *wait)
390 {
391         struct spu_context *ctx = file->private_data;
392         u32 mbox_stat;
393         unsigned int mask;
394
395         spu_acquire(ctx);
396
397         mbox_stat = ctx->ops->mbox_stat_read(ctx);
398
399         spu_release(ctx);
400
401         poll_wait(file, &ctx->ibox_wq, wait);
402
403         mask = 0;
404         if (mbox_stat & 0xff0000)
405                 mask |= POLLIN | POLLRDNORM;
406
407         return mask;
408 }
409
410 static struct file_operations spufs_ibox_fops = {
411         .open   = spufs_pipe_open,
412         .read   = spufs_ibox_read,
413         .poll   = spufs_ibox_poll,
414         .fasync = spufs_ibox_fasync,
415 };
416
417 static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
418                         size_t len, loff_t *pos)
419 {
420         struct spu_context *ctx = file->private_data;
421         u32 ibox_stat;
422
423         if (len < 4)
424                 return -EINVAL;
425
426         spu_acquire(ctx);
427         ibox_stat = (ctx->ops->mbox_stat_read(ctx) >> 16) & 0xff;
428         spu_release(ctx);
429
430         if (copy_to_user(buf, &ibox_stat, sizeof ibox_stat))
431                 return -EFAULT;
432
433         return 4;
434 }
435
436 static struct file_operations spufs_ibox_stat_fops = {
437         .open   = spufs_pipe_open,
438         .read   = spufs_ibox_stat_read,
439 };
440
441 /* low-level mailbox write */
442 size_t spu_wbox_write(struct spu_context *ctx, u32 data)
443 {
444         return ctx->ops->wbox_write(ctx, data);
445 }
446
447 static int spufs_wbox_fasync(int fd, struct file *file, int on)
448 {
449         struct spu_context *ctx = file->private_data;
450         int ret;
451
452         ret = fasync_helper(fd, file, on, &ctx->wbox_fasync);
453
454         return ret;
455 }
456
457 /* interrupt-level wbox callback function. */
458 void spufs_wbox_callback(struct spu *spu)
459 {
460         struct spu_context *ctx = spu->ctx;
461
462         wake_up_all(&ctx->wbox_wq);
463         kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
464 }
465
466 static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
467                         size_t len, loff_t *pos)
468 {
469         struct spu_context *ctx = file->private_data;
470         u32 wbox_data;
471         int ret;
472
473         if (len < 4)
474                 return -EINVAL;
475
476         if (copy_from_user(&wbox_data, buf, sizeof wbox_data))
477                 return -EFAULT;
478
479         spu_acquire(ctx);
480
481         ret = 0;
482         if (file->f_flags & O_NONBLOCK) {
483                 if (!spu_wbox_write(ctx, wbox_data))
484                         ret = -EAGAIN;
485         } else {
486                 ret = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
487         }
488
489         spu_release(ctx);
490
491         return ret ? ret : sizeof wbox_data;
492 }
493
494 static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait)
495 {
496         struct spu_context *ctx = file->private_data;
497         u32 mbox_stat;
498         unsigned int mask;
499
500         spu_acquire(ctx);
501         mbox_stat = ctx->ops->mbox_stat_read(ctx);
502         spu_release(ctx);
503
504         poll_wait(file, &ctx->wbox_wq, wait);
505
506         mask = 0;
507         if (mbox_stat & 0x00ff00)
508                 mask = POLLOUT | POLLWRNORM;
509
510         return mask;
511 }
512
513 static struct file_operations spufs_wbox_fops = {
514         .open   = spufs_pipe_open,
515         .write  = spufs_wbox_write,
516         .poll   = spufs_wbox_poll,
517         .fasync = spufs_wbox_fasync,
518 };
519
520 static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
521                         size_t len, loff_t *pos)
522 {
523         struct spu_context *ctx = file->private_data;
524         u32 wbox_stat;
525
526         if (len < 4)
527                 return -EINVAL;
528
529         spu_acquire(ctx);
530         wbox_stat = (ctx->ops->mbox_stat_read(ctx) >> 8) & 0xff;
531         spu_release(ctx);
532
533         if (copy_to_user(buf, &wbox_stat, sizeof wbox_stat))
534                 return -EFAULT;
535
536         return 4;
537 }
538
539 static struct file_operations spufs_wbox_stat_fops = {
540         .open   = spufs_pipe_open,
541         .read   = spufs_wbox_stat_read,
542 };
543
544 /* interrupt-level stop callback function. */
545 void spufs_stop_callback(struct spu *spu)
546 {
547         struct spu_context *ctx = spu->ctx;
548
549         wake_up_all(&ctx->stop_wq);
550 }
551
552 static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
553 {
554         struct spu *spu;
555         u64 pte_fault;
556
557         *stat = ctx->ops->status_read(ctx);
558         if (ctx->state != SPU_STATE_RUNNABLE)
559                 return 1;
560         spu = ctx->spu;
561         pte_fault = spu->dsisr &
562             (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
563         return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
564 }
565
566 static inline int spu_run_init(struct spu_context *ctx, u32 * npc,
567                                u32 * status)
568 {
569         int ret;
570
571         if ((ret = spu_acquire_runnable(ctx)) != 0)
572                 return ret;
573         ctx->ops->npc_write(ctx, *npc);
574         ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
575         return 0;
576 }
577
578 static inline int spu_run_fini(struct spu_context *ctx, u32 * npc,
579                                u32 * status)
580 {
581         int ret = 0;
582
583         *status = ctx->ops->status_read(ctx);
584         *npc = ctx->ops->npc_read(ctx);
585         spu_release(ctx);
586
587         if (signal_pending(current))
588                 ret = -ERESTARTSYS;
589         if (unlikely(current->ptrace & PT_PTRACED)) {
590                 if ((*status & SPU_STATUS_STOPPED_BY_STOP)
591                     && (*status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
592                         force_sig(SIGTRAP, current);
593                         ret = -ERESTARTSYS;
594                 }
595         }
596         return ret;
597 }
598
599 static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
600                                          u32 *status)
601 {
602         int ret;
603
604         if ((ret = spu_run_fini(ctx, npc, status)) != 0)
605                 return ret;
606         if (*status & (SPU_STATUS_STOPPED_BY_STOP |
607                        SPU_STATUS_STOPPED_BY_HALT)) {
608                 return *status;
609         }
610         if ((ret = spu_run_init(ctx, npc, status)) != 0)
611                 return ret;
612         return 0;
613 }
614
615 static inline int spu_process_events(struct spu_context *ctx)
616 {
617         struct spu *spu = ctx->spu;
618         u64 pte_fault = MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED;
619         int ret = 0;
620
621         if (spu->dsisr & pte_fault)
622                 ret = spu_irq_class_1_bottom(spu);
623         if (spu->class_0_pending)
624                 ret = spu_irq_class_0_bottom(spu);
625         if (!ret && signal_pending(current))
626                 ret = -ERESTARTSYS;
627         return ret;
628 }
629
630 long spufs_run_spu(struct file *file, struct spu_context *ctx,
631                    u32 * npc, u32 * status)
632 {
633         int ret;
634
635         if ((ret = spu_run_init(ctx, npc, status)) != 0)
636                 return ret;
637
638         do {
639                 ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
640                 if (unlikely(ret))
641                         break;
642                 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
643                         ret = spu_reacquire_runnable(ctx, npc, status);
644                         if (ret) {
645                                 return ret;
646                         }
647                         continue;
648                 }
649                 ret = spu_process_events(ctx);
650
651         } while (!ret && !(*status & (SPU_STATUS_STOPPED_BY_STOP |
652                                       SPU_STATUS_STOPPED_BY_HALT)));
653
654         ctx->ops->runcntl_stop(ctx);
655         ret = spu_run_fini(ctx, npc, status);
656         if (!ret)
657                 ret = *status;
658         spu_yield(ctx);
659
660         return ret;
661 }
662
663 static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
664                         size_t len, loff_t *pos)
665 {
666         struct spu_context *ctx = file->private_data;
667         u32 data;
668
669         if (len < 4)
670                 return -EINVAL;
671
672         spu_acquire(ctx);
673         data = ctx->ops->signal1_read(ctx);
674         spu_release(ctx);
675
676         if (copy_to_user(buf, &data, 4))
677                 return -EFAULT;
678
679         return 4;
680 }
681
682 static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
683                         size_t len, loff_t *pos)
684 {
685         struct spu_context *ctx;
686         u32 data;
687
688         ctx = file->private_data;
689
690         if (len < 4)
691                 return -EINVAL;
692
693         if (copy_from_user(&data, buf, 4))
694                 return -EFAULT;
695
696         spu_acquire(ctx);
697         ctx->ops->signal1_write(ctx, data);
698         spu_release(ctx);
699
700         return 4;
701 }
702
703 static struct file_operations spufs_signal1_fops = {
704         .open = spufs_pipe_open,
705         .read = spufs_signal1_read,
706         .write = spufs_signal1_write,
707 };
708
709 static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
710                         size_t len, loff_t *pos)
711 {
712         struct spu_context *ctx;
713         u32 data;
714
715         ctx = file->private_data;
716
717         if (len < 4)
718                 return -EINVAL;
719
720         spu_acquire(ctx);
721         data = ctx->ops->signal2_read(ctx);
722         spu_release(ctx);
723
724         if (copy_to_user(buf, &data, 4))
725                 return -EFAULT;
726
727         return 4;
728 }
729
730 static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
731                         size_t len, loff_t *pos)
732 {
733         struct spu_context *ctx;
734         u32 data;
735
736         ctx = file->private_data;
737
738         if (len < 4)
739                 return -EINVAL;
740
741         if (copy_from_user(&data, buf, 4))
742                 return -EFAULT;
743
744         spu_acquire(ctx);
745         ctx->ops->signal2_write(ctx, data);
746         spu_release(ctx);
747
748         return 4;
749 }
750
751 static struct file_operations spufs_signal2_fops = {
752         .open = spufs_pipe_open,
753         .read = spufs_signal2_read,
754         .write = spufs_signal2_write,
755 };
756
757 static void spufs_signal1_type_set(void *data, u64 val)
758 {
759         struct spu_context *ctx = data;
760
761         spu_acquire(ctx);
762         ctx->ops->signal1_type_set(ctx, val);
763         spu_release(ctx);
764 }
765
766 static u64 spufs_signal1_type_get(void *data)
767 {
768         struct spu_context *ctx = data;
769         u64 ret;
770
771         spu_acquire(ctx);
772         ret = ctx->ops->signal1_type_get(ctx);
773         spu_release(ctx);
774
775         return ret;
776 }
777 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
778                                         spufs_signal1_type_set, "%llu");
779
780 static void spufs_signal2_type_set(void *data, u64 val)
781 {
782         struct spu_context *ctx = data;
783
784         spu_acquire(ctx);
785         ctx->ops->signal2_type_set(ctx, val);
786         spu_release(ctx);
787 }
788
789 static u64 spufs_signal2_type_get(void *data)
790 {
791         struct spu_context *ctx = data;
792         u64 ret;
793
794         spu_acquire(ctx);
795         ret = ctx->ops->signal2_type_get(ctx);
796         spu_release(ctx);
797
798         return ret;
799 }
800 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
801                                         spufs_signal2_type_set, "%llu");
802
803 static void spufs_npc_set(void *data, u64 val)
804 {
805         struct spu_context *ctx = data;
806         spu_acquire(ctx);
807         ctx->ops->npc_write(ctx, val);
808         spu_release(ctx);
809 }
810
811 static u64 spufs_npc_get(void *data)
812 {
813         struct spu_context *ctx = data;
814         u64 ret;
815         spu_acquire(ctx);
816         ret = ctx->ops->npc_read(ctx);
817         spu_release(ctx);
818         return ret;
819 }
820 DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, "%llx\n")
821
822 static void spufs_decr_set(void *data, u64 val)
823 {
824         struct spu_context *ctx = data;
825         struct spu_lscsa *lscsa = ctx->csa.lscsa;
826         spu_acquire_saved(ctx);
827         lscsa->decr.slot[0] = (u32) val;
828         spu_release(ctx);
829 }
830
831 static u64 spufs_decr_get(void *data)
832 {
833         struct spu_context *ctx = data;
834         struct spu_lscsa *lscsa = ctx->csa.lscsa;
835         u64 ret;
836         spu_acquire_saved(ctx);
837         ret = lscsa->decr.slot[0];
838         spu_release(ctx);
839         return ret;
840 }
841 DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
842                         "%llx\n")
843
844 static void spufs_decr_status_set(void *data, u64 val)
845 {
846         struct spu_context *ctx = data;
847         struct spu_lscsa *lscsa = ctx->csa.lscsa;
848         spu_acquire_saved(ctx);
849         lscsa->decr_status.slot[0] = (u32) val;
850         spu_release(ctx);
851 }
852
853 static u64 spufs_decr_status_get(void *data)
854 {
855         struct spu_context *ctx = data;
856         struct spu_lscsa *lscsa = ctx->csa.lscsa;
857         u64 ret;
858         spu_acquire_saved(ctx);
859         ret = lscsa->decr_status.slot[0];
860         spu_release(ctx);
861         return ret;
862 }
863 DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
864                         spufs_decr_status_set, "%llx\n")
865
866 static void spufs_spu_tag_mask_set(void *data, u64 val)
867 {
868         struct spu_context *ctx = data;
869         struct spu_lscsa *lscsa = ctx->csa.lscsa;
870         spu_acquire_saved(ctx);
871         lscsa->tag_mask.slot[0] = (u32) val;
872         spu_release(ctx);
873 }
874
875 static u64 spufs_spu_tag_mask_get(void *data)
876 {
877         struct spu_context *ctx = data;
878         struct spu_lscsa *lscsa = ctx->csa.lscsa;
879         u64 ret;
880         spu_acquire_saved(ctx);
881         ret = lscsa->tag_mask.slot[0];
882         spu_release(ctx);
883         return ret;
884 }
885 DEFINE_SIMPLE_ATTRIBUTE(spufs_spu_tag_mask_ops, spufs_spu_tag_mask_get,
886                         spufs_spu_tag_mask_set, "%llx\n")
887
888 static void spufs_event_mask_set(void *data, u64 val)
889 {
890         struct spu_context *ctx = data;
891         struct spu_lscsa *lscsa = ctx->csa.lscsa;
892         spu_acquire_saved(ctx);
893         lscsa->event_mask.slot[0] = (u32) val;
894         spu_release(ctx);
895 }
896
897 static u64 spufs_event_mask_get(void *data)
898 {
899         struct spu_context *ctx = data;
900         struct spu_lscsa *lscsa = ctx->csa.lscsa;
901         u64 ret;
902         spu_acquire_saved(ctx);
903         ret = lscsa->event_mask.slot[0];
904         spu_release(ctx);
905         return ret;
906 }
907 DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
908                         spufs_event_mask_set, "%llx\n")
909
910 static void spufs_srr0_set(void *data, u64 val)
911 {
912         struct spu_context *ctx = data;
913         struct spu_lscsa *lscsa = ctx->csa.lscsa;
914         spu_acquire_saved(ctx);
915         lscsa->srr0.slot[0] = (u32) val;
916         spu_release(ctx);
917 }
918
919 static u64 spufs_srr0_get(void *data)
920 {
921         struct spu_context *ctx = data;
922         struct spu_lscsa *lscsa = ctx->csa.lscsa;
923         u64 ret;
924         spu_acquire_saved(ctx);
925         ret = lscsa->srr0.slot[0];
926         spu_release(ctx);
927         return ret;
928 }
929 DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
930                         "%llx\n")
931
932 struct tree_descr spufs_dir_contents[] = {
933         { "mem",  &spufs_mem_fops,  0666, },
934         { "regs", &spufs_regs_fops,  0666, },
935         { "mbox", &spufs_mbox_fops, 0444, },
936         { "ibox", &spufs_ibox_fops, 0444, },
937         { "wbox", &spufs_wbox_fops, 0222, },
938         { "mbox_stat", &spufs_mbox_stat_fops, 0444, },
939         { "ibox_stat", &spufs_ibox_stat_fops, 0444, },
940         { "wbox_stat", &spufs_wbox_stat_fops, 0444, },
941         { "signal1", &spufs_signal1_fops, 0666, },
942         { "signal2", &spufs_signal2_fops, 0666, },
943         { "signal1_type", &spufs_signal1_type, 0666, },
944         { "signal2_type", &spufs_signal2_type, 0666, },
945         { "npc", &spufs_npc_ops, 0666, },
946         { "fpcr", &spufs_fpcr_fops, 0666, },
947         { "decr", &spufs_decr_ops, 0666, },
948         { "decr_status", &spufs_decr_status_ops, 0666, },
949         { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, },
950         { "event_mask", &spufs_event_mask_ops, 0666, },
951         { "srr0", &spufs_srr0_ops, 0666, },
952         {},
953 };