/*
 * 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;
	}
/*
 * 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___time:
		    err = sys___time((userptr_t)tf->tf_a0,
				     (userptr_t)tf->tf_a1);


		    break;

            /* ASST2: These implementations of read and write only work for
             * console I/O (stdin, stdout and stderr file descriptors)
             */
            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, (userptr_t)tf->tf_a1, tf->tf_a2,
                                &retval);
                break;

            /* process calls */
            case SYS__exit:
            	thread_exit(_MKWAIT_EXIT(tf->tf_a0));
            	panic("Returning from exit\n");
	
            case SYS_fork:
            	err = sys_fork(tf, &retval);
            	break;

            /* ASST2 - You need to fill in the code for each of these cases */
            case SYS_getpid:
            	err = sys_getpid(&retval);
                break;

            case SYS_waitpid:
                if(sys_waitpid(tf->tf_a0, \
                		(userptr_t)tf->tf_a1, tf->tf_a2, &retval) == -1)
                {
                  err=retval;
                }
                else{
                err=0;
                }
                break;

            case SYS_kill:
            	err = sys_kill(tf->tf_a0, tf->tf_a1);
            	break;

	    /* Even more system calls will go 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 */
	KASSERT(curthread->t_curspl == 0);
	/* ...or leak any spinlocks */
	KASSERT(curthread->t_iplhigh_count == 0);
}
Example #3
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)
{
    //kprintf("Starting syscall\n");
	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___time:
		err = sys___time((userptr_t)tf->tf_a0,
				 (userptr_t)tf->tf_a1);
		break;
#ifdef UW
	case SYS_write:
	  err = sys_write((int)tf->tf_a0,
			  (userptr_t)tf->tf_a1,
			  (int)tf->tf_a2,
			  (int *)(&retval));
	  break;
	case SYS__exit:
	  sys__exit((int)tf->tf_a0);
	  /* sys__exit does not return, execution should not get here */
	  panic("unexpected return from sys__exit");
	  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_fork:
	    err = sys_fork(tf, (pid_t *)&retval);
	    break;
	case SYS_execv:
	    err=sys_execv((char *)tf->tf_a0, (char **) tf->tf_a1);
	    break;
#endif // UW

	    /* 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 */
	KASSERT(curthread->t_curspl == 0);
	/* ...or leak any spinlocks */
	KASSERT(curthread->t_iplhigh_count == 0);
}
Example #4
0
/**
 * SPB & FAR
 * 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, err;
	int32_t retval;

	off_t pos = 0;
	off_t lsret;
	int whence;

	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;

	    case SYS_open:
	    	err = sys_open((const char*)tf->tf_a0, tf->tf_a1, &retval);
	    break;

	    case SYS_read:
	    	err = sys_read((int)tf->tf_a0,(void*)tf->tf_a1,(size_t)tf->tf_a2,&retval);
	    break;

	    case SYS_write:
	    	err = sys_write((int)tf->tf_a0,(const void*)tf->tf_a1,(size_t)tf->tf_a2,&retval);	
	    break;

	    case SYS_close:
	    	err = sys_close((int)tf->tf_a0, &retval);
   	    break;

   	    case SYS_lseek:

   	    	pos |= (off_t)tf->tf_a2;
   	    	pos <<= 32;			//puts a2 and a3 into one var.
   	    	pos |= (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, pos, (int)whence, &lsret);
   	    	if(!err){
   	    		retval = lsret>>32;
   	    		tf->tf_v1 = lsret;
   	    	}
   	    break;

   	    case SYS_dup2:
   	    	err = sys_dup2((int)tf->tf_a0 , (int)tf->tf_a1, &retval);
   	    break;

   	    case SYS_chdir:
   	    	err = sys_chdir((const char*)tf->tf_a0);
   	    break;

   	    case SYS___getcwd:
   	    	err = sys___getcwd((char*)tf->tf_a0, (size_t)tf->tf_a1, &retval);
   	    break;

   	    case SYS_fork:
   	    	err = sys_fork(tf, &retval);
   	    break;

   	    case SYS_getpid:
   	    	err = sys_getpid(&retval);
   	    break;

   	    case SYS__exit:
   	    	err = sys__exit((int)tf->tf_a0, &retval);
   	    break;

   	    case SYS_waitpid:
   	    	err = sys_waitpid((int) tf->tf_a0, (int*) tf->tf_a1, tf->tf_a2, &retval);
   	    break;

   	    case SYS_execv:
   	    	err = sys_execv((const char*) tf->tf_a0, (char**) tf->tf_a1, &retval);
   	    break;

	    default:
		kprintf("Unknown syscall %d\n", callno);
		err = ENOSYS;
		break;
	}
Example #5
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___time:
		err = sys___time((userptr_t)tf->tf_a0,
				 (userptr_t)tf->tf_a1);
		break;
        //F*****G A2
        case SYS_write:
           err=write(tf->tf_a0,(void*)tf->tf_a1,tf->tf_a2);
         break;
	    /* Add stuff here */
  	    case SYS_open:
  	      break;
  	     case SYS_close:
  	     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);
}
Example #6
0
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;

	uint32_t v0, v1;
	off_t pos;
	int whence;
	//userptr_t *status;

	struct stat statbuf;


	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);	 /* the syscall ov*/
		break;

	    case SYS_open:
	    err = sys_open((const_userptr_t)tf->tf_a0, tf->tf_a1, (mode_t)tf ->tf_a2, &retval);
	    break;

	    case SYS_close:
	    err = sys_close((tf->tf_a0),&retval);
	    break;

	    case SYS_read:
	    	err = sys_read(tf->tf_a0, (userptr_t)tf->tf_a1, (size_t)tf -> tf_a2, &retval);
	    	//retval = (int32_t)bytes;
	    	break;

	    case SYS_write:
	   	    err = sys_write(tf->tf_a0, (userptr_t)tf->tf_a1, (size_t)tf -> tf_a2, &retval);
	   	    //retval = (int32_t)bytes;
	   	    break;

	    case SYS_lseek:
	    	pos = tf->tf_a2;
	    	pos = pos << 32;
	    	pos += tf -> tf_a3;
	    	err = copyin((const_userptr_t)tf->tf_sp+16,&whence,sizeof(int));
	    	if(err)
	    	{
	    		break;
	    	}
	    	err = sys_lseek(tf->tf_a0, pos, whence, &v0, &v1);
	    	if(err)
	    	{
	    		break;
	    	}
	    	retval = v0;
	    	tf->tf_v1 = v1;
	    	break;

	    case SYS__exit:

	    	sys__exit(tf->tf_a0);


