syscall.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*****************************************************************
  2. * syscall.c
  3. * adapted from MIT xv6 by Zhiyi Huang, [email protected]
  4. * University of Otago
  5. *
  6. ********************************************************************/
  7. #include "types.h"
  8. #include "defs.h"
  9. #include "param.h"
  10. #include "memlayout.h"
  11. #include "mmu.h"
  12. #include "proc.h"
  13. #include "arm.h"
  14. #include "syscall.h"
  15. // User code makes a system call with INT T_SYSCALL.
  16. // System call number in %eax.
  17. // Arguments on the stack, from the user call to the C
  18. // library system call function. The saved user %esp points
  19. // to a saved program counter, and then the first argument.
  20. // Fetch the int at addr from the current process.
  21. int
  22. fetchint(uint addr, int *ip)
  23. {
  24. if(addr >= curr_proc->sz || addr+4 > curr_proc->sz)
  25. return -1;
  26. *ip = *(int*)(addr);
  27. return 0;
  28. }
  29. // Fetch the nul-terminated string at addr from the current process.
  30. // Doesn't actually copy the string - just sets *pp to point at it.
  31. // Returns length of string, not including nul.
  32. int
  33. fetchstr(uint addr, char **pp)
  34. {
  35. char *s, *ep;
  36. if(addr >= curr_proc->sz)
  37. return -1;
  38. *pp = (char*)addr;
  39. ep = (char*)curr_proc->sz;
  40. for(s = *pp; s < ep; s++)
  41. if(*s == 0)
  42. return s - *pp;
  43. return -1;
  44. }
  45. // Fetch the nth 32-bit system call argument.
  46. int
  47. argint(int n, int *ip)
  48. {
  49. return fetchint(curr_proc->tf->sp + 4*n, ip);
  50. }
  51. // Fetch the nth word-sized system call argument as a pointer
  52. // to a block of memory of size n bytes. Check that the pointer
  53. // lies within the process address space.
  54. int
  55. argptr(int n, char **pp, int size)
  56. {
  57. int i;
  58. if(argint(n, &i) < 0)
  59. return -1;
  60. if((uint)i >= curr_proc->sz || (uint)i+size > curr_proc->sz)
  61. return -1;
  62. *pp = (char*)i;
  63. return 0;
  64. }
  65. // Fetch the nth word-sized system call argument as a string pointer.
  66. // Check that the pointer is valid and the string is nul-terminated.
  67. // (There is no shared writable memory, so the string can't change
  68. // between this check and being used by the kernel.)
  69. int
  70. argstr(int n, char **pp)
  71. {
  72. int addr;
  73. if(argint(n, &addr) < 0)
  74. return -1;
  75. return fetchstr(addr, pp);
  76. }
  77. extern int sys_chdir(void);
  78. extern int sys_close(void);
  79. extern int sys_dup(void);
  80. extern int sys_exec(void);
  81. extern int sys_exit(void);
  82. extern int sys_fork(void);
  83. extern int sys_fstat(void);
  84. extern int sys_getpid(void);
  85. extern int sys_kill(void);
  86. extern int sys_link(void);
  87. extern int sys_mkdir(void);
  88. extern int sys_mknod(void);
  89. extern int sys_open(void);
  90. extern int sys_pipe(void);
  91. extern int sys_read(void);
  92. extern int sys_sbrk(void);
  93. extern int sys_sleep(void);
  94. extern int sys_unlink(void);
  95. extern int sys_wait(void);
  96. extern int sys_write(void);
  97. extern int sys_uptime(void);
  98. static int (*syscalls[])(void) = {
  99. [SYS_fork] sys_fork,
  100. [SYS_exit] sys_exit,
  101. [SYS_wait] sys_wait,
  102. [SYS_pipe] sys_pipe,
  103. [SYS_read] sys_read,
  104. [SYS_kill] sys_kill,
  105. [SYS_exec] sys_exec,
  106. [SYS_fstat] sys_fstat,
  107. [SYS_chdir] sys_chdir,
  108. [SYS_dup] sys_dup,
  109. [SYS_getpid] sys_getpid,
  110. [SYS_sbrk] sys_sbrk,
  111. [SYS_sleep] sys_sleep,
  112. [SYS_uptime] sys_uptime,
  113. [SYS_open] sys_open,
  114. [SYS_write] sys_write,
  115. [SYS_mknod] sys_mknod,
  116. [SYS_unlink] sys_unlink,
  117. [SYS_link] sys_link,
  118. [SYS_mkdir] sys_mkdir,
  119. [SYS_close] sys_close,
  120. };
  121. void
  122. syscall(void)
  123. {
  124. int num;
  125. num = curr_proc->tf->r0;
  126. if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
  127. // cprintf("\n%d %s: sys call %d syscall address %x\n",
  128. // curr_proc->pid, curr_proc->name, num, syscalls[num]);
  129. if(num == SYS_exec) {
  130. if(syscalls[num]() == -1) curr_proc->tf->r0 = -1;
  131. } else curr_proc->tf->r0 = syscalls[num]();
  132. } else {
  133. cprintf("%d %s: unknown sys call %d\n",
  134. curr_proc->pid, curr_proc->name, num);
  135. curr_proc->tf->r0 = -1;
  136. }
  137. }