2 * SPU file system -- file contents
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
6 * Author: Arnd Bergmann <arndb@de.ibm.com>
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)
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.
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.
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>
31 #include <asm/semaphore.h>
33 #include <asm/uaccess.h>
39 spufs_mem_open(struct inode
*inode
, struct file
*file
)
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
;
48 spufs_mem_read(struct file
*file
, char __user
*buffer
,
49 size_t size
, loff_t
*pos
)
51 struct spu_context
*ctx
= file
->private_data
;
57 local_store
= ctx
->ops
->get_ls(ctx
);
58 ret
= simple_read_from_buffer(buffer
, size
, pos
, local_store
, LS_SIZE
);
65 spufs_mem_write(struct file
*file
, const char __user
*buffer
,
66 size_t size
, loff_t
*pos
)
68 struct spu_context
*ctx
= file
->private_data
;
72 size
= min_t(ssize_t
, LS_SIZE
- *pos
, size
);
79 local_store
= ctx
->ops
->get_ls(ctx
);
80 ret
= copy_from_user(local_store
+ *pos
- size
,
81 buffer
, size
) ? -EFAULT
: size
;
87 #ifdef CONFIG_SPARSEMEM
89 spufs_mem_mmap_nopage(struct vm_area_struct
*vma
,
90 unsigned long address
, int *type
)
92 struct page
*page
= NOPAGE_SIGBUS
;
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
;
100 if (ctx
->state
== SPU_STATE_SAVED
)
101 page
= vmalloc_to_page(ctx
->csa
.lscsa
->ls
+ offset
);
103 page
= pfn_to_page((ctx
->spu
->local_store_phys
+ offset
)
109 *type
= VM_FAULT_MINOR
;
111 page_cache_get(page
);
115 static struct vm_operations_struct spufs_mem_mmap_vmops
= {
116 .nopage
= spufs_mem_mmap_nopage
,
120 spufs_mem_mmap(struct file
*file
, struct vm_area_struct
*vma
)
122 if (!(vma
->vm_flags
& VM_SHARED
))
126 vma
->vm_page_prot
= __pgprot(pgprot_val(vma
->vm_page_prot
)
129 vma
->vm_ops
= &spufs_mem_mmap_vmops
;
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
,
145 spufs_regs_open(struct inode
*inode
, struct file
*file
)
147 struct spufs_inode_info
*i
= SPUFS_I(inode
);
148 file
->private_data
= i
->i_ctx
;
153 spufs_regs_read(struct file
*file
, char __user
*buffer
,
154 size_t size
, loff_t
*pos
)
156 struct spu_context
*ctx
= file
->private_data
;
157 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
160 spu_acquire_saved(ctx
);
162 ret
= simple_read_from_buffer(buffer
, size
, pos
,
163 lscsa
->gprs
, sizeof lscsa
->gprs
);
170 spufs_regs_write(struct file
*file
, const char __user
*buffer
,
171 size_t size
, loff_t
*pos
)
173 struct spu_context
*ctx
= file
->private_data
;
174 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
177 size
= min_t(ssize_t
, sizeof lscsa
->gprs
- *pos
, size
);
182 spu_acquire_saved(ctx
);
184 ret
= copy_from_user(lscsa
->gprs
+ *pos
- size
,
185 buffer
, size
) ? -EFAULT
: size
;
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
,
199 spufs_fpcr_read(struct file
*file
, char __user
* buffer
,
200 size_t size
, loff_t
* pos
)
202 struct spu_context
*ctx
= file
->private_data
;
203 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
206 spu_acquire_saved(ctx
);
208 ret
= simple_read_from_buffer(buffer
, size
, pos
,
209 &lscsa
->fpcr
, sizeof(lscsa
->fpcr
));
216 spufs_fpcr_write(struct file
*file
, const char __user
* buffer
,
217 size_t size
, loff_t
* pos
)
219 struct spu_context
*ctx
= file
->private_data
;
220 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
223 size
= min_t(ssize_t
, sizeof(lscsa
->fpcr
) - *pos
, size
);
228 spu_acquire_saved(ctx
);
230 ret
= copy_from_user((char *)&lscsa
->fpcr
+ *pos
- size
,
231 buffer
, size
) ? -EFAULT
: size
;
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
,
244 /* generic open function for all pipe-like files */
245 static int spufs_pipe_open(struct inode
*inode
, struct file
*file
)
247 struct spufs_inode_info
*i
= SPUFS_I(inode
);
248 file
->private_data
= i
->i_ctx
;
250 return nonseekable_open(inode
, file
);
253 static ssize_t
spufs_mbox_read(struct file
*file
, char __user
*buf
,
254 size_t len
, loff_t
*pos
)
256 struct spu_context
*ctx
= file
->private_data
;
264 ret
= ctx
->ops
->mbox_read(ctx
, &mbox_data
);
270 if (copy_to_user(buf
, &mbox_data
, sizeof mbox_data
))
276 static struct file_operations spufs_mbox_fops
= {
277 .open
= spufs_pipe_open
,
278 .read
= spufs_mbox_read
,
281 static ssize_t
spufs_mbox_stat_read(struct file
*file
, char __user
*buf
,
282 size_t len
, loff_t
*pos
)
284 struct spu_context
*ctx
= file
->private_data
;
292 mbox_stat
= ctx
->ops
->mbox_stat_read(ctx
) & 0xff;
296 if (copy_to_user(buf
, &mbox_stat
, sizeof mbox_stat
))
302 static struct file_operations spufs_mbox_stat_fops
= {
303 .open
= spufs_pipe_open
,
304 .read
= spufs_mbox_stat_read
,
307 /* low-level ibox access function */
308 size_t spu_ibox_read(struct spu_context
*ctx
, u32
*data
)
310 return ctx
->ops
->ibox_read(ctx
, data
);
313 static int spufs_ibox_fasync(int fd
, struct file
*file
, int on
)
315 struct spu_context
*ctx
= file
->private_data
;
317 return fasync_helper(fd
, file
, on
, &ctx
->ibox_fasync
);
320 /* interrupt-level ibox callback function. */
321 void spufs_ibox_callback(struct spu
*spu
)
323 struct spu_context
*ctx
= spu
->ctx
;
325 wake_up_all(&ctx
->ibox_wq
);
326 kill_fasync(&ctx
->ibox_fasync
, SIGIO
, POLLIN
);
329 static ssize_t
spufs_ibox_read(struct file
*file
, char __user
*buf
,
330 size_t len
, loff_t
*pos
)
332 struct spu_context
*ctx
= file
->private_data
;
342 if (file
->f_flags
& O_NONBLOCK
) {
343 if (!spu_ibox_read(ctx
, &ibox_data
))
346 ret
= spufs_wait(ctx
->ibox_wq
, spu_ibox_read(ctx
, &ibox_data
));
355 if (copy_to_user(buf
, &ibox_data
, sizeof ibox_data
))
361 static unsigned int spufs_ibox_poll(struct file
*file
, poll_table
*wait
)
363 struct spu_context
*ctx
= file
->private_data
;
366 poll_wait(file
, &ctx
->ibox_wq
, wait
);
369 mask
= ctx
->ops
->mbox_stat_poll(ctx
, POLLIN
| POLLRDNORM
);
375 static struct file_operations spufs_ibox_fops
= {
376 .open
= spufs_pipe_open
,
377 .read
= spufs_ibox_read
,
378 .poll
= spufs_ibox_poll
,
379 .fasync
= spufs_ibox_fasync
,
382 static ssize_t
spufs_ibox_stat_read(struct file
*file
, char __user
*buf
,
383 size_t len
, loff_t
*pos
)
385 struct spu_context
*ctx
= file
->private_data
;
392 ibox_stat
= (ctx
->ops
->mbox_stat_read(ctx
) >> 16) & 0xff;
395 if (copy_to_user(buf
, &ibox_stat
, sizeof ibox_stat
))
401 static struct file_operations spufs_ibox_stat_fops
= {
402 .open
= spufs_pipe_open
,
403 .read
= spufs_ibox_stat_read
,
406 /* low-level mailbox write */
407 size_t spu_wbox_write(struct spu_context
*ctx
, u32 data
)
409 return ctx
->ops
->wbox_write(ctx
, data
);
412 static int spufs_wbox_fasync(int fd
, struct file
*file
, int on
)
414 struct spu_context
*ctx
= file
->private_data
;
417 ret
= fasync_helper(fd
, file
, on
, &ctx
->wbox_fasync
);
422 /* interrupt-level wbox callback function. */
423 void spufs_wbox_callback(struct spu
*spu
)
425 struct spu_context
*ctx
= spu
->ctx
;
427 wake_up_all(&ctx
->wbox_wq
);
428 kill_fasync(&ctx
->wbox_fasync
, SIGIO
, POLLOUT
);
431 static ssize_t
spufs_wbox_write(struct file
*file
, const char __user
*buf
,
432 size_t len
, loff_t
*pos
)
434 struct spu_context
*ctx
= file
->private_data
;
441 if (copy_from_user(&wbox_data
, buf
, sizeof wbox_data
))
447 if (file
->f_flags
& O_NONBLOCK
) {
448 if (!spu_wbox_write(ctx
, wbox_data
))
451 ret
= spufs_wait(ctx
->wbox_wq
, spu_wbox_write(ctx
, wbox_data
));
456 return ret
? ret
: sizeof wbox_data
;
459 static unsigned int spufs_wbox_poll(struct file
*file
, poll_table
*wait
)
461 struct spu_context
*ctx
= file
->private_data
;
464 poll_wait(file
, &ctx
->wbox_wq
, wait
);
467 mask
= ctx
->ops
->mbox_stat_poll(ctx
, POLLOUT
| POLLWRNORM
);
473 static struct file_operations spufs_wbox_fops
= {
474 .open
= spufs_pipe_open
,
475 .write
= spufs_wbox_write
,
476 .poll
= spufs_wbox_poll
,
477 .fasync
= spufs_wbox_fasync
,
480 static ssize_t
spufs_wbox_stat_read(struct file
*file
, char __user
*buf
,
481 size_t len
, loff_t
*pos
)
483 struct spu_context
*ctx
= file
->private_data
;
490 wbox_stat
= (ctx
->ops
->mbox_stat_read(ctx
) >> 8) & 0xff;
493 if (copy_to_user(buf
, &wbox_stat
, sizeof wbox_stat
))
499 static struct file_operations spufs_wbox_stat_fops
= {
500 .open
= spufs_pipe_open
,
501 .read
= spufs_wbox_stat_read
,
504 static ssize_t
spufs_signal1_read(struct file
*file
, char __user
*buf
,
505 size_t len
, loff_t
*pos
)
507 struct spu_context
*ctx
= file
->private_data
;
514 data
= ctx
->ops
->signal1_read(ctx
);
517 if (copy_to_user(buf
, &data
, 4))
523 static ssize_t
spufs_signal1_write(struct file
*file
, const char __user
*buf
,
524 size_t len
, loff_t
*pos
)
526 struct spu_context
*ctx
;
529 ctx
= file
->private_data
;
534 if (copy_from_user(&data
, buf
, 4))
538 ctx
->ops
->signal1_write(ctx
, data
);
544 static struct file_operations spufs_signal1_fops
= {
545 .open
= spufs_pipe_open
,
546 .read
= spufs_signal1_read
,
547 .write
= spufs_signal1_write
,
550 static ssize_t
spufs_signal2_read(struct file
*file
, char __user
*buf
,
551 size_t len
, loff_t
*pos
)
553 struct spu_context
*ctx
;
556 ctx
= file
->private_data
;
562 data
= ctx
->ops
->signal2_read(ctx
);
565 if (copy_to_user(buf
, &data
, 4))
571 static ssize_t
spufs_signal2_write(struct file
*file
, const char __user
*buf
,
572 size_t len
, loff_t
*pos
)
574 struct spu_context
*ctx
;
577 ctx
= file
->private_data
;
582 if (copy_from_user(&data
, buf
, 4))
586 ctx
->ops
->signal2_write(ctx
, data
);
592 static struct file_operations spufs_signal2_fops
= {
593 .open
= spufs_pipe_open
,
594 .read
= spufs_signal2_read
,
595 .write
= spufs_signal2_write
,
598 static void spufs_signal1_type_set(void *data
, u64 val
)
600 struct spu_context
*ctx
= data
;
603 ctx
->ops
->signal1_type_set(ctx
, val
);
607 static u64
spufs_signal1_type_get(void *data
)
609 struct spu_context
*ctx
= data
;
613 ret
= ctx
->ops
->signal1_type_get(ctx
);
618 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type
, spufs_signal1_type_get
,
619 spufs_signal1_type_set
, "%llu");
621 static void spufs_signal2_type_set(void *data
, u64 val
)
623 struct spu_context
*ctx
= data
;
626 ctx
->ops
->signal2_type_set(ctx
, val
);
630 static u64
spufs_signal2_type_get(void *data
)
632 struct spu_context
*ctx
= data
;
636 ret
= ctx
->ops
->signal2_type_get(ctx
);
641 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type
, spufs_signal2_type_get
,
642 spufs_signal2_type_set
, "%llu");
644 static void spufs_npc_set(void *data
, u64 val
)
646 struct spu_context
*ctx
= data
;
648 ctx
->ops
->npc_write(ctx
, val
);
652 static u64
spufs_npc_get(void *data
)
654 struct spu_context
*ctx
= data
;
657 ret
= ctx
->ops
->npc_read(ctx
);
661 DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops
, spufs_npc_get
, spufs_npc_set
, "%llx\n")
663 static void spufs_decr_set(void *data
, u64 val
)
665 struct spu_context
*ctx
= data
;
666 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
667 spu_acquire_saved(ctx
);
668 lscsa
->decr
.slot
[0] = (u32
) val
;
672 static u64
spufs_decr_get(void *data
)
674 struct spu_context
*ctx
= data
;
675 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
677 spu_acquire_saved(ctx
);
678 ret
= lscsa
->decr
.slot
[0];
682 DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops
, spufs_decr_get
, spufs_decr_set
,
685 static void spufs_decr_status_set(void *data
, u64 val
)
687 struct spu_context
*ctx
= data
;
688 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
689 spu_acquire_saved(ctx
);
690 lscsa
->decr_status
.slot
[0] = (u32
) val
;
694 static u64
spufs_decr_status_get(void *data
)
696 struct spu_context
*ctx
= data
;
697 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
699 spu_acquire_saved(ctx
);
700 ret
= lscsa
->decr_status
.slot
[0];
704 DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops
, spufs_decr_status_get
,
705 spufs_decr_status_set
, "%llx\n")
707 static void spufs_spu_tag_mask_set(void *data
, u64 val
)
709 struct spu_context
*ctx
= data
;
710 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
711 spu_acquire_saved(ctx
);
712 lscsa
->tag_mask
.slot
[0] = (u32
) val
;
716 static u64
spufs_spu_tag_mask_get(void *data
)
718 struct spu_context
*ctx
= data
;
719 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
721 spu_acquire_saved(ctx
);
722 ret
= lscsa
->tag_mask
.slot
[0];
726 DEFINE_SIMPLE_ATTRIBUTE(spufs_spu_tag_mask_ops
, spufs_spu_tag_mask_get
,
727 spufs_spu_tag_mask_set
, "%llx\n")
729 static void spufs_event_mask_set(void *data
, u64 val
)
731 struct spu_context
*ctx
= data
;
732 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
733 spu_acquire_saved(ctx
);
734 lscsa
->event_mask
.slot
[0] = (u32
) val
;
738 static u64
spufs_event_mask_get(void *data
)
740 struct spu_context
*ctx
= data
;
741 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
743 spu_acquire_saved(ctx
);
744 ret
= lscsa
->event_mask
.slot
[0];
748 DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops
, spufs_event_mask_get
,
749 spufs_event_mask_set
, "%llx\n")
751 static void spufs_srr0_set(void *data
, u64 val
)
753 struct spu_context
*ctx
= data
;
754 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
755 spu_acquire_saved(ctx
);
756 lscsa
->srr0
.slot
[0] = (u32
) val
;
760 static u64
spufs_srr0_get(void *data
)
762 struct spu_context
*ctx
= data
;
763 struct spu_lscsa
*lscsa
= ctx
->csa
.lscsa
;
765 spu_acquire_saved(ctx
);
766 ret
= lscsa
->srr0
.slot
[0];
770 DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops
, spufs_srr0_get
, spufs_srr0_set
,
773 struct tree_descr spufs_dir_contents
[] = {
774 { "mem", &spufs_mem_fops
, 0666, },
775 { "regs", &spufs_regs_fops
, 0666, },
776 { "mbox", &spufs_mbox_fops
, 0444, },
777 { "ibox", &spufs_ibox_fops
, 0444, },
778 { "wbox", &spufs_wbox_fops
, 0222, },
779 { "mbox_stat", &spufs_mbox_stat_fops
, 0444, },
780 { "ibox_stat", &spufs_ibox_stat_fops
, 0444, },
781 { "wbox_stat", &spufs_wbox_stat_fops
, 0444, },
782 { "signal1", &spufs_signal1_fops
, 0666, },
783 { "signal2", &spufs_signal2_fops
, 0666, },
784 { "signal1_type", &spufs_signal1_type
, 0666, },
785 { "signal2_type", &spufs_signal2_type
, 0666, },
786 { "npc", &spufs_npc_ops
, 0666, },
787 { "fpcr", &spufs_fpcr_fops
, 0666, },
788 { "decr", &spufs_decr_ops
, 0666, },
789 { "decr_status", &spufs_decr_status_ops
, 0666, },
790 { "spu_tag_mask", &spufs_spu_tag_mask_ops
, 0666, },
791 { "event_mask", &spufs_event_mask_ops
, 0666, },
792 { "srr0", &spufs_srr0_ops
, 0666, },