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