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 if(addr >= proc->sz || addr+4 > proc->sz) 21 return -1; 22 *ip = *(int*)(addr); 23 return 0; 24 } 25 26 // Fetch the nul-terminated string at addr from the current process. 27 // Doesn't actually copy the string - just sets *pp to point at it. 28 // Returns length of string, not including nul. 29 int 30 fetchstr(uint addr, char **pp) 31 { 32 char *s, *ep; 33 34 if(addr >= proc->sz) 35 return -1; 36 *pp = (char*)addr; 37 ep = (char*)proc->sz; 38 for(s = *pp; s < ep; s++) 39 if(*s == 0) 40 return s - *pp; 41 return -1; 42 } 43 44 // Fetch the nth 32-bit system call argument. 45 int 46 argint(int n, int *ip) 47 { 48 return fetchint(proc->tf->esp + 4 + 4*n, ip); 49 } 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 59 if(argint(n, &i) < 0) 60 return -1; 61 if((uint)i >= proc->sz || (uint)i+size > proc->sz) 62 return -1; 63 *pp = (char*)i; 64 return 0; 65 } 66 67 // Fetch the nth word-sized system call argument as a string pointer. 68 // Check that the pointer is valid and the string is nul-terminated. 69 // (There is no shared writable memory, so the string can't change 70 // between this check and being used by the kernel.) 71 int 72 argstr(int n, char **pp) 73 { 74 int addr; 75 if(argint(n, &addr) < 0) 76 return -1; 77 return fetchstr(addr, pp); 78 } 79 80 extern int sys_chdir(void); 81 extern int sys_close(void); 82 extern int sys_dup(void); 83 extern int sys_exec(void); 84 extern int sys_exit(void); 85 extern int sys_fork(void); 86 extern int sys_fstat(void); 87 extern int sys_getpid(void); 88 extern int sys_kill(void); 89 extern int sys_link(void); 90 extern int sys_mkdir(void); 91 extern int sys_mknod(void); 92 extern int sys_open(void); 93 extern int sys_pipe(void); 94 extern int sys_read(void); 95 extern int sys_sbrk(void); 96 extern int sys_sleep(void); 97 extern int sys_unlink(void); 98 extern int sys_wait(void); 99 extern int sys_write(void); 100 extern int sys_uptime(void); 101 102 static int (*syscalls[])(void) = { 103 [SYS_fork] sys_fork, 104 [SYS_exit] sys_exit, 105 [SYS_wait] sys_wait, 106 [SYS_pipe] sys_pipe, 107 [SYS_read] sys_read, 108 [SYS_kill] sys_kill, 109 [SYS_exec] sys_exec, 110 [SYS_fstat] sys_fstat, 111 [SYS_chdir] sys_chdir, 112 [SYS_dup] sys_dup, 113 [SYS_getpid] sys_getpid, 114 [SYS_sbrk] sys_sbrk, 115 [SYS_sleep] sys_sleep, 116 [SYS_uptime] sys_uptime, 117 [SYS_open] sys_open, 118 [SYS_write] sys_write, 119 [SYS_mknod] sys_mknod, 120 [SYS_unlink] sys_unlink, 121 [SYS_link] sys_link, 122 [SYS_mkdir] sys_mkdir, 123 [SYS_close] sys_close, 124 }; 125 126 void 127 syscall(void) 128 { 129 int num; 130 131 num = proc->tf->eax; 132 if(num >= 0 && num < SYS_open && syscalls[num]) { 133 proc->tf->eax = syscalls[num](); 134 } else if (num >= SYS_open && num < NELEM(syscalls) && syscalls[num]) { 135 proc->tf->eax = syscalls[num](); 136 } else { 137 cprintf("%d %s: unknown sys call %d\n", 138 proc->pid, proc->name, num); 139 proc->tf->eax = -1; 140 } 141 } 142