1 #include <linux/file.h> 2 #include <linux/fs.h> 3 #include <linux/export.h> 4 #include <linux/mount.h> 5 #include <linux/namei.h> 6 #include <linux/slab.h> 7 8 #include <linux/uaccess.h> 9 10 #include "spufs.h" 11 12 /** 13 * sys_spu_run - run code loaded into an SPU 14 * 15 * @unpc: next program counter for the SPU 16 * @ustatus: status of the SPU 17 * 18 * This system call transfers the control of execution of a 19 * user space thread to an SPU. It will return when the 20 * SPU has finished executing or when it hits an error 21 * condition and it will be interrupted if a signal needs 22 * to be delivered to a handler in user space. 23 * 24 * The next program counter is set to the passed value 25 * before the SPU starts fetching code and the user space 26 * pointer gets updated with the new value when returning 27 * from kernel space. 28 * 29 * The status value returned from spu_run reflects the 30 * value of the spu_status register after the SPU has stopped. 31 * 32 */ 33 static long do_spu_run(struct file *filp, 34 __u32 __user *unpc, 35 __u32 __user *ustatus) 36 { 37 long ret; 38 struct spufs_inode_info *i; 39 u32 npc, status; 40 41 ret = -EFAULT; 42 if (get_user(npc, unpc)) 43 goto out; 44 45 /* check if this file was created by spu_create */ 46 ret = -EINVAL; 47 if (filp->f_op != &spufs_context_fops) 48 goto out; 49 50 i = SPUFS_I(file_inode(filp)); 51 ret = spufs_run_spu(i->i_ctx, &npc, &status); 52 53 if (put_user(npc, unpc)) 54 ret = -EFAULT; 55 56 if (ustatus && put_user(status, ustatus)) 57 ret = -EFAULT; 58 out: 59 return ret; 60 } 61 62 static long do_spu_create(const char __user *pathname, unsigned int flags, 63 umode_t mode, struct file *neighbor) 64 { 65 struct path path; 66 struct dentry *dentry; 67 int ret; 68 69 dentry = user_path_create(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY); 70 ret = PTR_ERR(dentry); 71 if (!IS_ERR(dentry)) { 72 ret = spufs_create(&path, dentry, flags, mode, neighbor); 73 done_path_create(&path, dentry); 74 } 75 76 return ret; 77 } 78 79 struct spufs_calls spufs_calls = { 80 .create_thread = do_spu_create, 81 .spu_run = do_spu_run, 82 .notify_spus_active = do_notify_spus_active, 83 .owner = THIS_MODULE, 84 #ifdef CONFIG_COREDUMP 85 .coredump_extra_notes_size = spufs_coredump_extra_notes_size, 86 .coredump_extra_notes_write = spufs_coredump_extra_notes_write, 87 #endif 88 }; 89