162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <linux/file.h> 362306a36Sopenharmony_ci#include <linux/fs.h> 462306a36Sopenharmony_ci#include <linux/export.h> 562306a36Sopenharmony_ci#include <linux/mount.h> 662306a36Sopenharmony_ci#include <linux/namei.h> 762306a36Sopenharmony_ci#include <linux/slab.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/uaccess.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "spufs.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/** 1462306a36Sopenharmony_ci * sys_spu_run - run code loaded into an SPU 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * @unpc: next program counter for the SPU 1762306a36Sopenharmony_ci * @ustatus: status of the SPU 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * This system call transfers the control of execution of a 2062306a36Sopenharmony_ci * user space thread to an SPU. It will return when the 2162306a36Sopenharmony_ci * SPU has finished executing or when it hits an error 2262306a36Sopenharmony_ci * condition and it will be interrupted if a signal needs 2362306a36Sopenharmony_ci * to be delivered to a handler in user space. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * The next program counter is set to the passed value 2662306a36Sopenharmony_ci * before the SPU starts fetching code and the user space 2762306a36Sopenharmony_ci * pointer gets updated with the new value when returning 2862306a36Sopenharmony_ci * from kernel space. 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * The status value returned from spu_run reflects the 3162306a36Sopenharmony_ci * value of the spu_status register after the SPU has stopped. 3262306a36Sopenharmony_ci * 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_cistatic long do_spu_run(struct file *filp, 3562306a36Sopenharmony_ci __u32 __user *unpc, 3662306a36Sopenharmony_ci __u32 __user *ustatus) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci long ret; 3962306a36Sopenharmony_ci struct spufs_inode_info *i; 4062306a36Sopenharmony_ci u32 npc, status; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci ret = -EFAULT; 4362306a36Sopenharmony_ci if (get_user(npc, unpc)) 4462306a36Sopenharmony_ci goto out; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci /* check if this file was created by spu_create */ 4762306a36Sopenharmony_ci ret = -EINVAL; 4862306a36Sopenharmony_ci if (filp->f_op != &spufs_context_fops) 4962306a36Sopenharmony_ci goto out; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci i = SPUFS_I(file_inode(filp)); 5262306a36Sopenharmony_ci ret = spufs_run_spu(i->i_ctx, &npc, &status); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci if (put_user(npc, unpc)) 5562306a36Sopenharmony_ci ret = -EFAULT; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci if (ustatus && put_user(status, ustatus)) 5862306a36Sopenharmony_ci ret = -EFAULT; 5962306a36Sopenharmony_ciout: 6062306a36Sopenharmony_ci return ret; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic long do_spu_create(const char __user *pathname, unsigned int flags, 6462306a36Sopenharmony_ci umode_t mode, struct file *neighbor) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci struct path path; 6762306a36Sopenharmony_ci struct dentry *dentry; 6862306a36Sopenharmony_ci int ret; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci dentry = user_path_create(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY); 7162306a36Sopenharmony_ci ret = PTR_ERR(dentry); 7262306a36Sopenharmony_ci if (!IS_ERR(dentry)) { 7362306a36Sopenharmony_ci ret = spufs_create(&path, dentry, flags, mode, neighbor); 7462306a36Sopenharmony_ci done_path_create(&path, dentry); 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci return ret; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistruct spufs_calls spufs_calls = { 8162306a36Sopenharmony_ci .create_thread = do_spu_create, 8262306a36Sopenharmony_ci .spu_run = do_spu_run, 8362306a36Sopenharmony_ci .notify_spus_active = do_notify_spus_active, 8462306a36Sopenharmony_ci .owner = THIS_MODULE, 8562306a36Sopenharmony_ci#ifdef CONFIG_COREDUMP 8662306a36Sopenharmony_ci .coredump_extra_notes_size = spufs_coredump_extra_notes_size, 8762306a36Sopenharmony_ci .coredump_extra_notes_write = spufs_coredump_extra_notes_write, 8862306a36Sopenharmony_ci#endif 8962306a36Sopenharmony_ci}; 90