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/poll.h>
29 #include <asm/semaphore.h>
31 #include <asm/uaccess.h>
37 spufs_mem_open(struct inode *inode, struct file *file)
39 struct spufs_inode_info *i = SPUFS_I(inode);
40 file->private_data = i->i_ctx;
41 file->f_mapping = i->i_ctx->local_store;
46 spufs_mem_read(struct file *file, char __user *buffer,
47 size_t size, loff_t *pos)
49 struct spu_context *ctx = file->private_data;
55 local_store = ctx->ops->get_ls(ctx);
56 ret = simple_read_from_buffer(buffer, size, pos, local_store, LS_SIZE);
63 spufs_mem_write(struct file *file, const char __user *buffer,
64 size_t size, loff_t *pos)
66 struct spu_context *ctx = file->private_data;
70 size = min_t(ssize_t, LS_SIZE - *pos, size);
77 local_store = ctx->ops->get_ls(ctx);
78 ret = copy_from_user(local_store + *pos - size,
79 buffer, size) ? -EFAULT : size;
85 #ifdef CONFIG_SPARSEMEM
87 spufs_mem_mmap_nopage(struct vm_area_struct *vma,
88 unsigned long address, int *type)
90 struct page *page = NOPAGE_SIGBUS;
92 struct spu_context *ctx = vma->vm_file->private_data;
93 unsigned long offset = address - vma->vm_start;
94 offset += vma->vm_pgoff << PAGE_SHIFT;
98 if (ctx->state == SPU_STATE_SAVED)
99 page = vmalloc_to_page(ctx->csa.lscsa->ls + offset);
101 page = pfn_to_page((ctx->spu->local_store_phys + offset)
107 *type = VM_FAULT_MINOR;
112 static struct vm_operations_struct spufs_mem_mmap_vmops = {
113 .nopage = spufs_mem_mmap_nopage,
117 spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
119 if (!(vma->vm_flags & VM_SHARED))
123 vma->vm_flags |= VM_RESERVED;
124 vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
127 vma->vm_ops = &spufs_mem_mmap_vmops;
132 static struct file_operations spufs_mem_fops = {
133 .open = spufs_mem_open,
134 .read = spufs_mem_read,
135 .write = spufs_mem_write,
136 .llseek = generic_file_llseek,
137 #ifdef CONFIG_SPARSEMEM
138 .mmap = spufs_mem_mmap,
143 spufs_regs_open(struct inode *inode, struct file *file)
145 struct spufs_inode_info *i = SPUFS_I(inode);
146 file->private_data = i->i_ctx;
151 spufs_regs_read(struct file *file, char __user *buffer,
152 size_t size, loff_t *pos)
154 struct spu_context *ctx = file->private_data;
155 struct spu_lscsa *lscsa = ctx->csa.lscsa;
158 spu_acquire_saved(ctx);
160 ret = simple_read_from_buffer(buffer, size, pos,
161 lscsa->gprs, sizeof lscsa->gprs);
168 spufs_regs_write(struct file *file, const char __user *buffer,
169 size_t size, loff_t *pos)
171 struct spu_context *ctx = file->private_data;
172 struct spu_lscsa *lscsa = ctx->csa.lscsa;
175 size = min_t(ssize_t, sizeof lscsa->gprs - *pos, size);
180 spu_acquire_saved(ctx);
182 ret = copy_from_user(lscsa->gprs + *pos - size,
183 buffer, size) ? -EFAULT : size;
189 static struct file_operations spufs_regs_fops = {
190 .open = spufs_regs_open,
191 .read = spufs_regs_read,
192 .write = spufs_regs_write,
193 .llseek = generic_file_llseek,
197 spufs_fpcr_read(struct file *file, char __user * buffer,
198 size_t size, loff_t * pos)
200 struct spu_context *ctx = file->private_data;
201 struct spu_lscsa *lscsa = ctx->csa.lscsa;
204 spu_acquire_saved(ctx);
206 ret = simple_read_from_buffer(buffer, size, pos,
207 &lscsa->fpcr, sizeof(lscsa->fpcr));
214 spufs_fpcr_write(struct file *file, const char __user * buffer,
215 size_t size, loff_t * pos)
217 struct spu_context *ctx = file->private_data;
218 struct spu_lscsa *lscsa = ctx->csa.lscsa;
221 size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
226 spu_acquire_saved(ctx);
228 ret = copy_from_user((char *)&lscsa->fpcr + *pos - size,
229 buffer, size) ? -EFAULT : size;
235 static struct file_operations spufs_fpcr_fops = {
236 .open = spufs_regs_open,
237 .read = spufs_fpcr_read,
238 .write = spufs_fpcr_write,
239 .llseek = generic_file_llseek,
242 /* generic open function for all pipe-like files */
243 static int spufs_pipe_open(struct inode *inode, struct file *file)
245 struct spufs_inode_info *i = SPUFS_I(inode);
246 file->private_data = i->i_ctx;
248 return nonseekable_open(inode, file);
251 static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
252 size_t len, loff_t *pos)
254 struct spu_context *ctx = file->private_data;
262 ret = ctx->ops->mbox_read(ctx, &mbox_data);
268 if (copy_to_user(buf, &mbox_data, sizeof mbox_data))
274 static struct file_operations spufs_mbox_fops = {
275 .open = spufs_pipe_open,
276 .read = spufs_mbox_read,
279 static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
280 size_t len, loff_t *pos)
282 struct spu_context *ctx = file->private_data;
290 mbox_stat = ctx->ops->mbox_stat_read(ctx) & 0xff;
294 if (copy_to_user(buf, &mbox_stat, sizeof mbox_stat))
300 static struct file_operations spufs_mbox_stat_fops = {
301 .open = spufs_pipe_open,
302 .read = spufs_mbox_stat_read,
307 * Same as wait_event_interruptible(), except that here
308 * we need to call spu_release(ctx) before sleeping, and
309 * then spu_acquire(ctx) when awoken.
312 #define spufs_wait(wq, condition) \
315 DEFINE_WAIT(__wait); \
317 prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \
320 if (!signal_pending(current)) { \
326 __ret = -ERESTARTSYS; \
329 finish_wait(&(wq), &__wait); \
333 /* low-level ibox access function */
334 size_t spu_ibox_read(struct spu_context *ctx, u32 *data)
336 return ctx->ops->ibox_read(ctx, data);
339 static int spufs_ibox_fasync(int fd, struct file *file, int on)
341 struct spu_context *ctx = file->private_data;
343 return fasync_helper(fd, file, on, &ctx->ibox_fasync);
346 /* interrupt-level ibox callback function. */
347 void spufs_ibox_callback(struct spu *spu)
349 struct spu_context *ctx = spu->ctx;
351 wake_up_all(&ctx->ibox_wq);
352 kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN);
355 static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
356 size_t len, loff_t *pos)
358 struct spu_context *ctx = file->private_data;
368 if (file->f_flags & O_NONBLOCK) {
369 if (!spu_ibox_read(ctx, &ibox_data))
372 ret = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
381 if (copy_to_user(buf, &ibox_data, sizeof ibox_data))
387 static unsigned int spufs_ibox_poll(struct file *file, poll_table *wait)
389 struct spu_context *ctx = file->private_data;
395 mbox_stat = ctx->ops->mbox_stat_read(ctx);
399 poll_wait(file, &ctx->ibox_wq, wait);
402 if (mbox_stat & 0xff0000)
403 mask |= POLLIN | POLLRDNORM;
408 static struct file_operations spufs_ibox_fops = {
409 .open = spufs_pipe_open,
410 .read = spufs_ibox_read,
411 .poll = spufs_ibox_poll,
412 .fasync = spufs_ibox_fasync,
415 static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
416 size_t len, loff_t *pos)
418 struct spu_context *ctx = file->private_data;
425 ibox_stat = (ctx->ops->mbox_stat_read(ctx) >> 16) & 0xff;
428 if (copy_to_user(buf, &ibox_stat, sizeof ibox_stat))
434 static struct file_operations spufs_ibox_stat_fops = {
435 .open = spufs_pipe_open,
436 .read = spufs_ibox_stat_read,
439 /* low-level mailbox write */
440 size_t spu_wbox_write(struct spu_context *ctx, u32 data)
442 return ctx->ops->wbox_write(ctx, data);
445 static int spufs_wbox_fasync(int fd, struct file *file, int on)
447 struct spu_context *ctx = file->private_data;
450 ret = fasync_helper(fd, file, on, &ctx->wbox_fasync);
455 /* interrupt-level wbox callback function. */
456 void spufs_wbox_callback(struct spu *spu)
458 struct spu_context *ctx = spu->ctx;
460 wake_up_all(&ctx->wbox_wq);
461 kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
464 static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
465 size_t len, loff_t *pos)
467 struct spu_context *ctx = file->private_data;
474 if (copy_from_user(&wbox_data, buf, sizeof wbox_data))
480 if (file->f_flags & O_NONBLOCK) {
481 if (!spu_wbox_write(ctx, wbox_data))
484 ret = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
489 return ret ? ret : sizeof wbox_data;
492 static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait)
494 struct spu_context *ctx = file->private_data;
499 mbox_stat = ctx->ops->mbox_stat_read(ctx);
502 poll_wait(file, &ctx->wbox_wq, wait);
505 if (mbox_stat & 0x00ff00)
506 mask = POLLOUT | POLLWRNORM;
511 static struct file_operations spufs_wbox_fops = {
512 .open = spufs_pipe_open,
513 .write = spufs_wbox_write,
514 .poll = spufs_wbox_poll,
515 .fasync = spufs_wbox_fasync,
518 static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
519 size_t len, loff_t *pos)
521 struct spu_context *ctx = file->private_data;
528 wbox_stat = (ctx->ops->mbox_stat_read(ctx) >> 8) & 0xff;
531 if (copy_to_user(buf, &wbox_stat, sizeof wbox_stat))
537 static struct file_operations spufs_wbox_stat_fops = {
538 .open = spufs_pipe_open,
539 .read = spufs_wbox_stat_read,
542 long spufs_run_spu(struct file *file, struct spu_context *ctx,
543 u32 *npc, u32 *status)
547 ret = spu_acquire_runnable(ctx);
551 ctx->ops->npc_write(ctx, *npc);
553 ret = spu_run(ctx->spu);
556 ret = ctx->ops->status_read(ctx);
558 *npc = ctx->ops->npc_read(ctx);
565 static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
566 size_t len, loff_t *pos)
568 struct spu_context *ctx = file->private_data;
575 data = ctx->ops->signal1_read(ctx);
578 if (copy_to_user(buf, &data, 4))
584 static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
585 size_t len, loff_t *pos)
587 struct spu_context *ctx;
590 ctx = file->private_data;
595 if (copy_from_user(&data, buf, 4))
599 ctx->ops->signal1_write(ctx, data);
605 static struct file_operations spufs_signal1_fops = {
606 .open = spufs_pipe_open,
607 .read = spufs_signal1_read,
608 .write = spufs_signal1_write,
611 static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
612 size_t len, loff_t *pos)
614 struct spu_context *ctx;
617 ctx = file->private_data;
623 data = ctx->ops->signal2_read(ctx);
626 if (copy_to_user(buf, &data, 4))
632 static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
633 size_t len, loff_t *pos)
635 struct spu_context *ctx;
638 ctx = file->private_data;
643 if (copy_from_user(&data, buf, 4))
647 ctx->ops->signal2_write(ctx, data);
653 static struct file_operations spufs_signal2_fops = {
654 .open = spufs_pipe_open,
655 .read = spufs_signal2_read,
656 .write = spufs_signal2_write,
659 static void spufs_signal1_type_set(void *data, u64 val)
661 struct spu_context *ctx = data;
664 ctx->ops->signal1_type_set(ctx, val);
668 static u64 spufs_signal1_type_get(void *data)
670 struct spu_context *ctx = data;
674 ret = ctx->ops->signal1_type_get(ctx);
679 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
680 spufs_signal1_type_set, "%llu");
682 static void spufs_signal2_type_set(void *data, u64 val)
684 struct spu_context *ctx = data;
687 ctx->ops->signal2_type_set(ctx, val);
691 static u64 spufs_signal2_type_get(void *data)
693 struct spu_context *ctx = data;
697 ret = ctx->ops->signal2_type_get(ctx);
702 DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
703 spufs_signal2_type_set, "%llu");
705 static void spufs_npc_set(void *data, u64 val)
707 struct spu_context *ctx = data;
709 ctx->ops->npc_write(ctx, val);
713 static u64 spufs_npc_get(void *data)
715 struct spu_context *ctx = data;
718 ret = ctx->ops->npc_read(ctx);
722 DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, "%llx\n")
724 static void spufs_decr_set(void *data, u64 val)
726 struct spu_context *ctx = data;
727 struct spu_lscsa *lscsa = ctx->csa.lscsa;
728 spu_acquire_saved(ctx);
729 lscsa->decr.slot[0] = (u32) val;
733 static u64 spufs_decr_get(void *data)
735 struct spu_context *ctx = data;
736 struct spu_lscsa *lscsa = ctx->csa.lscsa;
738 spu_acquire_saved(ctx);
739 ret = lscsa->decr.slot[0];
743 DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
746 static void spufs_decr_status_set(void *data, u64 val)
748 struct spu_context *ctx = data;
749 struct spu_lscsa *lscsa = ctx->csa.lscsa;
750 spu_acquire_saved(ctx);
751 lscsa->decr_status.slot[0] = (u32) val;
755 static u64 spufs_decr_status_get(void *data)
757 struct spu_context *ctx = data;
758 struct spu_lscsa *lscsa = ctx->csa.lscsa;
760 spu_acquire_saved(ctx);
761 ret = lscsa->decr_status.slot[0];
765 DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
766 spufs_decr_status_set, "%llx\n")
768 static void spufs_spu_tag_mask_set(void *data, u64 val)
770 struct spu_context *ctx = data;
771 struct spu_lscsa *lscsa = ctx->csa.lscsa;
772 spu_acquire_saved(ctx);
773 lscsa->tag_mask.slot[0] = (u32) val;
777 static u64 spufs_spu_tag_mask_get(void *data)
779 struct spu_context *ctx = data;
780 struct spu_lscsa *lscsa = ctx->csa.lscsa;
782 spu_acquire_saved(ctx);
783 ret = lscsa->tag_mask.slot[0];
787 DEFINE_SIMPLE_ATTRIBUTE(spufs_spu_tag_mask_ops, spufs_spu_tag_mask_get,
788 spufs_spu_tag_mask_set, "%llx\n")
790 static void spufs_event_mask_set(void *data, u64 val)
792 struct spu_context *ctx = data;
793 struct spu_lscsa *lscsa = ctx->csa.lscsa;
794 spu_acquire_saved(ctx);
795 lscsa->event_mask.slot[0] = (u32) val;
799 static u64 spufs_event_mask_get(void *data)
801 struct spu_context *ctx = data;
802 struct spu_lscsa *lscsa = ctx->csa.lscsa;
804 spu_acquire_saved(ctx);
805 ret = lscsa->event_mask.slot[0];
809 DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
810 spufs_event_mask_set, "%llx\n")
812 static void spufs_srr0_set(void *data, u64 val)
814 struct spu_context *ctx = data;
815 struct spu_lscsa *lscsa = ctx->csa.lscsa;
816 spu_acquire_saved(ctx);
817 lscsa->srr0.slot[0] = (u32) val;
821 static u64 spufs_srr0_get(void *data)
823 struct spu_context *ctx = data;
824 struct spu_lscsa *lscsa = ctx->csa.lscsa;
826 spu_acquire_saved(ctx);
827 ret = lscsa->srr0.slot[0];
831 DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
834 struct tree_descr spufs_dir_contents[] = {
835 { "mem", &spufs_mem_fops, 0666, },
836 { "regs", &spufs_regs_fops, 0666, },
837 { "mbox", &spufs_mbox_fops, 0444, },
838 { "ibox", &spufs_ibox_fops, 0444, },
839 { "wbox", &spufs_wbox_fops, 0222, },
840 { "mbox_stat", &spufs_mbox_stat_fops, 0444, },
841 { "ibox_stat", &spufs_ibox_stat_fops, 0444, },
842 { "wbox_stat", &spufs_wbox_stat_fops, 0444, },
843 { "signal1", &spufs_signal1_fops, 0666, },
844 { "signal2", &spufs_signal2_fops, 0666, },
845 { "signal1_type", &spufs_signal1_type, 0666, },
846 { "signal2_type", &spufs_signal2_type, 0666, },
847 { "npc", &spufs_npc_ops, 0666, },
848 { "fpcr", &spufs_fpcr_fops, 0666, },
849 { "decr", &spufs_decr_ops, 0666, },
850 { "decr_status", &spufs_decr_status_ops, 0666, },
851 { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, },
852 { "event_mask", &spufs_event_mask_ops, 0666, },
853 { "srr0", &spufs_srr0_ops, 0666, },