//			We are only here because of one of 2 reasons. We tried to kill the initial thread
//			while there was/were (an) immediate child(ren) of it running.

//			*NOTE* I'm actually NOT sure if that's a valid reason to be here

//			Second reason? Something went horribly, horribly wrong
	    	err = 0;
	    	break;
 
	    case SYS_dup2:

	    	err = sys_dup2(tf->tf_a0,tf->tf_a1,&retval);
	    	break;

	    case SYS_fstat:

	    	err = sys_fstat(tf->tf_a0, &statbuf);
	    	break;

	    case SYS_fork:
	    	err = sys_fork(tf, &retval);
	    	break;

	    case SYS_getpid:
	    	err = sys_getpid(&retval);
	    	break;

	    case SYS_waitpid:
	    	err = sys_waitpid(tf->tf_a0, (int*)tf->tf_a1, (int)tf->tf_a2, &retval);
	    	break;

	    case SYS___getcwd:

	    	err = sys___getcwd((char*)tf->tf_a0,(size_t)tf->tf_a1,&retval);
	    	break;

	    case SYS_chdir:
	    	err = sys_chdir((char*)tf->tf_a0,&retval);
	    	break;

	    case SYS_execv:
	    	err = sys_execv((const char*)tf->tf_a0, (char**)tf->tf_a1);
	    	break;
	    case SYS_sbrk:
	    	err = 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 */
	KASSERT(curthread->t_curspl == 0);
	/* ...or leak any spinlocks */
	KASSERT(curthread->t_iplhigh_count == 0);


}
Example #7
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(void *trapframe, unsigned long junk)
{
  curproc->rt = (curproc->rt == BACKGROUND_U ?  BACKGROUND_K : INTERACTIVE_K);
  (void)junk;
  struct trapframe *tf = (struct trapframe*)trapframe;
  
  if(!curproc->context)
    curproc->context = kmalloc(sizeof(struct trapframe));
  
  memcpy(curproc->context, tf, sizeof(struct trapframe));
  
  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___time:
    err = sys___time((userptr_t)tf->tf_a0,
		     (userptr_t)tf->tf_a1);
    break;
    
    /* Add stuff here */
    
  case SYS__exit:
    _exit((int)tf->tf_a0);
    break;
    
  case SYS_chdir:
    err = chdir((const char*)tf->tf_a0);
    break;

  case SYS_close:
    err = close((int)tf->tf_a0,
		   &retval);
    break;

  case SYS_dup2:
    err = dup2((int)tf->tf_a0,
		  (int)tf->tf_a1,
		   &retval);
    break;
    
  case SYS_execv:
    err = execv((const char*)tf->tf_a0,
		(char **)tf->tf_a1);
    break;

  case SYS_fork:
    err = fork(&retval);
    break;

  case SYS___getcwd:
    err = __getcwd((char*)tf->tf_a0,
		   (size_t)tf->tf_a1,
		   &retval);
    break;

  case SYS_getpid:
    err = getpid(&retval);//always return 0
    break;

  case SYS_lseek:
    err = lseek((int)tf->tf_a0,
		(off_t)(tf->tf_a1 | tf->tf_a2),
		(int)tf->tf_a3,
		(off_t*)&retval);
    break;

  case SYS_open:
    err = open((const char*)tf->tf_a0,
	       (int)tf->tf_a1,
	       &retval);
    break;

  case SYS_read:
    err = read((int)tf->tf_a0,
	       (void*)tf->tf_a1,
	       (size_t)tf->tf_a2,
	       &retval);
    break;
    
  case SYS_waitpid:
    err = waitpid((pid_t)tf->tf_a0,
		  (int *)tf->tf_a1,
		  (int)tf->tf_a2,
		  &retval);
    break;

  case SYS_write:
    err = write((int)tf->tf_a0,
		(userptr_t)tf->tf_a1,
		(size_t)tf->tf_a2,
		&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);
	curproc->rt = (curproc->rt == BACKGROUND_K ?  BACKGROUND_U : INTERACTIVE_U);
}
Example #8
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;

	/* note the casts to userptr_t */

	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;


	    /* process calls */

	    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__exit:
		sys__exit(tf->tf_a0);
		panic("Returning from exit\n");

	    case SYS_waitpid:
		err = sys_waitpid(
			tf->tf_a0,
			(userptr_t)tf->tf_a1,
			tf->tf_a2, 
			&retval);
		break;

	    case SYS_getpid:
		err = sys_getpid(&retval);
		break;


	    /* file calls */

	    case SYS_open:
		err = sys_open(
			(userptr_t)tf->tf_a0,
			tf->tf_a1,
			tf->tf_a2,
			&retval);
		break;

	    case SYS_dup2:
		err = sys_dup2(
			tf->tf_a0,
			tf->tf_a1,
			&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,
			(userptr_t)tf->tf_a1,
			tf->tf_a2,
			&retval);
		break;
	    case SYS_lseek:
		{
			/*
			 * Because the position argument is 64 bits wide,
			 * it goes in the a2/a3 registers and we have to
			 * get "whence" from the stack. Furthermore, the
			 * return value is 64 bits wide, so the extra
			 * part of it goes in the v1 register.
			 *
			 * This is a trifle messy.
			 */
			uint64_t offset;
			int whence;
			off_t retval64;

			join32to64(tf->tf_a2, tf->tf_a3, &offset);

			err = copyin((userptr_t)tf->tf_sp + 16,
				     &whence, sizeof(int));
			if (err) {
				break;
			}

			err = sys_lseek(tf->tf_a0, offset, whence, &retval64);
			if (err) {
				break;
			}

			split64to32(retval64, &tf->tf_v0, &tf->tf_v1);
			retval = tf->tf_v0;
		}	
		break;

	    case SYS_chdir:
		err = sys_chdir((userptr_t)tf->tf_a0);
		break;

	    case SYS___getcwd:
		err = sys___getcwd(
			(userptr_t)tf->tf_a0,
			tf->tf_a1,
			&retval);
		break;


	    /* Even more system calls will go 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 */
	KASSERT(curthread->t_curspl == 0);
	/* ...or leak any spinlocks */
	KASSERT(curthread->t_iplhigh_count == 0);
}
Example #9
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;

	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);
}
Example #10
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;
	}
