Mercurial > hg > Members > anatofuz > CbC_xv6
comparison src/syscall.c @ 0:83c23a36980d
Init
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 26 May 2017 23:11:05 +0900 |
parents | |
children | 397e74cbf14e |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:83c23a36980d |
---|---|
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 "arm.h" | |
8 #include "syscall.h" | |
9 | |
10 // User code makes a system call with INT T_SYSCALL. System call number | |
11 // in r0. Arguments on the stack, from the user call to the C library | |
12 // system call function. The saved user sp points to the first argument. | |
13 | |
14 // Fetch the int at addr from the current process. | |
15 int fetchint(uint addr, int *ip) | |
16 { | |
17 if(addr >= proc->sz || addr+4 > proc->sz) { | |
18 return -1; | |
19 } | |
20 | |
21 *ip = *(int*)(addr); | |
22 return 0; | |
23 } | |
24 | |
25 // Fetch the nul-terminated string at addr from the current process. | |
26 // Doesn't actually copy the string - just sets *pp to point at it. | |
27 // Returns length of string, not including nul. | |
28 int fetchstr(uint addr, char **pp) | |
29 { | |
30 char *s, *ep; | |
31 | |
32 if(addr >= proc->sz) { | |
33 return -1; | |
34 } | |
35 | |
36 *pp = (char*)addr; | |
37 ep = (char*)proc->sz; | |
38 | |
39 for(s = *pp; s < ep; s++) { | |
40 if(*s == 0) { | |
41 return s - *pp; | |
42 } | |
43 } | |
44 | |
45 return -1; | |
46 } | |
47 | |
48 // Fetch the nth (starting from 0) 32-bit system call argument. | |
49 // In our ABI, r0 contains system call index, r1-r4 contain parameters. | |
50 // now we support system calls with at most 4 parameters. | |
51 int argint(int n, int *ip) | |
52 { | |
53 if (n > 3) { | |
54 panic ("too many system call parameters\n"); | |
55 } | |
56 | |
57 *ip = *(&proc->tf->r1 + n); | |
58 | |
59 return 0; | |
60 } | |
61 | |
62 // Fetch the nth word-sized system call argument as a pointer | |
63 // to a block of memory of size n bytes. Check that the pointer | |
64 // lies within the process address space. | |
65 int argptr(int n, char **pp, int size) | |
66 { | |
67 int i; | |
68 | |
69 if(argint(n, &i) < 0) { | |
70 return -1; | |
71 } | |
72 | |
73 if((uint)i >= proc->sz || (uint)i+size > proc->sz) { | |
74 return -1; | |
75 } | |
76 | |
77 *pp = (char*)i; | |
78 return 0; | |
79 } | |
80 | |
81 // Fetch the nth word-sized system call argument as a string pointer. | |
82 // Check that the pointer is valid and the string is nul-terminated. | |
83 // (There is no shared writable memory, so the string can't change | |
84 // between this check and being used by the kernel.) | |
85 int argstr(int n, char **pp) | |
86 { | |
87 int addr; | |
88 | |
89 if(argint(n, &addr) < 0) { | |
90 return -1; | |
91 } | |
92 | |
93 return fetchstr(addr, pp); | |
94 } | |
95 | |
96 extern int sys_chdir(void); | |
97 extern int sys_close(void); | |
98 extern int sys_dup(void); | |
99 extern int sys_exec(void); | |
100 extern int sys_exit(void); | |
101 extern int sys_fork(void); | |
102 extern int sys_fstat(void); | |
103 extern int sys_getpid(void); | |
104 extern int sys_kill(void); | |
105 extern int sys_link(void); | |
106 extern int sys_mkdir(void); | |
107 extern int sys_mknod(void); | |
108 extern int sys_open(void); | |
109 extern int sys_pipe(void); | |
110 extern int sys_read(void); | |
111 extern int sys_sbrk(void); | |
112 extern int sys_sleep(void); | |
113 extern int sys_unlink(void); | |
114 extern int sys_wait(void); | |
115 extern int sys_write(void); | |
116 extern int sys_uptime(void); | |
117 | |
118 static int (*syscalls[])(void) = { | |
119 [SYS_fork] sys_fork, | |
120 [SYS_exit] sys_exit, | |
121 [SYS_wait] sys_wait, | |
122 [SYS_pipe] sys_pipe, | |
123 [SYS_read] sys_read, | |
124 [SYS_kill] sys_kill, | |
125 [SYS_exec] sys_exec, | |
126 [SYS_fstat] sys_fstat, | |
127 [SYS_chdir] sys_chdir, | |
128 [SYS_dup] sys_dup, | |
129 [SYS_getpid] sys_getpid, | |
130 [SYS_sbrk] sys_sbrk, | |
131 [SYS_sleep] sys_sleep, | |
132 [SYS_uptime] sys_uptime, | |
133 [SYS_open] sys_open, | |
134 [SYS_write] sys_write, | |
135 [SYS_mknod] sys_mknod, | |
136 [SYS_unlink] sys_unlink, | |
137 [SYS_link] sys_link, | |
138 [SYS_mkdir] sys_mkdir, | |
139 [SYS_close] sys_close, | |
140 }; | |
141 | |
142 void syscall(void) | |
143 { | |
144 int num; | |
145 int ret; | |
146 | |
147 num = proc->tf->r0; | |
148 | |
149 //cprintf ("syscall(%d) from %s(%d)\n", num, proc->name, proc->pid); | |
150 | |
151 if((num > 0) && (num <= NELEM(syscalls)) && syscalls[num]) { | |
152 ret = syscalls[num](); | |
153 | |
154 // in ARM, parameters to main (argc, argv) are passed in r0 and r1 | |
155 // do not set the return value if it is SYS_exec (the user program | |
156 // anyway does not expect us to return anything). | |
157 if (num != SYS_exec) { | |
158 proc->tf->r0 = ret; | |
159 } | |
160 } else { | |
161 cprintf("%d %s: unknown sys call %d\n", proc->pid, proc->name, num); | |
162 proc->tf->r0 = -1; | |
163 } | |
164 } |