syscalls.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /*
  2. * Copyright 2003 PathScale, Inc.
  3. *
  4. * Licensed under the GPL
  5. */
  6. #include "linux/linkage.h"
  7. #include "linux/slab.h"
  8. #include "linux/shm.h"
  9. #include "linux/utsname.h"
  10. #include "linux/personality.h"
  11. #include "asm/uaccess.h"
  12. #define __FRAME_OFFSETS
  13. #include "asm/ptrace.h"
  14. #include "asm/unistd.h"
  15. #include "asm/prctl.h" /* XXX This should get the constants from libc */
  16. #include "choose-mode.h"
  17. #include "kern.h"
  18. asmlinkage long sys_uname64(struct new_utsname __user * name)
  19. {
  20. int err;
  21. down_read(&uts_sem);
  22. err = copy_to_user(name, &system_utsname, sizeof (*name));
  23. up_read(&uts_sem);
  24. if (personality(current->personality) == PER_LINUX32)
  25. err |= copy_to_user(&name->machine, "i686", 5);
  26. return err ? -EFAULT : 0;
  27. }
  28. #ifdef CONFIG_MODE_TT
  29. extern long arch_prctl(int code, unsigned long addr);
  30. static long arch_prctl_tt(int code, unsigned long addr)
  31. {
  32. unsigned long tmp;
  33. long ret;
  34. switch(code){
  35. case ARCH_SET_GS:
  36. case ARCH_SET_FS:
  37. ret = arch_prctl(code, addr);
  38. break;
  39. case ARCH_GET_FS:
  40. case ARCH_GET_GS:
  41. ret = arch_prctl(code, (unsigned long) &tmp);
  42. if(!ret)
  43. ret = put_user(tmp, &addr);
  44. break;
  45. default:
  46. ret = -EINVAL;
  47. break;
  48. }
  49. return(ret);
  50. }
  51. #endif
  52. #ifdef CONFIG_MODE_SKAS
  53. /* XXX: Must also call arch_prctl in the host, beside saving the segment bases! */
  54. static long arch_prctl_skas(int code, unsigned long addr)
  55. {
  56. long ret = 0;
  57. switch(code){
  58. case ARCH_SET_FS:
  59. current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr;
  60. break;
  61. case ARCH_SET_GS:
  62. current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr;
  63. break;
  64. case ARCH_GET_FS:
  65. ret = put_user(current->thread.regs.regs.skas.
  66. regs[FS_BASE / sizeof(unsigned long)],
  67. (unsigned long __user *)addr);
  68. break;
  69. case ARCH_GET_GS:
  70. ret = put_user(current->thread.regs.regs.skas.
  71. regs[GS_BASE / sizeof(unsigned long)],
  72. (unsigned long __user *)addr);
  73. break;
  74. default:
  75. ret = -EINVAL;
  76. break;
  77. }
  78. return(ret);
  79. }
  80. #endif
  81. long sys_arch_prctl(int code, unsigned long addr)
  82. {
  83. return(CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code, addr));
  84. }
  85. long sys_clone(unsigned long clone_flags, unsigned long newsp,
  86. void __user *parent_tid, void __user *child_tid)
  87. {
  88. long ret;
  89. if (!newsp)
  90. newsp = UPT_SP(&current->thread.regs.regs);
  91. current->thread.forking = 1;
  92. ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
  93. child_tid);
  94. current->thread.forking = 0;
  95. return(ret);
  96. }