Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/powerpc/platforms/cell/spu_syscalls.c
26481 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* SPU file system -- system call stubs
4
*
5
* (C) Copyright IBM Deutschland Entwicklung GmbH 2005
6
* (C) Copyright 2006-2007, IBM Corporation
7
*
8
* Author: Arnd Bergmann <[email protected]>
9
*/
10
#include <linux/file.h>
11
#include <linux/fs.h>
12
#include <linux/module.h>
13
#include <linux/syscalls.h>
14
#include <linux/rcupdate.h>
15
#include <linux/binfmts.h>
16
17
#include <asm/spu.h>
18
19
/* protected by rcu */
20
static struct spufs_calls *spufs_calls;
21
22
#ifdef CONFIG_SPU_FS_MODULE
23
24
static inline struct spufs_calls *spufs_calls_get(void)
25
{
26
struct spufs_calls *calls = NULL;
27
28
rcu_read_lock();
29
calls = rcu_dereference(spufs_calls);
30
if (calls && !try_module_get(calls->owner))
31
calls = NULL;
32
rcu_read_unlock();
33
34
return calls;
35
}
36
37
static inline void spufs_calls_put(struct spufs_calls *calls)
38
{
39
if (!calls)
40
return;
41
42
BUG_ON(calls != spufs_calls);
43
44
/* we don't need to rcu this, as we hold a reference to the module */
45
module_put(spufs_calls->owner);
46
}
47
48
#else /* !defined CONFIG_SPU_FS_MODULE */
49
50
static inline struct spufs_calls *spufs_calls_get(void)
51
{
52
return spufs_calls;
53
}
54
55
static inline void spufs_calls_put(struct spufs_calls *calls) { }
56
57
#endif /* CONFIG_SPU_FS_MODULE */
58
59
DEFINE_CLASS(spufs_calls, struct spufs_calls *, spufs_calls_put(_T), spufs_calls_get(), void)
60
61
SYSCALL_DEFINE4(spu_create, const char __user *, name, unsigned int, flags,
62
umode_t, mode, int, neighbor_fd)
63
{
64
CLASS(spufs_calls, calls)();
65
if (!calls)
66
return -ENOSYS;
67
68
if (flags & SPU_CREATE_AFFINITY_SPU) {
69
CLASS(fd, neighbor)(neighbor_fd);
70
if (fd_empty(neighbor))
71
return -EBADF;
72
return calls->create_thread(name, flags, mode, fd_file(neighbor));
73
} else {
74
return calls->create_thread(name, flags, mode, NULL);
75
}
76
}
77
78
SYSCALL_DEFINE3(spu_run,int, fd, __u32 __user *, unpc, __u32 __user *, ustatus)
79
{
80
CLASS(spufs_calls, calls)();
81
if (!calls)
82
return -ENOSYS;
83
84
CLASS(fd, arg)(fd);
85
if (fd_empty(arg))
86
return -EBADF;
87
88
return calls->spu_run(fd_file(arg), unpc, ustatus);
89
}
90
91
#ifdef CONFIG_COREDUMP
92
int elf_coredump_extra_notes_size(void)
93
{
94
CLASS(spufs_calls, calls)();
95
if (!calls)
96
return 0;
97
98
return calls->coredump_extra_notes_size();
99
}
100
101
int elf_coredump_extra_notes_write(struct coredump_params *cprm)
102
{
103
CLASS(spufs_calls, calls)();
104
if (!calls)
105
return 0;
106
107
return calls->coredump_extra_notes_write(cprm);
108
}
109
#endif
110
111
void notify_spus_active(void)
112
{
113
struct spufs_calls *calls;
114
115
calls = spufs_calls_get();
116
if (!calls)
117
return;
118
119
calls->notify_spus_active();
120
spufs_calls_put(calls);
121
122
return;
123
}
124
125
int register_spu_syscalls(struct spufs_calls *calls)
126
{
127
if (spufs_calls)
128
return -EBUSY;
129
130
rcu_assign_pointer(spufs_calls, calls);
131
return 0;
132
}
133
EXPORT_SYMBOL_GPL(register_spu_syscalls);
134
135
void unregister_spu_syscalls(struct spufs_calls *calls)
136
{
137
BUG_ON(spufs_calls->owner != calls->owner);
138
RCU_INIT_POINTER(spufs_calls, NULL);
139
synchronize_rcu();
140
}
141
EXPORT_SYMBOL_GPL(unregister_spu_syscalls);
142
143