syscall.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
  3. * The President and Fellows of Harvard College.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. #include <types.h>
  30. #include <kern/errno.h>
  31. #include <kern/syscall.h>
  32. #include <lib.h>
  33. #include <mips/trapframe.h>
  34. #include <thread.h>
  35. #include <current.h>
  36. #include <syscall.h>
  37. /*
  38. * System call dispatcher.
  39. *
  40. * A pointer to the trapframe created during exception entry (in
  41. * exception.S) is passed in.
  42. *
  43. * The calling conventions for syscalls are as follows: Like ordinary
  44. * function calls, the first 4 32-bit arguments are passed in the 4
  45. * argument registers a0-a3. 64-bit arguments are passed in *aligned*
  46. * pairs of registers, that is, either a0/a1 or a2/a3. This means that
  47. * if the first argument is 32-bit and the second is 64-bit, a1 is
  48. * unused.
  49. *
  50. * This much is the same as the calling conventions for ordinary
  51. * function calls. In addition, the system call number is passed in
  52. * the v0 register.
  53. *
  54. * On successful return, the return value is passed back in the v0
  55. * register, or v0 and v1 if 64-bit. This is also like an ordinary
  56. * function call, and additionally the a3 register is also set to 0 to
  57. * indicate success.
  58. *
  59. * On an error return, the error code is passed back in the v0
  60. * register, and the a3 register is set to 1 to indicate failure.
  61. * (Userlevel code takes care of storing the error code in errno and
  62. * returning the value -1 from the actual userlevel syscall function.
  63. * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.)
  64. *
  65. * Upon syscall return the program counter stored in the trapframe
  66. * must be incremented by one instruction; otherwise the exception
  67. * return code will restart the "syscall" instruction and the system
  68. * call will repeat forever.
  69. *
  70. * If you run out of registers (which happens quickly with 64-bit
  71. * values) further arguments must be fetched from the user-level
  72. * stack, starting at sp+16 to skip over the slots for the
  73. * registerized values, with copyin().
  74. */
  75. void
  76. syscall(struct trapframe * tf)
  77. {
  78. int callno;
  79. int32_t retval;
  80. int err;
  81. KASSERT(curthread != NULL);
  82. KASSERT(curthread->t_curspl == 0);
  83. KASSERT(curthread->t_iplhigh_count == 0);
  84. callno = tf->tf_v0;
  85. /*
  86. * Initialize retval to 0. Many of the system calls don't
  87. * really return a value, just 0 for success and -1 on
  88. * error. Since retval is the value returned on success,
  89. * initialize it to 0 by default; thus it's not necessary to
  90. * deal with it except for calls that return other values,
  91. * like write.
  92. */
  93. retval = 0;
  94. switch (callno)
  95. {
  96. case SYS_reboot:
  97. err = sys_reboot(tf->tf_a0);
  98. break;
  99. case SYS___time:
  100. err = sys___time((userptr_t)tf->tf_a0,
  101. (userptr_t)tf->tf_a1);
  102. break;
  103. #ifdef UW
  104. case SYS_write:
  105. err = sys_write((int)tf->tf_a0,
  106. (userptr_t)tf->tf_a1,
  107. (int)tf->tf_a2,
  108. (int *)(&retval));
  109. break;
  110. case SYS__exit:
  111. sys__exit((int)tf->tf_a0);
  112. /* sys__exit does not return, execution should not get here */
  113. panic("unexpected return from sys__exit");
  114. break;
  115. case SYS_getpid:
  116. err = sys_getpid((pid_t *)&retval);
  117. break;
  118. case SYS_waitpid:
  119. err = sys_waitpid((pid_t)tf->tf_a0,
  120. (userptr_t)tf->tf_a1,
  121. (int)tf->tf_a2,
  122. (pid_t *)&retval);
  123. break;
  124. #endif // UW
  125. case SYS_fork:
  126. err = sys_fork(tf, (pid_t*)&retval);
  127. break;
  128. case SYS_execv:
  129. err = sys_execv((char *)tf->tf_a0,(userptr_t)tf->tf_a1);
  130. break;
  131. default:
  132. kprintf("Unknown syscall %d\n", callno);
  133. err = ENOSYS;
  134. break;
  135. }
  136. if (err)
  137. {
  138. /*
  139. * Return the error code. This gets converted at
  140. * userlevel to a return value of -1 and the error
  141. * code in errno.
  142. */
  143. tf->tf_v0 = err;
  144. tf->tf_a3 = 1; /* signal an error */
  145. }
  146. else
  147. {
  148. /* Success. */
  149. tf->tf_v0 = retval;
  150. tf->tf_a3 = 0; /* signal no error */
  151. }
  152. /*
  153. * Now, advance the program counter, to avoid restarting
  154. * the syscall over and over again.
  155. */
  156. tf->tf_epc += 4;
  157. /* Make sure the syscall code didn't forget to lower spl */
  158. KASSERT(curthread->t_curspl == 0);
  159. /* ...or leak any spinlocks */
  160. KASSERT(curthread->t_iplhigh_count == 0);
  161. }
  162. /*
  163. * Enter user mode for a newly forked process.
  164. *
  165. * This function is provided as a reminder. You need to write
  166. * both it and the code that calls it.
  167. *
  168. * Thus, you can trash it and do things another way if you prefer.
  169. */
  170. void enter_forked_process(void * trap, unsigned long x)
  171. {
  172. (void)x;
  173. struct trapframe * tf = (struct trapframe *)trap;
  174. struct trapframe childframe = *tf;
  175. childframe.tf_v0 = 0;
  176. childframe.tf_epc += 4;
  177. childframe.tf_a3 = 0;
  178. mips_usermode(&childframe);
  179. }