]>
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 | */ | |
8fce10a3 AB |
32 | static long do_spu_run(struct file *filp, |
33 | __u32 __user *unpc, | |
34 | __u32 __user *ustatus) | |
67207b96 AB |
35 | { |
36 | long ret; | |
37 | struct spufs_inode_info *i; | |
38 | u32 npc, status; | |
39 | ||
40 | ret = -EFAULT; | |
9add11da | 41 | if (get_user(npc, unpc)) |
67207b96 AB |
42 | goto out; |
43 | ||
e80358ad | 44 | /* check if this file was created by spu_create */ |
67207b96 | 45 | ret = -EINVAL; |
e80358ad | 46 | if (filp->f_op != &spufs_context_fops) |
67207b96 AB |
47 | goto out; |
48 | ||
b4d1ab58 | 49 | i = SPUFS_I(filp->f_path.dentry->d_inode); |
50af32a9 | 50 | ret = spufs_run_spu(i->i_ctx, &npc, &status); |
67207b96 | 51 | |
9add11da AB |
52 | if (put_user(npc, unpc)) |
53 | ret = -EFAULT; | |
54 | ||
55 | if (ustatus && put_user(status, ustatus)) | |
67207b96 AB |
56 | ret = -EFAULT; |
57 | out: | |
58 | return ret; | |
59 | } | |
60 | ||
1e8b0f6d JK |
61 | static long do_spu_create(const char __user *pathname, unsigned int flags, |
62 | mode_t mode, struct file *neighbor) | |
67207b96 AB |
63 | { |
64 | char *tmp; | |
65 | int ret; | |
66 | ||
67 | tmp = getname(pathname); | |
68 | ret = PTR_ERR(tmp); | |
69 | if (!IS_ERR(tmp)) { | |
70 | struct nameidata nd; | |
71 | ||
72 | ret = path_lookup(tmp, LOOKUP_PARENT| | |
73 | LOOKUP_OPEN|LOOKUP_CREATE, &nd); | |
74 | if (!ret) { | |
8e68e2f2 | 75 | ret = spufs_create(&nd, flags, mode, neighbor); |
1d957f9b | 76 | path_put(&nd.path); |
67207b96 AB |
77 | } |
78 | putname(tmp); | |
79 | } | |
80 | ||
81 | return ret; | |
82 | } | |
83 | ||
84 | struct spufs_calls spufs_calls = { | |
8e68e2f2 | 85 | .create_thread = do_spu_create, |
67207b96 | 86 | .spu_run = do_spu_run, |
48cad41f ME |
87 | .coredump_extra_notes_size = spufs_coredump_extra_notes_size, |
88 | .coredump_extra_notes_write = spufs_coredump_extra_notes_write, | |
aed3a8c9 | 89 | .notify_spus_active = do_notify_spus_active, |
67207b96 AB |
90 | .owner = THIS_MODULE, |
91 | }; |