syscall.c (3980B)
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(uintp addr, int *ip) 19 { 20 if(addr >= proc->sz || addr+sizeof(int) > proc->sz) 21 return -1; 22 *ip = *(int*)(addr); 23 return 0; 24 } 25 26 int 27 fetchuintp(uintp addr, uintp *ip) 28 { 29 if(addr >= proc->sz || addr+sizeof(uintp) > proc->sz) 30 return -1; 31 *ip = *(uintp*)(addr); 32 return 0; 33 } 34 35 // Fetch the nul-terminated string at addr from the current process. 36 // Doesn't actually copy the string - just sets *pp to point at it. 37 // Returns length of string, not including nul. 38 int 39 fetchstr(uintp addr, char **pp) 40 { 41 char *s, *ep; 42 43 if(addr >= proc->sz) 44 return -1; 45 *pp = (char*)addr; 46 ep = (char*)proc->sz; 47 for(s = *pp; s < ep; s++) 48 if(*s == 0) 49 return s - *pp; 50 return -1; 51 } 52 53 #if X64 54 // arguments passed in registers on x64 55 static uintp 56 fetcharg(int n) 57 { 58 switch (n) { 59 case 0: return proc->tf->rdi; 60 case 1: return proc->tf->rsi; 61 case 2: return proc->tf->rdx; 62 case 3: return proc->tf->rcx; 63 case 4: return proc->tf->r8; 64 case 5: return proc->tf->r9; 65 } 66 } 67 68 int 69 argint(int n, int *ip) 70 { 71 *ip = fetcharg(n); 72 return 0; 73 } 74 75 int 76 arguintp(int n, uintp *ip) 77 { 78 *ip = fetcharg(n); 79 return 0; 80 } 81 #else 82 // Fetch the nth 32-bit system call argument. 83 int 84 argint(int n, int *ip) 85 { 86 return fetchint(proc->tf->esp + 4 + 4*n, ip); 87 } 88 89 int 90 arguintp(int n, uintp *ip) 91 { 92 return fetchuintp(proc->tf->esp + sizeof(uintp) + sizeof(uintp)*n, ip); 93 } 94 #endif 95 96 // Fetch the nth word-sized system call argument as a pointer 97 // to a block of memory of size n bytes. Check that the pointer 98 // lies within the process address space. 99 int 100 argptr(int n, char **pp, int size) 101 { 102 uintp i; 103 104 if(arguintp(n, &i) < 0) 105 return -1; 106 if(i >= proc->sz || i+size > proc->sz) 107 return -1; 108 *pp = (char*)i; 109 return 0; 110 } 111 112 // Fetch the nth word-sized system call argument as a string pointer. 113 // Check that the pointer is valid and the string is nul-terminated. 114 // (There is no shared writable memory, so the string can't change 115 // between this check and being used by the kernel.) 116 int 117 argstr(int n, char **pp) 118 { 119 uintp addr; 120 if(arguintp(n, &addr) < 0) 121 return -1; 122 return fetchstr(addr, pp); 123 } 124 125 extern int sys_chdir(void); 126 extern int sys_close(void); 127 extern int sys_dup(void); 128 extern int sys_exec(void); 129 extern int sys_exit(void); 130 extern int sys_fork(void); 131 extern int sys_fstat(void); 132 extern int sys_getpid(void); 133 extern int sys_kill(void); 134 extern int sys_link(void); 135 extern int sys_mkdir(void); 136 extern int sys_mknod(void); 137 extern int sys_open(void); 138 extern int sys_pipe(void); 139 extern int sys_read(void); 140 extern int sys_sbrk(void); 141 extern int sys_sleep(void); 142 extern int sys_unlink(void); 143 extern int sys_wait(void); 144 extern int sys_write(void); 145 extern int sys_uptime(void); 146 147 static int (*syscalls[])(void) = { 148 [SYS_fork] sys_fork, 149 [SYS_exit] sys_exit, 150 [SYS_wait] sys_wait, 151 [SYS_pipe] sys_pipe, 152 [SYS_read] sys_read, 153 [SYS_kill] sys_kill, 154 [SYS_exec] sys_exec, 155 [SYS_fstat] sys_fstat, 156 [SYS_chdir] sys_chdir, 157 [SYS_dup] sys_dup, 158 [SYS_getpid] sys_getpid, 159 [SYS_sbrk] sys_sbrk, 160 [SYS_sleep] sys_sleep, 161 [SYS_uptime] sys_uptime, 162 [SYS_open] sys_open, 163 [SYS_write] sys_write, 164 [SYS_mknod] sys_mknod, 165 [SYS_unlink] sys_unlink, 166 [SYS_link] sys_link, 167 [SYS_mkdir] sys_mkdir, 168 [SYS_close] sys_close, 169 }; 170 171 void 172 syscall(void) 173 { 174 int num; 175 176 num = proc->tf->eax; 177 if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { 178 proc->tf->eax = syscalls[num](); 179 } else { 180 cprintf("%d %s: unknown sys call %d\n", 181 proc->pid, proc->name, num); 182 proc->tf->eax = -1; 183 } 184 }