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 | |