Commit | Line | Data |
---|---|---|
67207b96 AB |
1 | #include <linux/file.h> |
2 | #include <linux/fs.h> | |
3 | #include <linux/module.h> | |
4 | #include <linux/mount.h> | |
5 | #include <linux/namei.h> | |
6 | ||
7 | #include <asm/uaccess.h> | |
8 | ||
9 | #include "spufs.h" | |
10 | ||
11 | /** | |
12 | * sys_spu_run - run code loaded into an SPU | |
13 | * | |
14 | * @unpc: next program counter for the SPU | |
15 | * @ustatus: status of the SPU | |
16 | * | |
17 | * This system call transfers the control of execution of a | |
18 | * user space thread to an SPU. It will return when the | |
19 | * SPU has finished executing or when it hits an error | |
20 | * condition and it will be interrupted if a signal needs | |
21 | * to be delivered to a handler in user space. | |
22 | * | |
23 | * The next program counter is set to the passed value | |
24 | * before the SPU starts fetching code and the user space | |
25 | * pointer gets updated with the new value when returning | |
26 | * from kernel space. | |
27 | * | |
28 | * The status value returned from spu_run reflects the | |
29 | * value of the spu_status register after the SPU has stopped. | |
30 | * | |
31 | */ | |
32 | long do_spu_run(struct file *filp, __u32 __user *unpc, __u32 __user *ustatus) | |
33 | { | |
34 | long ret; | |
35 | struct spufs_inode_info *i; | |
36 | u32 npc, status; | |
37 | ||
38 | ret = -EFAULT; | |
8b3d6663 | 39 | if (get_user(npc, unpc) || get_user(status, ustatus)) |
67207b96 AB |
40 | goto out; |
41 | ||
42 | ret = -EINVAL; | |
43 | if (filp->f_vfsmnt->mnt_sb->s_magic != SPUFS_MAGIC) | |
44 | goto out; | |
45 | ||
46 | i = SPUFS_I(filp->f_dentry->d_inode); | |
47 | ret = spufs_run_spu(filp, i->i_ctx, &npc, &status); | |
48 | ||
8b3d6663 | 49 | if (put_user(npc, unpc) || put_user(status, ustatus)) |
67207b96 AB |
50 | ret = -EFAULT; |
51 | out: | |
52 | return ret; | |
53 | } | |
54 | ||
55 | #ifndef MODULE | |
56 | asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus) | |
57 | { | |
58 | int fput_needed; | |
59 | struct file *filp; | |
60 | long ret; | |
61 | ||
62 | ret = -EBADF; | |
63 | filp = fget_light(fd, &fput_needed); | |
64 | if (filp) { | |
65 | ret = do_spu_run(filp, unpc, ustatus); | |
66 | fput_light(filp, fput_needed); | |
67 | } | |
68 | ||
69 | return ret; | |
70 | } | |
71 | #endif | |
72 | ||
73 | asmlinkage long sys_spu_create(const char __user *pathname, | |
74 | unsigned int flags, mode_t mode) | |
75 | { | |
76 | char *tmp; | |
77 | int ret; | |
78 | ||
79 | tmp = getname(pathname); | |
80 | ret = PTR_ERR(tmp); | |
81 | if (!IS_ERR(tmp)) { | |
82 | struct nameidata nd; | |
83 | ||
84 | ret = path_lookup(tmp, LOOKUP_PARENT| | |
85 | LOOKUP_OPEN|LOOKUP_CREATE, &nd); | |
86 | if (!ret) { | |
87 | ret = spufs_create_thread(&nd, pathname, flags, mode); | |
88 | path_release(&nd); | |
89 | } | |
90 | putname(tmp); | |
91 | } | |
92 | ||
93 | return ret; | |
94 | } | |
95 | ||
96 | struct spufs_calls spufs_calls = { | |
97 | .create_thread = sys_spu_create, | |
98 | .spu_run = do_spu_run, | |
99 | .owner = THIS_MODULE, | |
100 | }; |