Path: blob/master/arch/powerpc/platforms/cell/spu_syscalls.c
26481 views
// SPDX-License-Identifier: GPL-2.0-or-later1/*2* SPU file system -- system call stubs3*4* (C) Copyright IBM Deutschland Entwicklung GmbH 20055* (C) Copyright 2006-2007, IBM Corporation6*7* Author: Arnd Bergmann <[email protected]>8*/9#include <linux/file.h>10#include <linux/fs.h>11#include <linux/module.h>12#include <linux/syscalls.h>13#include <linux/rcupdate.h>14#include <linux/binfmts.h>1516#include <asm/spu.h>1718/* protected by rcu */19static struct spufs_calls *spufs_calls;2021#ifdef CONFIG_SPU_FS_MODULE2223static inline struct spufs_calls *spufs_calls_get(void)24{25struct spufs_calls *calls = NULL;2627rcu_read_lock();28calls = rcu_dereference(spufs_calls);29if (calls && !try_module_get(calls->owner))30calls = NULL;31rcu_read_unlock();3233return calls;34}3536static inline void spufs_calls_put(struct spufs_calls *calls)37{38if (!calls)39return;4041BUG_ON(calls != spufs_calls);4243/* we don't need to rcu this, as we hold a reference to the module */44module_put(spufs_calls->owner);45}4647#else /* !defined CONFIG_SPU_FS_MODULE */4849static inline struct spufs_calls *spufs_calls_get(void)50{51return spufs_calls;52}5354static inline void spufs_calls_put(struct spufs_calls *calls) { }5556#endif /* CONFIG_SPU_FS_MODULE */5758DEFINE_CLASS(spufs_calls, struct spufs_calls *, spufs_calls_put(_T), spufs_calls_get(), void)5960SYSCALL_DEFINE4(spu_create, const char __user *, name, unsigned int, flags,61umode_t, mode, int, neighbor_fd)62{63CLASS(spufs_calls, calls)();64if (!calls)65return -ENOSYS;6667if (flags & SPU_CREATE_AFFINITY_SPU) {68CLASS(fd, neighbor)(neighbor_fd);69if (fd_empty(neighbor))70return -EBADF;71return calls->create_thread(name, flags, mode, fd_file(neighbor));72} else {73return calls->create_thread(name, flags, mode, NULL);74}75}7677SYSCALL_DEFINE3(spu_run,int, fd, __u32 __user *, unpc, __u32 __user *, ustatus)78{79CLASS(spufs_calls, calls)();80if (!calls)81return -ENOSYS;8283CLASS(fd, arg)(fd);84if (fd_empty(arg))85return -EBADF;8687return calls->spu_run(fd_file(arg), unpc, ustatus);88}8990#ifdef CONFIG_COREDUMP91int elf_coredump_extra_notes_size(void)92{93CLASS(spufs_calls, calls)();94if (!calls)95return 0;9697return calls->coredump_extra_notes_size();98}99100int elf_coredump_extra_notes_write(struct coredump_params *cprm)101{102CLASS(spufs_calls, calls)();103if (!calls)104return 0;105106return calls->coredump_extra_notes_write(cprm);107}108#endif109110void notify_spus_active(void)111{112struct spufs_calls *calls;113114calls = spufs_calls_get();115if (!calls)116return;117118calls->notify_spus_active();119spufs_calls_put(calls);120121return;122}123124int register_spu_syscalls(struct spufs_calls *calls)125{126if (spufs_calls)127return -EBUSY;128129rcu_assign_pointer(spufs_calls, calls);130return 0;131}132EXPORT_SYMBOL_GPL(register_spu_syscalls);133134void unregister_spu_syscalls(struct spufs_calls *calls)135{136BUG_ON(spufs_calls->owner != calls->owner);137RCU_INIT_POINTER(spufs_calls, NULL);138synchronize_rcu();139}140EXPORT_SYMBOL_GPL(unregister_spu_syscalls);141142143