mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
2.2 KiB
89 lines
2.2 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
#include <linux/file.h> |
|
#include <linux/fs.h> |
|
#include <linux/export.h> |
|
#include <linux/mount.h> |
|
#include <linux/namei.h> |
|
#include <linux/slab.h> |
|
|
|
#include <linux/uaccess.h> |
|
|
|
#include "spufs.h" |
|
|
|
/** |
|
* sys_spu_run - run code loaded into an SPU |
|
* |
|
* @unpc: next program counter for the SPU |
|
* @ustatus: status of the SPU |
|
* |
|
* This system call transfers the control of execution of a |
|
* user space thread to an SPU. It will return when the |
|
* SPU has finished executing or when it hits an error |
|
* condition and it will be interrupted if a signal needs |
|
* to be delivered to a handler in user space. |
|
* |
|
* The next program counter is set to the passed value |
|
* before the SPU starts fetching code and the user space |
|
* pointer gets updated with the new value when returning |
|
* from kernel space. |
|
* |
|
* The status value returned from spu_run reflects the |
|
* value of the spu_status register after the SPU has stopped. |
|
* |
|
*/ |
|
static long do_spu_run(struct file *filp, |
|
__u32 __user *unpc, |
|
__u32 __user *ustatus) |
|
{ |
|
long ret; |
|
struct spufs_inode_info *i; |
|
u32 npc, status; |
|
|
|
ret = -EFAULT; |
|
if (get_user(npc, unpc)) |
|
goto out; |
|
|
|
/* check if this file was created by spu_create */ |
|
ret = -EINVAL; |
|
if (filp->f_op != &spufs_context_fops) |
|
goto out; |
|
|
|
i = SPUFS_I(file_inode(filp)); |
|
ret = spufs_run_spu(i->i_ctx, &npc, &status); |
|
|
|
if (put_user(npc, unpc)) |
|
ret = -EFAULT; |
|
|
|
if (ustatus && put_user(status, ustatus)) |
|
ret = -EFAULT; |
|
out: |
|
return ret; |
|
} |
|
|
|
static long do_spu_create(const char __user *pathname, unsigned int flags, |
|
umode_t mode, struct file *neighbor) |
|
{ |
|
struct path path; |
|
struct dentry *dentry; |
|
int ret; |
|
|
|
dentry = user_path_create(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY); |
|
ret = PTR_ERR(dentry); |
|
if (!IS_ERR(dentry)) { |
|
ret = spufs_create(&path, dentry, flags, mode, neighbor); |
|
done_path_create(&path, dentry); |
|
} |
|
|
|
return ret; |
|
} |
|
|
|
struct spufs_calls spufs_calls = { |
|
.create_thread = do_spu_create, |
|
.spu_run = do_spu_run, |
|
.notify_spus_active = do_notify_spus_active, |
|
.owner = THIS_MODULE, |
|
#ifdef CONFIG_COREDUMP |
|
.coredump_extra_notes_size = spufs_coredump_extra_notes_size, |
|
.coredump_extra_notes_write = spufs_coredump_extra_notes_write, |
|
#endif |
|
};
|
|
|