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 <arndb@de.ibm.com> 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 void notify_spus_active(void) 92 { 93 struct spufs_calls *calls; 94 95 calls = spufs_calls_get(); 96 if (!calls) 97 return; 98 99 calls->notify_spus_active(); 100 spufs_calls_put(calls); 101 102 return; 103 } 104 105 int register_spu_syscalls(struct spufs_calls *calls) 106 { 107 if (spufs_calls) 108 return -EBUSY; 109 110 rcu_assign_pointer(spufs_calls, calls); 111 return 0; 112 } 113 EXPORT_SYMBOL_GPL(register_spu_syscalls); 114 115 void unregister_spu_syscalls(struct spufs_calls *calls) 116 { 117 BUG_ON(spufs_calls->owner != calls->owner); 118 RCU_INIT_POINTER(spufs_calls, NULL); 119 synchronize_rcu(); 120 } 121 EXPORT_SYMBOL_GPL(unregister_spu_syscalls); 122