syscalls.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/file.h>
  3. #include <linux/fs.h>
  4. #include <linux/export.h>
  5. #include <linux/mount.h>
  6. #include <linux/namei.h>
  7. #include <linux/slab.h>
  8. #include <linux/uaccess.h>
  9. #include "spufs.h"
  10. /**
  11. * sys_spu_run - run code loaded into an SPU
  12. *
  13. * @unpc: next program counter for the SPU
  14. * @ustatus: status of the SPU
  15. *
  16. * This system call transfers the control of execution of a
  17. * user space thread to an SPU. It will return when the
  18. * SPU has finished executing or when it hits an error
  19. * condition and it will be interrupted if a signal needs
  20. * to be delivered to a handler in user space.
  21. *
  22. * The next program counter is set to the passed value
  23. * before the SPU starts fetching code and the user space
  24. * pointer gets updated with the new value when returning
  25. * from kernel space.
  26. *
  27. * The status value returned from spu_run reflects the
  28. * value of the spu_status register after the SPU has stopped.
  29. *
  30. */
  31. static long do_spu_run(struct file *filp,
  32. __u32 __user *unpc,
  33. __u32 __user *ustatus)
  34. {
  35. long ret;
  36. struct spufs_inode_info *i;
  37. u32 npc, status;
  38. ret = -EFAULT;
  39. if (get_user(npc, unpc))
  40. goto out;
  41. /* check if this file was created by spu_create */
  42. ret = -EINVAL;
  43. if (filp->f_op != &spufs_context_fops)
  44. goto out;
  45. i = SPUFS_I(file_inode(filp));
  46. ret = spufs_run_spu(i->i_ctx, &npc, &status);
  47. if (put_user(npc, unpc))
  48. ret = -EFAULT;
  49. if (ustatus && put_user(status, ustatus))
  50. ret = -EFAULT;
  51. out:
  52. return ret;
  53. }
  54. static long do_spu_create(const char __user *pathname, unsigned int flags,
  55. umode_t mode, struct file *neighbor)
  56. {
  57. struct path path;
  58. struct dentry *dentry;
  59. int ret;
  60. dentry = user_path_create(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY);
  61. ret = PTR_ERR(dentry);
  62. if (!IS_ERR(dentry)) {
  63. ret = spufs_create(&path, dentry, flags, mode, neighbor);
  64. done_path_create(&path, dentry);
  65. }
  66. return ret;
  67. }
  68. struct spufs_calls spufs_calls = {
  69. .create_thread = do_spu_create,
  70. .spu_run = do_spu_run,
  71. .notify_spus_active = do_notify_spus_active,
  72. .owner = THIS_MODULE,
  73. #ifdef CONFIG_COREDUMP
  74. .coredump_extra_notes_size = spufs_coredump_extra_notes_size,
  75. .coredump_extra_notes_write = spufs_coredump_extra_notes_write,
  76. #endif
  77. };