00001 /* 00002 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009 00003 * The President and Fellows of Harvard College. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the University nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 */ 00029 00030 #include <types.h> 00031 #include <kern/errno.h> 00032 #include <kern/syscall.h> 00033 #include <lib.h> 00034 #include <mips/trapframe.h> 00035 #include <thread.h> 00036 #include <current.h> 00037 #include <syscall.h> 00038 00039 00040 /* 00041 * System call dispatcher. 00042 * 00043 * A pointer to the trapframe created during exception entry (in 00044 * exception.S) is passed in. 00045 * 00046 * The calling conventions for syscalls are as follows: Like ordinary 00047 * function calls, the first 4 32-bit arguments are passed in the 4 00048 * argument registers a0-a3. 64-bit arguments are passed in *aligned* 00049 * pairs of registers, that is, either a0/a1 or a2/a3. This means that 00050 * if the first argument is 32-bit and the second is 64-bit, a1 is 00051 * unused. 00052 * 00053 * This much is the same as the calling conventions for ordinary 00054 * function calls. In addition, the system call number is passed in 00055 * the v0 register. 00056 * 00057 * On successful return, the return value is passed back in the v0 00058 * register, or v0 and v1 if 64-bit. This is also like an ordinary 00059 * function call, and additionally the a3 register is also set to 0 to 00060 * indicate success. 00061 * 00062 * On an error return, the error code is passed back in the v0 00063 * register, and the a3 register is set to 1 to indicate failure. 00064 * (Userlevel code takes care of storing the error code in errno and 00065 * returning the value -1 from the actual userlevel syscall function. 00066 * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.) 00067 * 00068 * Upon syscall return the program counter stored in the trapframe 00069 * must be incremented by one instruction; otherwise the exception 00070 * return code will restart the "syscall" instruction and the system 00071 * call will repeat forever. 00072 * 00073 * If you run out of registers (which happens quickly with 64-bit 00074 * values) further arguments must be fetched from the user-level 00075 * stack, starting at sp+16 to skip over the slots for the 00076 * registerized values, with copyin(). 00077 */ 00078 void 00079 syscall(struct trapframe *tf) 00080 { 00081 int callno; 00082 int32_t retval; 00083 int err; 00084 00085 KASSERT(curthread != NULL); 00086 KASSERT(curthread->t_curspl == 0); 00087 KASSERT(curthread->t_iplhigh_count == 0); 00088 00089 callno = tf->tf_v0; 00090 00091 /* 00092 * Initialize retval to 0. Many of the system calls don't 00093 * really return a value, just 0 for success and -1 on 00094 * error. Since retval is the value returned on success, 00095 * initialize it to 0 by default; thus it's not necessary to 00096 * deal with it except for calls that return other values, 00097 * like write. 00098 */ 00099 00100 retval = 0; 00101 00102 switch (callno) { 00103 case SYS_reboot: 00104 err = sys_reboot(tf->tf_a0); 00105 break; 00106 00107 case SYS___time: 00108 err = sys___time((userptr_t)tf->tf_a0, 00109 (userptr_t)tf->tf_a1); 00110 break; 00111 #ifdef UW 00112 case SYS_write: 00113 err = sys_write((int)tf->tf_a0, 00114 (userptr_t)tf->tf_a1, 00115 (int)tf->tf_a2, 00116 (int *)(&retval)); 00117 break; 00118 case SYS__exit: 00119 sys__exit((int)tf->tf_a0); 00120 /* sys__exit does not return, execution should not get here */ 00121 panic("unexpected return from sys__exit"); 00122 break; 00123 case SYS_getpid: 00124 err = sys_getpid((pid_t *)&retval); 00125 break; 00126 case SYS_waitpid: 00127 err = sys_waitpid((pid_t)tf->tf_a0, 00128 (userptr_t)tf->tf_a1, 00129 (int)tf->tf_a2, 00130 (pid_t *)&retval); 00131 break; 00132 #endif // UW 00133 00134 /* Add stuff here */ 00135 00136 default: 00137 kprintf("Unknown syscall %d\n", callno); 00138 err = ENOSYS; 00139 break; 00140 } 00141 00142 00143 if (err) { 00144 /* 00145 * Return the error code. This gets converted at 00146 * userlevel to a return value of -1 and the error 00147 * code in errno. 00148 */ 00149 tf->tf_v0 = err; 00150 tf->tf_a3 = 1; /* signal an error */ 00151 } 00152 else { 00153 /* Success. */ 00154 tf->tf_v0 = retval; 00155 tf->tf_a3 = 0; /* signal no error */ 00156 } 00157 00158 /* 00159 * Now, advance the program counter, to avoid restarting 00160 * the syscall over and over again. 00161 */ 00162 00163 tf->tf_epc += 4; 00164 00165 /* Make sure the syscall code didn't forget to lower spl */ 00166 KASSERT(curthread->t_curspl == 0); 00167 /* ...or leak any spinlocks */ 00168 KASSERT(curthread->t_iplhigh_count == 0); 00169 } 00170 00171 /* 00172 * Enter user mode for a newly forked process. 00173 * 00174 * This function is provided as a reminder. You need to write 00175 * both it and the code that calls it. 00176 * 00177 * Thus, you can trash it and do things another way if you prefer. 00178 */ 00179 void 00180 enter_forked_process(struct trapframe *tf) 00181 { 00182 (void)tf; 00183 }