]>
Commit | Line | Data |
---|---|---|
67207b96 AB |
1 | #include <linux/file.h> |
2 | #include <linux/fs.h> | |
4b16f8e2 | 3 | #include <linux/export.h> |
67207b96 AB |
4 | #include <linux/mount.h> |
5 | #include <linux/namei.h> | |
5a0e3ad6 | 6 | #include <linux/slab.h> |
67207b96 | 7 | |
7c0f6ba6 | 8 | #include <linux/uaccess.h> |
67207b96 AB |
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 | */ | |
8fce10a3 AB |
33 | static long do_spu_run(struct file *filp, |
34 | __u32 __user *unpc, | |
35 | __u32 __user *ustatus) | |
67207b96 AB |
36 | { |
37 | long ret; | |
38 | struct spufs_inode_info *i; | |
39 | u32 npc, status; | |
40 | ||
41 | ret = -EFAULT; | |
9add11da | 42 | if (get_user(npc, unpc)) |
67207b96 AB |
43 | goto out; |
44 | ||
e80358ad | 45 | /* check if this file was created by spu_create */ |
67207b96 | 46 | ret = -EINVAL; |
e80358ad | 47 | if (filp->f_op != &spufs_context_fops) |
67207b96 AB |
48 | goto out; |
49 | ||
496ad9aa | 50 | i = SPUFS_I(file_inode(filp)); |
50af32a9 | 51 | ret = spufs_run_spu(i->i_ctx, &npc, &status); |
67207b96 | 52 | |
9add11da AB |
53 | if (put_user(npc, unpc)) |
54 | ret = -EFAULT; | |
55 | ||
56 | if (ustatus && put_user(status, ustatus)) | |
67207b96 AB |
57 | ret = -EFAULT; |
58 | out: | |
59 | return ret; | |
60 | } | |
61 | ||
1e8b0f6d | 62 | static long do_spu_create(const char __user *pathname, unsigned int flags, |
c6684b26 | 63 | umode_t mode, struct file *neighbor) |
67207b96 | 64 | { |
1ba10681 AV |
65 | struct path path; |
66 | struct dentry *dentry; | |
67207b96 AB |
67 | int ret; |
68 | ||
1ac12b4b | 69 | dentry = user_path_create(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY); |
1ba10681 AV |
70 | ret = PTR_ERR(dentry); |
71 | if (!IS_ERR(dentry)) { | |
72 | ret = spufs_create(&path, dentry, flags, mode, neighbor); | |
921a1650 | 73 | done_path_create(&path, dentry); |
67207b96 AB |
74 | } |
75 | ||
76 | return ret; | |
77 | } | |
78 | ||
79 | struct spufs_calls spufs_calls = { | |
8e68e2f2 | 80 | .create_thread = do_spu_create, |
67207b96 | 81 | .spu_run = do_spu_run, |
aed3a8c9 | 82 | .notify_spus_active = do_notify_spus_active, |
67207b96 | 83 | .owner = THIS_MODULE, |
e623fbf1 ME |
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 | |
67207b96 | 88 | }; |