Example #11
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;
	int32_t retval1;
	int err;
	off_t pos;
	int whence;
	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;

	    /* Start of process system calls */
	    case SYS_fork:
	    	err = sys_fork(tf, &retval);
	    break;
	    case SYS_execv:
	    	err = sys_execv((const char*)tf->tf_a0,(char **) tf->tf_a1);
	    break;
	    case SYS__exit:
	    	sys__exit(tf->tf_a0);
	    break;
	    case SYS_waitpid:
	    	err =  sys_waitpid((pid_t)tf->tf_a0, (int *)tf->tf_a1, tf->tf_a2, &retval);
	    break;
	    case SYS_getpid:
	    	err = sys_getpid(&retval);
	    break;

	    /* End of process system calls */

		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, &retval);
		break;
		case SYS_write :
			err = sys_write(tf->tf_a0,(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_lseek:
			pos =  (  (off_t)tf->tf_a2 << 32 | tf->tf_a3);
			if (copyin((const_userptr_t) tf->tf_sp+16, &whence, sizeof(int)) ) {
				err = EINVAL ; // definitely an error
				break;
			}
			err = sys_lseek(tf->tf_a0, pos,whence, &retval, &retval1);
			if (err == 0) { // if call has passed, then we need to copy retval1 to tf->tf_v1 (low32)
				tf->tf_v1 = retval1;
			}
		break;
		case SYS___getcwd:
			//char *buf, size_t buflen, int *retval
			err = sys__getcwd((char *)tf->tf_a0, (size_t) tf->tf_a1, &retval);
		break;
		case SYS_dup2:
			err = sys_dup2(tf->tf_a0, tf->tf_a1, &retval);
		break;
		case SYS_chdir:
			err = sys_chdir((const char *)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);
}
/*
 * 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);
}