// Dispatches to the correct kernel function, passing the arguments. int32_t syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5) { // Call the function corresponding to the 'syscallno' parameter. // Return any appropriate return value. // LAB 3: Your code here. /*stone's solution for lab3-B*/ int32_t ret = -E_INVAL; switch (syscallno){ case SYS_cputs: sys_cputs((char*)a1, a2); ret = 0; break; case SYS_cgetc: ret = sys_cgetc(); break; case SYS_getenvid: ret = sys_getenvid(); break; case SYS_env_destroy: ret = sys_env_destroy(a1); break; case SYS_map_kernel_page: ret = sys_map_kernel_page((void*)a1, (void*)a2); break; case SYS_sbrk: ret = sys_sbrk(a1); break; default: break; } return ret; //panic("syscall not implemented"); }
// Dispatches to the correct kernel function, passing the arguments. int32_t syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5) { // Call the function corresponding to the 'syscallno' parameter. // Return any appropriate return value. // LAB 3: Your code here. int32_t ret = -E_INVAL; switch(syscallno) { case SYS_cputs: sys_cputs((char *)a1, a2); break; case SYS_cgetc: ret = sys_cgetc(); break; case SYS_getenvid: ret = sys_getenvid(); break; case SYS_env_destroy: ret = sys_env_destroy(a1); break; case SYS_yield: sys_yield(); ret = 0; break; case SYS_map_kernel_page: ret = sys_map_kernel_page((void *)a1, (void *)a2); break; case SYS_sbrk: ret = sys_sbrk(a1); break; case SYS_exofork: ret = sys_exofork(); break; case SYS_env_set_status: ret = sys_env_set_status(a1,a2); break; case SYS_page_alloc: ret = sys_page_alloc(a1,(void*)a2,a3); break; case SYS_page_map: ret = sys_page_map(a1,(void*)a2,a3,(void*)a4,a5); break; case SYS_page_unmap: ret = sys_page_unmap(a1,(void*)a2); break; case SYS_env_set_pgfault_upcall: ret = sys_env_set_pgfault_upcall(a1,(void*)a2); break; case SYS_ipc_try_send: ret = sys_ipc_try_send(a1,a2,(void*)a3,a4); break; case SYS_ipc_recv: ret = sys_ipc_recv((void*)a1); } return ret; // panic("syscall not implemented"); }
// Dispatches to the correct kernel function, passing the arguments. int32_t syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5) { // Call the function corresponding to the 'syscallno' parameter. // Return any appropriate return value. // LAB 3: Your code here. switch (syscallno){ case SYS_getenvid: return sys_getenvid(); case SYS_cputs: sys_cputs((const char*)a1, a2); return 0; case SYS_cgetc: return sys_cgetc(); case SYS_env_destroy: return sys_env_destroy(a1); case SYS_map_kernel_page: return sys_map_kernel_page((void*)a1, (void*)a2); case SYS_sbrk: return sys_sbrk(a1); case SYS_yield: sys_yield(); return 0; case SYS_exofork: return sys_exofork(); case SYS_env_set_status: return sys_env_set_status((envid_t)a1, (int)a2); case SYS_page_alloc: return sys_page_alloc((envid_t)a1, (void *)a2, (int)a3); case SYS_page_map: return sys_page_map((envid_t)*((uint32_t*)a1), (void*)*((uint32_t*)a1+1), (envid_t)*((uint32_t*)a1+2), (void*)*((uint32_t*)a1+3), (int)*((uint32_t*)a1+4)); case SYS_page_unmap: return sys_page_unmap((envid_t)a1, (void*)a2); case SYS_env_set_priority: return sys_env_set_priority((envid_t)a1, (int) a2); case SYS_env_set_pgfault_upcall: return sys_env_set_pgfault_upcall((envid_t)a1, (void*)a2); case SYS_ipc_recv: return sys_ipc_recv((void*)a1); case SYS_ipc_try_send: return sys_ipc_try_send((envid_t)a1, a2, (void*)a3, (int)a4); default: return -E_INVAL; } }
ssize_t syscall_handler(uint32_t sys_nr, ...) { ssize_t ret = -EINVAL; va_list vl; va_start(vl, sys_nr); switch(sys_nr) { case __NR_exit: sys_exit(va_arg(vl, uint32_t)); ret = 0; break; case __NR_write: { int fd = va_arg(vl, int); const char* buf = va_arg(vl, const char*); size_t len = va_arg(vl, size_t); ret = sys_write(fd, buf, len); break; } //TODO: Currently, we ignore file descriptors case __NR_open: case __NR_close: ret = 0; break; case __NR_sbrk: { int incr = va_arg(vl, int); ret = sys_sbrk(incr); break; } default: kprintf("invalid system call: %u\n", sys_nr); ret = -ENOSYS; break; }; va_end(vl); return ret; }
/* * System call dispatcher. * * A pointer to the trapframe created during exception entry (in * exception-*.S) is passed in. * * The calling conventions for syscalls are as follows: Like ordinary * function calls, the first 4 32-bit arguments are passed in the 4 * argument registers a0-a3. 64-bit arguments are passed in *aligned* * pairs of registers, that is, either a0/a1 or a2/a3. This means that * if the first argument is 32-bit and the second is 64-bit, a1 is * unused. * * This much is the same as the calling conventions for ordinary * function calls. In addition, the system call number is passed in * the v0 register. * * On successful return, the return value is passed back in the v0 * register, or v0 and v1 if 64-bit. This is also like an ordinary * function call, and additionally the a3 register is also set to 0 to * indicate success. * * On an error return, the error code is passed back in the v0 * register, and the a3 register is set to 1 to indicate failure. * (Userlevel code takes care of storing the error code in errno and * returning the value -1 from the actual userlevel syscall function. * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.) * * Upon syscall return the program counter stored in the trapframe * must be incremented by one instruction; otherwise the exception * return code will restart the "syscall" instruction and the system * call will repeat forever. * * If you run out of registers (which happens quickly with 64-bit * values) further arguments must be fetched from the user-level * stack, starting at sp+16 to skip over the slots for the * registerized values, with copyin(). */ void syscall(struct trapframe *tf) { int callno; int32_t retval; int err; KASSERT(curthread != NULL); KASSERT(curthread->t_curspl == 0); KASSERT(curthread->t_iplhigh_count == 0); callno = tf->tf_v0; /* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */ retval = 0; off_t pos, new_pos; switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break; case SYS___time: err = sys___time((userptr_t) tf->tf_a0, (userptr_t) tf->tf_a1); break; case SYS_open: err = sys_open((userptr_t) tf->tf_a0, (int) tf->tf_a1, (int) tf->tf_a2, &retval); break; case SYS_read: err = sys_read((int) tf->tf_a0, (userptr_t) tf->tf_a1, (int) tf->tf_a2, &retval); break; case SYS_write: err = sys_write((int) tf->tf_a0, (userptr_t) tf->tf_a1, (int) tf->tf_a2, &retval); break; case SYS_lseek: pos = (((off_t)tf->tf_a2 << 32) | tf->tf_a3); err = sys_lseek((userptr_t) tf->tf_a0, pos, (userptr_t)(tf->tf_sp+16), &new_pos); if (err == 0) { retval = (int32_t)(new_pos >> 32); tf->tf_v1 = (int32_t)(new_pos & 0xFFFFFFFF); } break; case SYS_close: err = sys_close((userptr_t) tf->tf_a0, &retval); break; case SYS_dup2: err = sys_dup2((userptr_t) tf->tf_a0, (userptr_t) tf->tf_a1, &retval); break; case SYS_getpid: err = sys_getpid(&retval); break; case SYS_sbrk: err = sys_sbrk((userptr_t)tf->tf_a0, &retval); break; case SYS_fork: err = sys_fork(tf, &retval); break; case SYS_execv: err = sys_execv((userptr_t) tf->tf_a0, (userptr_t) tf->tf_a1, &retval); retval = 0; break; case SYS_waitpid: err = sys_waitpid((userptr_t) tf->tf_a0, (userptr_t) tf->tf_a1, (userptr_t) tf->tf_a2, &retval); break; case SYS__exit: //kprintf("TEMPPPP:Exit has been called! \n"); err = sys__exit((int) tf->tf_a0); break; /* Add stuff here */ default: kprintf("Unknown syscall %d\n", callno); err = ENOSYS; break; }
// Dispatches to the correct kernel function, passing the arguments. int32_t syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5) { // Call the function corresponding to the 'syscallno' parameter. // Return any appropriate return value. // LAB 3: Your code here. /*stone's solution for lab3-B*/ int32_t ret = -E_INVAL; switch (syscallno){ case SYS_cputs: sys_cputs((char*)a1, a2); ret = 0; break; case SYS_cgetc: ret = sys_cgetc(); break; case SYS_getenvid: ret = sys_getenvid(); break; case SYS_env_destroy: ret = sys_env_destroy(a1); break; case SYS_map_kernel_page: ret = sys_map_kernel_page((void*)a1, (void*)a2); break; case SYS_sbrk: ret = sys_sbrk(a1); break; /*stone's solution for lab4-A*/ case SYS_yield: sys_yield(); ret = 0; break; case SYS_exofork: ret = sys_exofork(); break; case SYS_env_set_status: ret = sys_env_set_status(a1, a2); break; case SYS_env_set_pgfault_upcall: ret = sys_env_set_pgfault_upcall((envid_t)a1, (void*)a2); break; case SYS_page_alloc: ret = sys_page_alloc((envid_t)a1, (void*)a2, (int)a3); break; case SYS_page_map: /*stone: see lib/syscall.c for modification details*/ ret = sys_page_map(*((uint32_t*)a1), (void*)*((uint32_t*)a1 + 1), *((uint32_t*)a1 + 2), (void*)*((uint32_t*)a1 + 3), *((uint32_t*)a1 + 4)); //ret = sys_page_map(a1, (void*)a2, a3, (void*)a4, a5); break; case SYS_page_unmap: ret = sys_page_unmap(a1, (void*)a2); break; case SYS_ipc_recv: ret = sys_ipc_recv((void*)a1); break; case SYS_ipc_try_send: ret = sys_ipc_try_send((envid_t)a1, a2, (void*)a3, (int)a4); break; case SYS_env_set_trapframe: ret = sys_env_set_trapframe((envid_t)a1, (struct Trapframe*)a2); break; default: break; } return ret; //panic("syscall not implemented"); }
/* * System call dispatcher. * * A pointer to the trapframe created during exception entry (in * exception-*.S) is passed in. * * The calling conventions for syscalls are as follows: Like ordinary * function calls, the first 4 32-bit arguments are passed in the 4 * argument registers a0-a3. 64-bit arguments are passed in *aligned* * pairs of registers, that is, either a0/a1 or a2/a3. This means that * if the first argument is 32-bit and the second is 64-bit, a1 is * unused. * * This much is the same as the calling conventions for ordinary * function calls. In addition, the system call number is passed in * the v0 register. * * On successful return, the return value is passed back in the v0 * register, or v0 and v1 if 64-bit. This is also like an ordinary * function call, and additionally the a3 register is also set to 0 to * indicate success. * * On an error return, the error code is passed back in the v0 * register, and the a3 register is set to 1 to indicate failure. * (Userlevel code takes care of storing the error code in errno and * returning the value -1 from the actual userlevel syscall function. * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.) * * Upon syscall return the program counter stored in the trapframe * must be incremented by one instruction; otherwise the exception * return code will restart the "syscall" instruction and the system * call will repeat forever. * * If you run out of registers (which happens quickly with 64-bit * values) further arguments must be fetched from the user-level * stack, starting at sp+16 to skip over the slots for the * registerized values, with copyin(). */ void syscall(struct trapframe *tf) { int callno; int32_t retval; int err; KASSERT(curthread != NULL); KASSERT(curthread->t_curspl == 0); KASSERT(curthread->t_iplhigh_count == 0); callno = tf->tf_v0; /* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */ retval = 0; int whence = 0; off_t position = 0; int32_t retval2 = 0; switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break; case SYS___time: err = sys___time((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1); break; /* Add stuff here */ case SYS_write: err = sys_write((int)tf->tf_a0,(const void *)tf->tf_a1,(size_t)tf->tf_a2, &retval); break; case SYS_read: err = sys_read(tf->tf_a0, (void *) tf->tf_a1, (size_t) tf->tf_a2, &retval); break; case SYS_open: err = sys_open((char *)tf->tf_a0, tf->tf_a1, (mode_t)tf->tf_a2, &retval); break; case SYS_close: err = sys_close(tf->tf_a0); break; case SYS_dup2: err = sys_dup2(tf->tf_a0, tf->tf_a1, &retval); break; case SYS_lseek: position |= (off_t)tf->tf_a2; position <<= 32; position |= (off_t)tf->tf_a3; err = copyin((const userptr_t)tf->tf_sp+16, &whence, sizeof(whence)); if (err) break; err = sys_lseek((int)tf->tf_a0, position, (int)whence, &retval, &retval2); if(!err) tf->tf_v1 = retval2; break; case SYS_fork: err = sys_fork(tf,&retval); break; case SYS_getpid: err = sys_getpid((pid_t *)&retval); break; case SYS_waitpid: err = sys_waitpid((pid_t)tf->tf_a0, (userptr_t)tf->tf_a1, (int)tf->tf_a2, (pid_t *)&retval); break; case SYS__exit: sys__exit((int)tf->tf_a0); err = -1; //will never come here as it doesnt return break; case SYS_execv: err=sys_execv((const char *)tf->tf_a0,(char **)tf->tf_a1); break; case SYS_sbrk: err=(int)sys_sbrk((intptr_t)tf->tf_a0, (vaddr_t *)&retval); break; default: kprintf("Unknown syscall %d\n", callno); err = ENOSYS; break; } if (err) { /* * Return the error code. This gets converted at * userlevel to a return value of -1 and the error * code in errno. */ tf->tf_v0 = err; tf->tf_a3 = 1; /* signal an error */ } else { /* Success. */ tf->tf_v0 = retval; tf->tf_a3 = 0; /* signal no error */ } /* * Now, advance the program counter, to avoid restarting * the syscall over and over again. */ tf->tf_epc += 4; /* Make sure the syscall code didn't forget to lower spl */ KASSERT(curthread->t_curspl == 0); /* ...or leak any spinlocks */ KASSERT(curthread->t_iplhigh_count == 0); }
/* * System call dispatcher. * * A pointer to the trapframe created during exception entry (in * exception.S) is passed in. * * The calling conventions for syscalls are as follows: Like ordinary * function calls, the first 4 32-bit arguments are passed in the 4 * argument registers a0-a3. 64-bit arguments are passed in *aligned* * pairs of registers, that is, either a0/a1 or a2/a3. This means that * if the first argument is 32-bit and the second is 64-bit, a1 is * unused. * * This much is the same as the calling conventions for ordinary * function calls. In addition, the system call number is passed in * the v0 register. * * On successful return, the return value is passed back in the v0 * register, or v0 and v1 if 64-bit. This is also like an ordinary * function call, and additionally the a3 register is also set to 0 to * indicate success. * * On an error return, the error code is passed back in the v0 * register, and the a3 register is set to 1 to indicate failure. * (Userlevel code takes care of storing the error code in errno and * returning the value -1 from the actual userlevel syscall function. * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.) * * Upon syscall return the program counter stored in the trapframe * must be incremented by one instruction; otherwise the exception * return code will restart the "syscall" instruction and the system * call will repeat forever. * * If you run out of registers (which happens quickly with 64-bit * values) further arguments must be fetched from the user-level * stack, starting at sp+16 to skip over the slots for the * registerized values, with copyin(). */ void syscall(struct trapframe *tf) { int callno; int32_t retval; int err = 0; KASSERT(curthread != NULL); KASSERT(curthread->t_curspl == 0); KASSERT(curthread->t_iplhigh_count == 0); callno = tf->tf_v0; /* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */ retval = 0; switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break; case SYS___time: err = sys___time((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1); break; /* Add stuff here */ case SYS_read: err = sys_read((int)tf->tf_a0, // filehandle (void*)tf->tf_a1, // buffer (size_t)tf->tf_a2, // size &retval); // return value break; case SYS_write: err = sys_write((int)tf->tf_a0, // filehandle (const void*)tf->tf_a1, // buffer (size_t)tf->tf_a2, // size &retval); // return value break; case SYS_open: err = sys_open((const char*)tf->tf_a0, // filename (int)tf->tf_a1, // flags &retval); // return value break; case SYS_close: err = sys_close((int)tf->tf_a0); // filehandle break; case SYS_dup2: err = sys_dup2((int)tf->tf_a0, // old_filehandle (int)tf->tf_a1, // new_filehandle &retval); // return value break; case SYS__exit: sys_exit((int)tf->tf_a0); // exitcode break; case SYS_getpid: retval = sys_getpid(); // exitcode break; case SYS_waitpid: err = sys_waitpid((pid_t)tf->tf_a0, (int*)tf->tf_a1, tf->tf_a2, &retval); break; case SYS_fork: err = sys_fork(tf, &retval); break; case SYS_execv: err = sys_execv((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1); break; case SYS_sbrk: err = sys_sbrk((intptr_t)tf->tf_a0, &retval); break; case SYS_lseek: { off_t offset = tf->tf_a2; offset = offset<<32; offset = offset|tf->tf_a3; int whence; int err_copyin = copyin((userptr_t)tf->tf_sp+16,&whence,sizeof(whence)); if (err_copyin) { break; } off_t retoffset; err = sys_lseek((int)tf->tf_a0, // filehandle offset, // desired offset whence, &retoffset); // return value if (!err) { retval = retoffset>>32; tf->tf_v1 = retoffset; } break; } break; case SYS___getcwd: err = sys___getcwd((char*)tf->tf_a0, // buffer (size_t)tf->tf_a1, // size &retval); // return value break; case SYS_chdir: err = sys_chdir((char*)tf->tf_a0); // path break; default: kprintf("Unknown syscall %d\n", callno); err = ENOSYS; break; }
/* call functions based on the call number. */ void mips_syscall(struct trapframe *tf) { int callno; int32_t retval; int err; assert(curspl==0); callno = tf->tf_v0; // the system call number is //passed in the v0 register. /* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */ retval = 0; switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break; case SYS_execv: // err = sys_execv_(tf); err = sys_execv(tf->tf_a0, tf->tf_a1); break; case SYS_fork: err = sys_fork(tf, &retval); break; case SYS_waitpid: err = sys_waitpid(tf->tf_a0,tf->tf_a1, &retval); break; case SYS_getpid: err = sys_getpid(&retval); break; case SYS__exit: err = sys__exit(tf->tf_a0, &retval); break; case SYS_read: err = sys_read(tf, &retval); break; case SYS_write: // err = sys_write(tf, &retval); err = sys_write(tf->tf_a0, tf->tf_a1, tf->tf_a2, &retval); break; case SYS_sbrk: err = sys_sbrk(tf->tf_a0, &retval); break; /* Add stuff here */ default: kprintf("Unknown syscall %d\n", callno); err = ENOSYS; break; } if (err) { /* * Return the error code. This gets converted at * userlevel to a return value of -1 and the error * code in errno. */ tf->tf_v0 = err; tf->tf_a3 = 1; /* signal an error */ } else { /* Success. */ tf->tf_v0 = retval; tf->tf_a3 = 0; /* signal no error */ } /* * Now, advance the program counter, to avoid restarting * the syscall over and over again. */ tf->tf_epc += 4; /* Make sure the syscall code didn't forget to lower spl */ assert(curspl==0); }
/* * System call dispatcher. * * A pointer to the trapframe created during exception entry (in * exception-*.S) is passed in. * * The calling conventions for syscalls are as follows: Like ordinary * function calls, the first 4 32-bit arguments are passed in the 4 * argument registers a0-a3. 64-bit arguments are passed in *aligned* * pairs of registers, that is, either a0/a1 or a2/a3. This means that * if the first argument is 32-bit and the second is 64-bit, a1 is * unused. * * This much is the same as the calling conventions for ordinary * function calls. In addition, the system call number is passed in * the v0 register. * * On successful return, the return value is passed back in the v0 * register, or v0 and v1 if 64-bit. This is also like an ordinary * function call, and additionally the a3 register is also set to 0 to * indicate success. * * On an error return, the error code is passed back in the v0 * register, and the a3 register is set to 1 to indicate failure. * (Userlevel code takes care of storing the error code in errno and * returning the value -1 from the actual userlevel syscall function. * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.) * * Upon syscall return the program counter stored in the trapframe * must be incremented by one instruction; otherwise the exception * return code will restart the "syscall" instruction and the system * call will repeat forever. * * If you run out of registers (which happens quickly with 64-bit * values) further arguments must be fetched from the user-level * stack, starting at sp+16 to skip over the slots for the * registerized values, with copyin(). */ void syscall(struct trapframe *tf) { int callno; int32_t retval; int err; KASSERT(curthread != NULL); KASSERT(curthread->t_curspl == 0); KASSERT(curthread->t_iplhigh_count == 0); callno = tf->tf_v0; /* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */ retval = 0; switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break; case SYS_open: { err = sys_open((const_userptr_t)tf->tf_a0, tf->tf_a1, tf->tf_a2, &retval); break; } case SYS_close: { err = sys_close(tf->tf_a0); break; } case SYS_read: { err = sys_read(tf->tf_a0, (userptr_t)tf->tf_a1, tf->tf_a2, &retval); break; } case SYS_write: { err = sys_write(tf->tf_a0, (const userptr_t)tf->tf_a1, tf->tf_a2, &retval); break; } case SYS_lseek: { // a little tricky, one of the inputs and the return value are 64 bits long. int fd = tf->tf_a0; off_t pos_left32 = tf->tf_a2; off_t pos_right32 = tf->tf_a3; //pos_left32 <<= 32; // pos_right32 is changing after this line . WTF !!! .. FOLLOW UP !! off_t left = pos_left32 << 32; //off_t pos = pos_left32 | pos_right32; off_t pos = left | pos_right32; int whence; err = copyin((const userptr_t)tf->tf_sp+16, (void*)&whence, sizeof(int)); if(err) break; off_t lseek_retval; err = sys_lseek(fd, pos, whence, &lseek_retval); if(err) break; // check this. how does the value get copied retval = lseek_retval >> 32; off_t lseek_right32 = lseek_retval; lseek_right32 = lseek_right32 << 32; lseek_right32 = lseek_right32 >> 32; tf->tf_v1 = lseek_right32; break; } case SYS_dup2: { err = sys_dup2(tf->tf_a0, tf->tf_a1, &retval); break; } case SYS_chdir: { err = sys_chdir((const userptr_t)tf->tf_a0); break; } case SYS___getcwd: { err = sys_getcwd((userptr_t)tf->tf_a0, tf->tf_a1); break; } case SYS___time: err = sys___time((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1); break; /* Add stuff here */ case SYS_fork: err = sys_fork(tf, &retval); break; case SYS_getpid: err = sys_getpid(&retval); break; case SYS__exit: err = sys__exit(tf->tf_a0); break; case SYS_waitpid: err = sys_waitpid(tf->tf_a0, (userptr_t)tf->tf_a1, tf->tf_a2, &retval); break; case SYS_execv: err = sys_execv((userptr_t)tf->tf_a0, (userptr_t *)tf->tf_a1); break; case SYS_sbrk: err = sys_sbrk((intptr_t)tf->tf_a0, &retval); break; default: kprintf("Unknown syscall %d\n", callno); err = ENOSYS; break; } if (err) { /* * Return the error code. This gets converted at * userlevel to a return value of -1 and the error * code in errno. */ tf->tf_v0 = err; tf->tf_a3 = 1; /* signal an error */ } else { /* Success. */ tf->tf_v0 = retval; tf->tf_a3 = 0; /* signal no error */ } /* * Now, advance the program counter, to avoid restarting * the syscall over and over again. */ tf->tf_epc += 4; /* Make sure the syscall code didn't forget to lower spl */ KASSERT(curthread->t_curspl == 0); /* ...or leak any spinlocks */ KASSERT(curthread->t_iplhigh_count == 0); }
void mips_syscall(struct trapframe *tf) { int callno; int32_t retval; int err; int s,act; char *d; //convert user level pointers to user level pointers assert(curspl==0); callno = tf->tf_v0; /* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */ retval = 0; switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break; // syscall.h has all the callno numbers for differnt syscalls case SYS_fork: err = sysfork(&retval,tf); break; case SYS_getpid : err = sysgetpid(&retval); break; case SYS_write : s=splhigh(); char *c = (char *)tf->tf_a1; kprintf("%c",*c); retval = 1; splx(s); err=0; break; case SYS_read : d = (char *)kmalloc(sizeof(char)*((tf->tf_a2)+1)); //char *b; //b = (char *)kmalloc(sizeof(char)*((tf->tf_a2)+1)); d[0] = getch(); d[1] ='\0'; putch(d[0]); putch('\n'); s=splhigh(); copyoutstr(d,(userptr_t)(tf->tf_a1),(tf->tf_a2)+1,&act); //DEBUG(1,"actual: %d tf size: %d\n",act,(tf->tf_a2)+1); //copyinstr((tf->tf_a1),b,(tf->tf_a2)+1,&act); //DEBUG(1,"copied bacl:%s\n",b); err=0; kfree(d); retval = strlen(d)+1; splx(s); break; case SYS_waitpid : err = syswaitpid(tf->tf_a0,(int *)tf->tf_a1,tf->tf_a2,&retval); //syswaitpid(&retval); break; case SYS__exit : err = sysexit(&retval,tf); break; case SYS_execv: err=sysexecv((char*)tf->tf_a0, (char**)tf->tf_a1); break; case SYS_sbrk: err = sys_sbrk((int)tf->tf_a0, &retval); break; default: kprintf("Unknown syscall %d\n", callno); err = ENOSYS; break; } if (err) { /* * Return the error code. This gets converted at * userlevel to a return value of -1 and the error * code in errno. */ tf->tf_v0 = err; tf->tf_a3 = 1; /* signal an error */ } else { /* Success. */ tf->tf_v0 = retval; tf->tf_a3 = 0; /* signal no error */ } /* * Now, advance the program counter, to avoid restarting * the syscall over and over again. */ tf->tf_epc += 4; /* Make sure the syscall code didn't forget to lower spl */ assert(curspl==0); }