/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- syscall
- enter_forked_process
1 /*
2 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
3 * The President and Fellows of Harvard College.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <types.h>
31 #include <kern/errno.h>
32 #include <kern/syscall.h>
33 #include <lib.h>
34 #include <mips/trapframe.h>
35 #include <thread.h>
36 #include <current.h>
37 #include <syscall.h>
38
39
40 /*
41 * System call dispatcher.
42 *
43 * A pointer to the trapframe created during exception entry (in
44 * exception.S) is passed in.
45 *
46 * The calling conventions for syscalls are as follows: Like ordinary
47 * function calls, the first 4 32-bit arguments are passed in the 4
48 * argument registers a0-a3. 64-bit arguments are passed in *aligned*
49 * pairs of registers, that is, either a0/a1 or a2/a3. This means that
50 * if the first argument is 32-bit and the second is 64-bit, a1 is
51 * unused.
52 *
53 * This much is the same as the calling conventions for ordinary
54 * function calls. In addition, the system call number is passed in
55 * the v0 register.
56 *
57 * On successful return, the return value is passed back in the v0
58 * register, or v0 and v1 if 64-bit. This is also like an ordinary
59 * function call, and additionally the a3 register is also set to 0 to
60 * indicate success.
61 *
62 * On an error return, the error code is passed back in the v0
63 * register, and the a3 register is set to 1 to indicate failure.
64 * (Userlevel code takes care of storing the error code in errno and
65 * returning the value -1 from the actual userlevel syscall function.
66 * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.)
67 *
68 * Upon syscall return the program counter stored in the trapframe
69 * must be incremented by one instruction; otherwise the exception
70 * return code will restart the "syscall" instruction and the system
71 * call will repeat forever.
72 *
73 * If you run out of registers (which happens quickly with 64-bit
74 * values) further arguments must be fetched from the user-level
75 * stack, starting at sp+16 to skip over the slots for the
76 * registerized values, with copyin().
77 */
78 void
79 syscall(struct trapframe *tf)
80 {
81 int callno;
82 int32_t retval;
83 int err;
84
85 KASSERT(curthread != NULL);
86 KASSERT(curthread->t_curspl == 0);
87 KASSERT(curthread->t_iplhigh_count == 0);
88
89 callno = tf->tf_v0;
90
91 /*
92 * Initialize retval to 0. Many of the system calls don't
93 * really return a value, just 0 for success and -1 on
94 * error. Since retval is the value returned on success,
95 * initialize it to 0 by default; thus it's not necessary to
96 * deal with it except for calls that return other values,
97 * like write.
98 */
99
100 retval = 0;
101
102 switch (callno) {
103 case SYS_reboot:
104 err = sys_reboot(tf->tf_a0);
105 break;
106
107 case SYS___time:
108 err = sys___time((userptr_t)tf->tf_a0,
109 (userptr_t)tf->tf_a1);
110 break;
111 #ifdef UW
112 case SYS_write:
113 err = sys_write((int)tf->tf_a0,
114 (userptr_t)tf->tf_a1,
115 (int)tf->tf_a2,
116 (int *)(&retval));
117 break;
118 case SYS__exit:
119 sys__exit((int)tf->tf_a0);
120 /* sys__exit does not return, execution should not get here */
121 panic("unexpected return from sys__exit");
122 break;
123 case SYS_getpid:
124 err = sys_getpid((pid_t *)&retval);
125 break;
126 case SYS_waitpid:
127 err = sys_waitpid((pid_t)tf->tf_a0,
128 (userptr_t)tf->tf_a1,
129 (int)tf->tf_a2,
130 (pid_t *)&retval);
131 break;
132 #endif // UW
133
134 /* Add stuff here */
135
136 default:
137 kprintf("Unknown syscall %d\n", callno);
138 err = ENOSYS;
139 break;
140 }
141
142
143 if (err) {
144 /*
145 * Return the error code. This gets converted at
146 * userlevel to a return value of -1 and the error
147 * code in errno.
148 */
149 tf->tf_v0 = err;
150 tf->tf_a3 = 1; /* signal an error */
151 }
152 else {
153 /* Success. */
154 tf->tf_v0 = retval;
155 tf->tf_a3 = 0; /* signal no error */
156 }
157
158 /*
159 * Now, advance the program counter, to avoid restarting
160 * the syscall over and over again.
161 */
162
163 tf->tf_epc += 4;
164
165 /* Make sure the syscall code didn't forget to lower spl */
166 KASSERT(curthread->t_curspl == 0);
167 /* ...or leak any spinlocks */
168 KASSERT(curthread->t_iplhigh_count == 0);
169 }
170
171 /*
172 * Enter user mode for a newly forked process.
173 *
174 * This function is provided as a reminder. You need to write
175 * both it and the code that calls it.
176 *
177 * Thus, you can trash it and do things another way if you prefer.
178 */
179 void
180 enter_forked_process(struct trapframe *tf)
181 {
182 (void)tf;
183 }