xv6

port of xv6 to x86-64
git clone http://frotz.net/git/xv6.git
Log | Files | Refs | README | LICENSE

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 }