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