[PATCH] spufs: serialize sys_spu_run per spu
[powerpc.git] / 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         unsigned int mask;
393
394         poll_wait(file, &ctx->ibox_wq, wait);
395
396         spu_acquire(ctx);
397         mask = ctx->ops->mbox_stat_poll(ctx, POLLIN | POLLRDNORM);
398         spu_release(ctx);
399
400         return mask;
401 }
402
403 static struct file_operations spufs_ibox_fops = {
404         .open   = spufs_pipe_open,
405         .read   = spufs_ibox_read,
406         .poll   = spufs_ibox_poll,
407         .fasync = spufs_ibox_fasync,
408 };
409
410 static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
411                         size_t len, loff_t *pos)
412 {
413         struct spu_context *ctx = file->private_data;
414         u32 ibox_stat;
415
416         if (len < 4)
417                 return -EINVAL;
418
419         spu_acquire(ctx);
420         ibox_stat = (ctx->ops->mbox_stat_read(ctx) >> 16) & 0xff;
421         spu_release(ctx);
422
423         if (copy_to_user(buf, &ibox_stat, sizeof ibox_stat))
424                 return -EFAULT;
425
426         return 4;
427 }
428
429 static struct file_operations spufs_ibox_stat_fops = {
430         .open   = spufs_pipe_open,
431         .read   = spufs_ibox_stat_read,
432 };
433
434 /* low-level mailbox write */
435 size_t spu_wbox_write(struct spu_context *ctx, u32 data)
436 {
437         return ctx->ops->wbox_write(ctx, data);
438 }
439
440 static int spufs_wbox_fasync(int fd, struct file *file, int on)
441 {
442         struct spu_context *ctx = file->private_data;
443         int ret;
444
445         ret = fasync_helper(fd, file, on, &ctx->wbox_fasync);
446
447         return ret;
448 }
449
450 /* interrupt-level wbox callback function. */
451 void spufs_wbox_callback(struct spu *spu)
452 {
453         struct spu_context *ctx = spu->ctx;
454
455         wake_up_all(&ctx->wbox_wq);
456         kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
457 }
458
459 static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
460                         size_t len, loff_t *pos)
461 {
462         struct spu_context *ctx = file->private_data;
463         u32 wbox_data;
464         int ret;
465
466         if (len < 4)
467                 return -EINVAL;
468
469         if (copy_from_user(&wbox_data, buf, sizeof wbox_data))
470                 return -EFAULT;
471
472         spu_acquire(ctx);
473
474         ret = 0;
475         if (file->f_flags & O_NONBLOCK) {
476                 if (!spu_wbox_write(ctx, wbox_data))
477                         ret = -EAGAIN;
478         } else {
479                 ret = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
480         }
481
482         spu_release(ctx);
483
484         return ret ? ret : sizeof wbox_data;
485 }
486
487 static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait)
488 {
489         struct spu_context *ctx = file->private_data;
490         unsigned int mask;
491
492         poll_wait(file, &ctx->wbox_wq, wait);
493
494         spu_acquire(ctx);
495         mask = ctx->ops->mbox_stat_poll(ctx, POLLOUT | POLLWRNORM);
496         spu_release(ctx);
497
498         return mask;
499 }
500
501 static struct file_operations spufs_wbox_fops = {
502         .open   = spufs_pipe_open,
503         .write  = spufs_wbox_write,
504         .poll   = spufs_wbox_poll,
505         .fasync = spufs_wbox_fasync,
506 };
507
508 static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
509                         size_t len, loff_t *pos)
510 {
511         struct spu_context *ctx = file->private_data;
512         u32 wbox_stat;
513
514         if (len < 4)
515                 return -EINVAL;
516
517         spu_acquire(ctx);
518         wbox_stat = (ctx->ops->mbox_stat_read(ctx) >> 8) & 0xff;
519         spu_release(ctx);
520
521         if (copy_to_user(buf, &wbox_stat, sizeof wbox_stat))
522                 return -EFAULT;
523
524         return 4;
525 }
526
527 static struct file_operations spufs_wbox_stat_fops = {
528         .open   = spufs_pipe_open,
529         .read   = spufs_wbox_stat_read,
530 };
531
532 /* interrupt-level stop callback function. */
533 void spufs_stop_callback(struct spu *spu)
534 {
535         struct spu_context *ctx = spu->ctx;
536
537         wake_up_all(&ctx->stop_wq);
538 }
539
540 static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
541 {
542         struct spu *spu;
543         u64 pte_fault;
544
545         *stat = ctx->ops->status_read(ctx);
546         if (ctx->state != SPU_STATE_RUNNABLE)
547                 return 1;
548         spu = ctx->spu;
549         pte_fault = spu->dsisr &
550             (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
551         return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
552 }
553
554 static inline int spu_run_init(struct spu_context *ctx, u32 * npc,
555                                u32 * status)
556 {
557         int ret;
558
559         if ((ret = spu_acquire_runnable(ctx)) != 0)
560                 return ret;
561         ctx->ops->npc_write(ctx, *npc);
562         ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
563         return 0;
564 }
565
566 static inline int spu_run_fini(struct spu_context *ctx, u32 * npc,
567                                u32 * status)
568 {
569         int ret = 0;
570
571         *status = ctx->ops->status_read(ctx);
572         *npc = ctx->ops->npc_read(ctx);
573         spu_release(ctx);
574
575         if (signal_pending(current))
576                 ret = -ERESTARTSYS;
577         if (unlikely(current->ptrace & PT_PTRACED)) {
578                 if ((*status & SPU_STATUS_STOPPED_BY_STOP)
579                     && (*status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
580                         force_sig(SIGTRAP, current);
581                         ret = -ERESTARTSYS;
582                 }
583         }
584         return ret;
585 }
586
587 static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
588                                          u32 *status)
589 {
590         int ret;
591
592         if ((ret = spu_run_fini(ctx, npc, status)) != 0)
593                 return ret;
594         if (*status & (SPU_STATUS_STOPPED_BY_STOP |
595                        SPU_STATUS_STOPPED_BY_HALT)) {
596                 return *status;
597         }
598         if ((ret = spu_run_init(ctx, npc, status)) != 0)
599                 return ret;
600         return 0;
601 }
602
603 static inline int spu_process_events(struct spu_context *ctx)
604 {
605         struct spu *spu = ctx->spu;
606         u64 pte_fault = MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED;
607         int ret = 0;
608
609         if (spu->dsisr & pte_fault)
610                 ret = spu_irq_class_1_bottom(spu);
611         if (spu->class_0_pending)
612                 ret = spu_irq_class_0_bottom(spu);
613         if (!ret && signal_pending(current))
614                 ret = -ERESTARTSYS;
615         return ret;
616 }
617
618 long spufs_run_spu(struct file *file, struct spu_context *ctx,
619                    u32 * npc, u32 * status)
620 {
621         int ret;
622
623         if (down_interruptible(&ctx->run_sema))
624                 return -ERESTARTSYS;
625
626         ret = spu_run_init(ctx, npc, status);
627         if (ret)
628                 goto out;
629
630         do {
631                 ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
632                 if (unlikely(ret))
633                         break;
634                 if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
635                         ret = spu_reacquire_runnable(ctx, npc, status);
636                         if (ret)
637                                 goto out;
638                         continue;
639                 }
640                 ret = spu_process_events(ctx);
641
642         } while (!ret && !(*status & (SPU_STATUS_STOPPED_BY_STOP |
643                                       SPU_STATUS_STOPPED_BY_HALT)));
644
645         ctx->ops->runcntl_stop(ctx);
646         ret = spu_run_fini(ctx, npc, status);
647         if (!ret)
648                 ret = *status;
649         spu_yield(ctx);
650
651 out:
652         up(&ctx->run_sema);
653         return ret;
654 }
655
656 static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
657                         size_t len, loff_t *pos)
658 {
659         struct spu_context *ctx = file->private_data;
660         u32 data;
661
662         if (len < 4)
663                 return -EINVAL;
664
665         spu_acquire(ctx);
666         data = ctx->ops->signal1_read(ctx);
667         spu_release(ctx);
668
669         if (copy_to_user(buf, &data, 4))
670                 return -EFAULT;
671
672         return 4;
673 }
674
675 static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
676                         size_t len, loff_t *pos)
677 {
678         struct spu_context *ctx;
679         u32 data;
680
681         ctx = file->private_data;
682
683         if (len < 4)
684                 return -EINVAL;
685
686         if (copy_from_user(&data, buf, 4))
687                 return -EFAULT;
688
689         spu_acquire(ctx);
690         ctx->ops->signal1_write(ctx, data);
691         spu_release(ctx);
692
693         return 4;
694 }
695
696 static struct file_operations spufs_signal1_fops = {
697         .open = spufs_pipe_open,
698         .read = spufs_signal1_read,
699         .write = spufs_signal1_write,
700 };
701
702 static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
703                         size_t len, loff_t *pos)
704 {
705         struct spu_context *ctx;
706         u32 data;
707
708         ctx = file->private_data;
709
710         if (len < 4)
711                 return -EINVAL;
712
713         spu_acquire(ctx);
714         data = ctx->ops->signal2_read(ctx);
715         spu_release(ctx);
716
717         if (copy_to_user(buf, &data, 4))
718                 return -EFAULT;
719
720         return 4;
721 }
722
723 static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
724                         size_t len, loff_t *pos)
725 {
726         struct spu_context *ctx;
727         u32 data;
728
729         ctx = file->private_data;
730
731         if (len < 4)
732                 return -EINVAL;
733
734         if (copy_from_user(&data, buf, 4))
735                 return -EFAULT;
736
737         spu_acquire(ctx);
738         ctx->ops->signal2_write(ctx, data);
739         spu_release(ctx);
740
741         return 4;
742 }
743
744 static struct file_operations spufs_signal2_fops = {
745         .open = spufs_pipe_open,
746         .read = spufs_signal2_read,
747         .write = spufs_signal2_write,
748 };
749
750 static void spufs_signal1_type_set(void *data, u64 val)
751 {
752         struct spu_context *ctx = data;
753
754         spu_acquire(ctx);
755         ctx->ops->signal1_type_set(ctx, val);
756         spu_release(ctx);
757 }
758
759 static u64 spufs_signal1_type_get(void *data)
760 {
761         struct spu_context *ctx = data;
762         u64 ret;
763
764         spu_acquire(ctx);
765         ret = ctx->ops->signal1_type_get(ctx);
766         spu_release(ctx);
767
768         return ret;
769 }
770 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
771                                         spufs_signal1_type_set, "%llu");
772
773 static void spufs_signal2_type_set(void *data, u64 val)
774 {
775         struct spu_context *ctx = data;
776
777         spu_acquire(ctx);
778         ctx->ops->signal2_type_set(ctx, val);
779         spu_release(ctx);
780 }
781
782 static u64 spufs_signal2_type_get(void *data)
783 {
784         struct spu_context *ctx = data;
785         u64 ret;
786
787         spu_acquire(ctx);
788         ret = ctx->ops->signal2_type_get(ctx);
789         spu_release(ctx);
790
791         return ret;
792 }
793 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
794                                         spufs_signal2_type_set, "%llu");
795
796 static void spufs_npc_set(void *data, u64 val)
797 {
798         struct spu_context *ctx = data;
799         spu_acquire(ctx);
800         ctx->ops->npc_write(ctx, val);
801         spu_release(ctx);
802 }
803
804 static u64 spufs_npc_get(void *data)
805 {
806         struct spu_context *ctx = data;
807         u64 ret;
808         spu_acquire(ctx);
809         ret = ctx->ops->npc_read(ctx);
810         spu_release(ctx);
811         return ret;
812 }
813 DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, "%llx\n")
814
815 static void spufs_decr_set(void *data, u64 val)
816 {
817         struct spu_context *ctx = data;
818         struct spu_lscsa *lscsa = ctx->csa.lscsa;
819         spu_acquire_saved(ctx);
820         lscsa->decr.slot[0] = (u32) val;
821         spu_release(ctx);
822 }
823
824 static u64 spufs_decr_get(void *data)
825 {
826         struct spu_context *ctx = data;
827         struct spu_lscsa *lscsa = ctx->csa.lscsa;
828         u64 ret;
829         spu_acquire_saved(ctx);
830         ret = lscsa->decr.slot[0];
831         spu_release(ctx);
832         return ret;
833 }
834 DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
835                         "%llx\n")
836
837 static void spufs_decr_status_set(void *data, u64 val)
838 {
839         struct spu_context *ctx = data;
840         struct spu_lscsa *lscsa = ctx->csa.lscsa;
841         spu_acquire_saved(ctx);
842         lscsa->decr_status.slot[0] = (u32) val;
843         spu_release(ctx);
844 }
845
846 static u64 spufs_decr_status_get(void *data)
847 {
848         struct spu_context *ctx = data;
849         struct spu_lscsa *lscsa = ctx->csa.lscsa;
850         u64 ret;
851         spu_acquire_saved(ctx);
852         ret = lscsa->decr_status.slot[0];
853         spu_release(ctx);
854         return ret;
855 }
856 DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
857                         spufs_decr_status_set, "%llx\n")
858
859 static void spufs_spu_tag_mask_set(void *data, u64 val)
860 {
861         struct spu_context *ctx = data;
862         struct spu_lscsa *lscsa = ctx->csa.lscsa;
863         spu_acquire_saved(ctx);
864         lscsa->tag_mask.slot[0] = (u32) val;
865         spu_release(ctx);
866 }
867
868 static u64 spufs_spu_tag_mask_get(void *data)
869 {
870         struct spu_context *ctx = data;
871         struct spu_lscsa *lscsa = ctx->csa.lscsa;
872         u64 ret;
873         spu_acquire_saved(ctx);
874         ret = lscsa->tag_mask.slot[0];
875         spu_release(ctx);
876         return ret;
877 }
878 DEFINE_SIMPLE_ATTRIBUTE(spufs_spu_tag_mask_ops, spufs_spu_tag_mask_get,
879                         spufs_spu_tag_mask_set, "%llx\n")
880
881 static void spufs_event_mask_set(void *data, u64 val)
882 {
883         struct spu_context *ctx = data;
884         struct spu_lscsa *lscsa = ctx->csa.lscsa;
885         spu_acquire_saved(ctx);
886         lscsa->event_mask.slot[0] = (u32) val;
887         spu_release(ctx);
888 }
889
890 static u64 spufs_event_mask_get(void *data)
891 {
892         struct spu_context *ctx = data;
893         struct spu_lscsa *lscsa = ctx->csa.lscsa;
894         u64 ret;
895         spu_acquire_saved(ctx);
896         ret = lscsa->event_mask.slot[0];
897         spu_release(ctx);
898         return ret;
899 }
900 DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
901                         spufs_event_mask_set, "%llx\n")
902
903 static void spufs_srr0_set(void *data, u64 val)
904 {
905         struct spu_context *ctx = data;
906         struct spu_lscsa *lscsa = ctx->csa.lscsa;
907         spu_acquire_saved(ctx);
908         lscsa->srr0.slot[0] = (u32) val;
909         spu_release(ctx);
910 }
911
912 static u64 spufs_srr0_get(void *data)
913 {
914         struct spu_context *ctx = data;
915         struct spu_lscsa *lscsa = ctx->csa.lscsa;
916         u64 ret;
917         spu_acquire_saved(ctx);
918         ret = lscsa->srr0.slot[0];
919         spu_release(ctx);
920         return ret;
921 }
922 DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
923                         "%llx\n")
924
925 struct tree_descr spufs_dir_contents[] = {
926         { "mem",  &spufs_mem_fops,  0666, },
927         { "regs", &spufs_regs_fops,  0666, },
928         { "mbox", &spufs_mbox_fops, 0444, },
929         { "ibox", &spufs_ibox_fops, 0444, },
930         { "wbox", &spufs_wbox_fops, 0222, },
931         { "mbox_stat", &spufs_mbox_stat_fops, 0444, },
932         { "ibox_stat", &spufs_ibox_stat_fops, 0444, },
933         { "wbox_stat", &spufs_wbox_stat_fops, 0444, },
934         { "signal1", &spufs_signal1_fops, 0666, },
935         { "signal2", &spufs_signal2_fops, 0666, },
936         { "signal1_type", &spufs_signal1_type, 0666, },
937         { "signal2_type", &spufs_signal2_type, 0666, },
938         { "npc", &spufs_npc_ops, 0666, },
939         { "fpcr", &spufs_fpcr_fops, 0666, },
940         { "decr", &spufs_decr_ops, 0666, },
941         { "decr_status", &spufs_decr_status_ops, 0666, },
942         { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, },
943         { "event_mask", &spufs_event_mask_ops, 0666, },
944         { "srr0", &spufs_srr0_ops, 0666, },
945         {},
946 };