1 #include <linux/file.h> 2 #include <linux/fs.h> 3 #include <linux/module.h> 4 #include <linux/mount.h> 5 #include <linux/namei.h> 6 7 #include <asm/uaccess.h> 8 9 #include "spufs.h" 10 11 /** 12 * sys_spu_run - run code loaded into an SPU 13 * 14 * @unpc: next program counter for the SPU 15 * @ustatus: status of the SPU 16 * 17 * This system call transfers the control of execution of a 18 * user space thread to an SPU. It will return when the 19 * SPU has finished executing or when it hits an error 20 * condition and it will be interrupted if a signal needs 21 * to be delivered to a handler in user space. 22 * 23 * The next program counter is set to the passed value 24 * before the SPU starts fetching code and the user space 25 * pointer gets updated with the new value when returning 26 * from kernel space. 27 * 28 * The status value returned from spu_run reflects the 29 * value of the spu_status register after the SPU has stopped. 30 * 31 */ 32 static long do_spu_run(struct file *filp, 33 __u32 __user *unpc, 34 __u32 __user *ustatus) 35 { 36 long ret; 37 struct spufs_inode_info *i; 38 u32 npc, status; 39 40 ret = -EFAULT; 41 if (get_user(npc, unpc)) 42 goto out; 43 44 /* check if this file was created by spu_create */ 45 ret = -EINVAL; 46 if (filp->f_op != &spufs_context_fops) 47 goto out; 48 49 i = SPUFS_I(filp->f_path.dentry->d_inode); 50 ret = spufs_run_spu(i->i_ctx, &npc, &status); 51 52 if (put_user(npc, unpc)) 53 ret = -EFAULT; 54 55 if (ustatus && put_user(status, ustatus)) 56 ret = -EFAULT; 57 out: 58 return ret; 59 } 60 61 #ifndef MODULE 62 asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus) 63 { 64 int fput_needed; 65 struct file *filp; 66 long ret; 67 68 ret = -EBADF; 69 filp = fget_light(fd, &fput_needed); 70 if (filp) { 71 ret = do_spu_run(filp, unpc, ustatus); 72 fput_light(filp, fput_needed); 73 } 74 75 return ret; 76 } 77 #endif 78 79 asmlinkage long do_spu_create(const char __user *pathname, unsigned int flags, 80 mode_t mode, struct file *neighbor) 81 { 82 char *tmp; 83 int ret; 84 85 tmp = getname(pathname); 86 ret = PTR_ERR(tmp); 87 if (!IS_ERR(tmp)) { 88 struct nameidata nd; 89 90 ret = path_lookup(tmp, LOOKUP_PARENT| 91 LOOKUP_OPEN|LOOKUP_CREATE, &nd); 92 if (!ret) { 93 ret = spufs_create(&nd, flags, mode, neighbor); 94 path_release(&nd); 95 } 96 putname(tmp); 97 } 98 99 return ret; 100 } 101 102 #ifndef MODULE 103 asmlinkage long sys_spu_create(const char __user *pathname, unsigned int flags, 104 mode_t mode, int neighbor_fd) 105 { 106 int fput_needed; 107 struct file *neighbor; 108 long ret; 109 110 if (flags & SPU_CREATE_AFFINITY_SPU) { 111 ret = -EBADF; 112 neighbor = fget_light(neighbor_fd, &fput_needed); 113 if (neighbor) { 114 ret = do_spu_create(pathname, flags, mode, neighbor); 115 fput_light(neighbor, fput_needed); 116 } 117 } 118 else { 119 ret = do_spu_create(pathname, flags, mode, NULL); 120 } 121 122 return ret; 123 } 124 #endif 125 126 struct spufs_calls spufs_calls = { 127 .create_thread = do_spu_create, 128 .spu_run = do_spu_run, 129 .owner = THIS_MODULE, 130 }; 131