Beispiel #1
0
/*
 * get system call
 */
static void
syscall_handler (struct intr_frame *f)
{
  int *esp = (int *)syscall_user_to_kernel_vaddr(f->esp);
  switch(*esp)
  {
    case SYS_WRITE:
      syscall_write(f);
      break;
    case SYS_EXIT:
      syscall_exit(f);
      break;
    case SYS_HALT:
      syscall_halt(f);
      break;
    case SYS_EXEC:
      syscall_exec(f);
      break;
    case SYS_CREATE:
      syscall_create(f);
      break;
    case SYS_REMOVE:
      syscall_remove(f);
      break;
    case SYS_OPEN:
      syscall_open(f);
      break;
    case SYS_FILESIZE:
      syscall_filesize(f);
      break;
    case SYS_READ:
      syscall_read(f);
      break;
    case SYS_SEEK:
      syscall_seek(f);
      break;
    case SYS_TELL:
      syscall_tell(f);
      break;
    case SYS_CLOSE:
      syscall_close(f);
      break;
    case SYS_WAIT:
      syscall_wait(f);
      break;
  }
}
Beispiel #2
0
static void
syscall_handler (struct intr_frame *f) 
{
  int syscall_num;
  VALIDATE_AND_GET_ARG (f->esp, syscall_num, f);
  void *cur_sp = f->esp + sizeof (void *);

  /* store user program stack pointer to the thread's 
     user_esp before changing to kernel mode */
  struct thread *t = thread_current ();
  t->user_esp = f->esp;

  switch (syscall_num)
    {
      case SYS_HALT:
        syscall_halt (f, cur_sp);
        break;
      case SYS_EXIT:
        syscall_exit (f, cur_sp);
        break;
      case SYS_EXEC:
        syscall_exec (f, cur_sp);
        break;
      case SYS_WAIT:
        syscall_wait (f, cur_sp);
        break;
      case SYS_CREATE:
        syscall_create (f, cur_sp);
        break;
      case SYS_REMOVE:
        syscall_remove (f, cur_sp);
        break;
      case SYS_OPEN:
        syscall_open (f, cur_sp);
        break;
      case SYS_FILESIZE:
        syscall_filesize (f, cur_sp);
        break;
      case SYS_READ:
        syscall_read (f, cur_sp);
        break;
      case SYS_WRITE:
        syscall_write (f, cur_sp);
        break;
      case SYS_SEEK:
        syscall_seek (f, cur_sp);
        break;
      case SYS_TELL:
        syscall_tell (f, cur_sp);
        break;
      case SYS_CLOSE:
        syscall_close (f, cur_sp);
        break;
      case SYS_MMAP:
        syscall_mmap (f, cur_sp);
        break;
      case SYS_MUNMAP:
        syscall_unmmap (f, cur_sp);
        break;
      default :
        printf ("Invalid system call! #%d\n", syscall_num);
        syscall_thread_exit (f, -1);
        break;
    }
}
Beispiel #3
0
static void
syscall_handler (struct intr_frame *f) 
{
  /* Validate the first addr of the stack frame */
  
  void *esp = utok_addr (f->esp, NULL);
  
  if (esp == NULL) {
    syscall_exit (-1);
    return;
  }
  
  enum SYSCALL_NUMBER call_number = *(enum SYSCALL_NUMBER *) esp;
  if (call_number < syscall_first_call || call_number > syscall_last_call) {
    syscall_exit (-1);
    return;
  }

  /* Buffer the arguments for validation */
  int argc = syscall_argc[call_number];
  uint32_t argbuf[3];

  int i = 0;
  for (; i < argc; i++) {
    /* Validate each argument  */
    void *vaddr = uptr_valid((uint32_t *) f->esp + 1 + i, f->esp);
    if (vaddr == NULL) {
      syscall_exit (-1);
      return;
    }
    /* Translate the argument to kernel virtual (== physical) memory */
    argbuf[i] = *(uint32_t *) vaddr;
  }
  
  int retval = 0;

  /* Switch based on call_number to delegate to corresponding syscall.
     Have not implemented several syscalls as of this project. 
     Use validation methods to check user-provided arguments.
  */
  switch (call_number) {
    case SYS_HALT:
      syscall_halt ();
      break;
    case SYS_EXIT:
      syscall_exit ((int) argbuf[0]);
      break;
    case SYS_EXEC:
      if (str_valid ((void *) argbuf[0], f->esp) == NULL) {
        syscall_exit (-1);
        return;
      }
      retval = syscall_exec ((char *) argbuf[0]);
      break;
    case SYS_WAIT:
      retval = syscall_wait ((int) argbuf[0]);
      break;
    case SYS_CREATE:
      if (str_valid ((char *) argbuf[0], f->esp) == NULL) {
        syscall_exit (-1);
        return;
      }
      retval = (int) syscall_create ((char *) argbuf[0],
                                     (unsigned) argbuf[1]);
      break;
    case SYS_REMOVE:
      if (!uptr_valid ((char *) argbuf[0], f->esp)) {
        syscall_exit (-1);
        return;
      }
      retval = (int) syscall_remove ((char *) argbuf[0]);
      break;
    case SYS_OPEN:
      if (str_valid ((char *) argbuf[0], f->esp) == NULL) {
        syscall_exit (-1);
        return;
      }
      retval = (int) syscall_open ((char *) argbuf[0]);
      break;
    case SYS_FILESIZE:
      retval = syscall_filesize ((int) argbuf[0]);
      break;
    case SYS_READ:
      if (buffer_valid ((void *) argbuf[1], f->esp, 
                        (unsigned) argbuf[2]) == NULL) {
        syscall_exit (-1);
        return;
      }
      retval = syscall_read ((int) argbuf[0],
                             (void *) argbuf[1],
                             (unsigned) argbuf[2]);
      break;
    case SYS_WRITE:
      if (buffer_valid ((void *) argbuf[1], f->esp, 
                        (unsigned) argbuf[2]) == NULL) {
        syscall_exit (-1);
        return;
      }
      retval = syscall_write ((int) argbuf[0],
                             (void *) argbuf[1],
                             (unsigned) argbuf[2]);
      break;
    case SYS_SEEK:
      syscall_seek ((int) argbuf[0], (unsigned) argbuf[1]);
      break;
    case SYS_TELL:
      retval = (int) syscall_tell ((int) argbuf[0]);
      break;
    case SYS_CLOSE:
      syscall_close ((int) argbuf[0]);
      break;
#ifdef VM
    case SYS_MMAP:
      // addr will be checked internally inside mmap
      retval = (int) syscall_mmap ((int) argbuf[0], (void *) argbuf[1]);
      break;
    case SYS_MUNMAP:
      syscall_munmap ((int) argbuf[0]);
      break;
#endif
    default:
      printf("unhandled system call!\n");
      thread_exit();
  }

  f->eax = retval;
}
Beispiel #4
0
static void
syscall_handler (struct intr_frame *f) 
{
	int nsyscall, i;
	int *esp = (int *)f -> esp;

	if(!is_valid(esp))
		thread_exit();
	
	int *arg_int[3];
	void **arg_ptr[3];

	// Get system call number.
	nsyscall = *(esp++);

	/* argc number
		0:
			SYS_HALT 
		1:
			SYS_EXIT, SYS_EXEC, SYS_WAIT, SYS_TELL, SYS_REMOVE, SYS_OPEN, SYS_CLOSE, SYS_FILESIZE
		2:
			SYS_CREATE, SYS_SEEK
		3:
			SYS_READ, SYS_WRITE
	*/
	if(nsyscall == SYS_HALT) {
		shutdown_power_off();
	}
	else if(nsyscall == SYS_EXIT) {
		for(i = 0; i < 1; i++) {
			if(is_valid((esp+i))) {
				arg_int[i] = esp + i;
			}
			else thread_exit();
		}

		syscall_exit(*arg_int[0]);
	}
	else if(nsyscall == SYS_EXEC) {
		for(i = 0; i < 1; i++) {
			if(is_valid((esp+i))) {
				arg_ptr[i] = (void **)(esp + i);
			}
			else thread_exit();
		}

		if(!is_valid(*arg_ptr[0]))
			thread_exit();
	
		lock_acquire(&lock_sys);
		f->eax = process_execute(*arg_ptr[0]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_WAIT) {
		for(i = 0; i < 1; i++) {
			if(is_valid((esp+i))) {
				arg_int[i] = esp + i;
			}
			else thread_exit();
		}

		f->eax = process_wait(*arg_int[0]);
	}
	else if(nsyscall == SYS_TELL) {
		for(i = 0; i < 1; i++) {
			if(is_valid((esp+i))) {
				arg_int[i] = esp + i;
			}
			else thread_exit();
		}

		lock_acquire(&lock_sys);
		f->eax = syscall_tell(*arg_int[0]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_REMOVE) {
		for(i = 0; i < 1; i++) {
			if(is_valid((esp+i))) {
				arg_ptr[i] = (void **)(esp + i);
			}
			else thread_exit();
		}
		
		if(!is_valid(*arg_ptr[0]))
			thread_exit();

		lock_acquire(&lock_sys);
		f->eax = filesys_remove(*arg_ptr[0]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_OPEN) {
		for(i = 0; i < 1; i++) {
			if(is_valid((esp+i))) {
				arg_ptr[i] = (void **)(esp + i);
			}
			else thread_exit();
		}
		
		if(!is_valid(*arg_ptr[0]))
			thread_exit();

		lock_acquire(&lock_sys);
		f->eax = syscall_open(*arg_ptr[0]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_CLOSE) {
		for(i = 0; i < 1; i++) {
			if(is_valid((esp+i))) {
				arg_int[i] = esp + i;
			}
			else thread_exit();
		}

		lock_acquire(&lock_sys);
		syscall_close(*arg_int[0]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_FILESIZE) {
		for(i = 0; i < 1; i++) {
			if(is_valid((esp+i))) {
				arg_int[i] = esp + i;
			}
			else thread_exit();
		}

		lock_acquire(&lock_sys);
		f->eax = syscall_filesize(*arg_int[0]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_CREATE) {
		for(i = 0; i < 2; i++) {
			if(is_valid((esp+i))) {
				arg_int[i] = esp + i;
				arg_ptr[i] = (void **)(esp + i);
			}
			else thread_exit();
		}

		if(!is_valid(*arg_ptr[0]))
			thread_exit();

		lock_acquire(&lock_sys);
		f->eax = filesys_create(*arg_ptr[0], *arg_int[1]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_SEEK) {
		for(i = 0; i < 2; i++) {
			if(is_valid((esp+i))) {
				arg_int[i] = esp + i;
			}
			else thread_exit();
		}

		lock_acquire(&lock_sys);
		syscall_seek(*arg_int[0], *arg_int[1]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_READ) {
		for(i = 0; i < 3; i++) {
			if(is_valid((esp+i))) {
				arg_int[i] = esp + i;
				arg_ptr[i] = (void **)(esp + i);
			}
			else thread_exit();
		}

		if(!is_valid(*arg_ptr[1]))
			thread_exit();

		lock_acquire(&lock_sys);
		f->eax = syscall_read(*arg_int[0], *arg_ptr[1], *arg_int[2]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_WRITE) {
		for(i = 0; i < 3; i++) {
			if(is_valid((esp+i))) {
				arg_int[i] = esp + i;
				arg_ptr[i] = (void **)(esp + i);
			}
			else thread_exit();
		}

		if(!is_valid(*arg_ptr[1]))
			thread_exit();

		lock_acquire(&lock_sys);
		f->eax = syscall_write(*arg_int[0], *arg_ptr[1], *arg_int[2]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_CHDIR) {
		for(i = 0; i < 1; i++) {
			if(is_valid((esp+i))) {
				arg_ptr[i] = (void **)(esp + i);
			}
			else thread_exit();
		}
		
		if(!is_valid(*arg_ptr[0]))
			thread_exit();

		lock_acquire(&lock_sys);
		f->eax = syscall_chdir(*arg_ptr[0]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_MKDIR) {
		for(i = 0; i < 1; i++) {
			if(is_valid((esp+i))) {
				arg_ptr[i] = (void **)(esp + i);
			}
			else thread_exit();
		}
		
		if(!is_valid(*arg_ptr[0]))
			thread_exit();

		lock_acquire(&lock_sys);
		f->eax = syscall_mkdir(*arg_ptr[0]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_READDIR) {
		for(i = 0; i < 2; i++) {
			if(is_valid((esp+i))) {
				arg_int[i] = esp + i;
				arg_ptr[i] = (void **)(esp + i);
			}
			else thread_exit();
		}

		if(!is_valid(*arg_ptr[1]))
			thread_exit();

		lock_acquire(&lock_sys);
		f->eax = syscall_readdir(*arg_int[0], *arg_ptr[1]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_ISDIR) {
		for(i = 0; i < 1; i++) {
			if(is_valid((esp+i))) {
				arg_int[i] = esp + i;
			}
			else thread_exit();
		}

		lock_acquire(&lock_sys);
		f->eax = syscall_isdir(*arg_int[0]);
		lock_release(&lock_sys);
	}
	else if(nsyscall == SYS_INUMBER) {
		for(i = 0; i < 1; i++) {
			if(is_valid((esp+i))) {
				arg_int[i] = esp + i;
			}
			else thread_exit();
		}

		lock_acquire(&lock_sys);
		f->eax = syscall_inumber(*arg_int[0]);
		lock_release(&lock_sys);
	}
	else
		thread_exit();
}
Beispiel #5
0
static void
syscall_handler (struct intr_frame *f) 
{
	int nsyscall, argc, i;
	int *esp = (int *)f->esp; /* get argument pointer */
	int *arg_int[3];
	void **arg_ptr[3];

	/* verify the argument pointer */
	if (!IS_VALID(esp))
		goto error_end;

	/* system call number */
	nsyscall = *(esp++);

	/* number of arguments */
	switch (nsyscall) {
	case SYS_HALT: 
		argc = 0;
		break;
	case SYS_EXIT:
	case SYS_EXEC:
	case SYS_WAIT:
	case SYS_TELL:
	case SYS_CLOSE:	
	case SYS_REMOVE:
	case SYS_OPEN:
	case SYS_FILESIZE:
		argc = 1;
		break;
	case SYS_CREATE:
	case SYS_SEEK:
		argc = 2;
		break;
	case SYS_READ:
	case SYS_WRITE:
		argc = 3;
		break;
	default:
		goto error_end;
	}

	/* verify the argument pointer */
	for (i = 0; i < argc; i++)
		if (IS_VALID(esp + i)) {
			arg_int[i] = esp + i;
			arg_ptr[i] = (void**)(esp + i);
		} else {
			break;
		}
	if (i < argc)
		goto error_end;

	/* system call */
	switch (nsyscall) {
	case SYS_HALT:
		shutdown_power_off();
		break; 
	case SYS_EXIT:
		syscall_exit(*arg_int[0]);
		break;
	case SYS_EXEC:
		if (!IS_VALID(*arg_ptr[0]))
			goto error_end;
		lock_acquire (&lock_filesys);
		f->eax = process_execute(*arg_ptr[0]);
		lock_release (&lock_filesys);
		break;
	case SYS_WAIT:
		f->eax = process_wait(*arg_int[0]);
		break;
	case SYS_TELL:
		lock_acquire (&lock_filesys);
		f->eax = syscall_tell(*arg_int[0]);
		lock_release (&lock_filesys);
		break;
	case SYS_CLOSE:	
		lock_acquire (&lock_filesys);
		process_file_close(*arg_int[0]);
		lock_release (&lock_filesys);
		break;
	case SYS_REMOVE:
		if (!IS_VALID(*arg_ptr[0]))
			goto error_end;
		lock_acquire (&lock_filesys);
		f->eax = syscall_remove(*arg_ptr[0]);
		lock_release (&lock_filesys);
		break;
	case SYS_OPEN:
		if (!IS_VALID(*arg_ptr[0]))
			goto error_end;
		lock_acquire (&lock_filesys);
		f->eax = process_file_open(*arg_ptr[0]);
		lock_release (&lock_filesys);
		break;
	case SYS_FILESIZE:
		lock_acquire (&lock_filesys);
		f->eax = syscall_filesize(*arg_int[0]);
		lock_release (&lock_filesys);
		break;
	case SYS_CREATE:
		if (!IS_VALID(*arg_ptr[0]))
			goto error_end;
		lock_acquire (&lock_filesys);
		f->eax = syscall_create(*arg_ptr[0], *arg_int[1]);
		lock_release (&lock_filesys);
		break;
	case SYS_SEEK:
		lock_acquire (&lock_filesys);
		syscall_seek(*arg_int[0], *arg_int[1]);
		lock_release (&lock_filesys);
		break;
	case SYS_READ:
		if (!IS_VALID(*arg_ptr[1]))
			goto error_end;
		lock_acquire (&lock_filesys);
		f->eax = syscall_read(*arg_int[0], *arg_ptr[1], *arg_int[2]);
		lock_release (&lock_filesys);
		break;
	case SYS_WRITE:
		if (!IS_VALID(*arg_ptr[1]))
			goto error_end;
		lock_acquire (&lock_filesys);
		f->eax = syscall_write(*arg_int[0], *arg_ptr[1], *arg_int[2]);
		lock_release (&lock_filesys);
		break;
	default:
		printf ("Unknown syscall : %d\n", nsyscall);
		goto error_end;
	}
	return;

error_end:
	thread_exit ();
}
static void
syscall_handler (struct intr_frame *f)
{
  // XXX : EDIT WITH 'syscall.h' 'lib/user/syscall.c' 'lib/syscall-nr.h
  //printf ("system call!\n");
  void *now = f->esp;
  // XXX : Check PTR Range, and bash to syscall_exit(-1);
  if(!is_valid_ptr(now))
    syscall_exit(-1);
  int syscall_number = *(int *)(f->esp);
  int argc_size_table[22] = {  // CHECK syscall-nr.h
	  0,  // SYS_HALT (*) :0
	  1,  // SYS_EXIT (*) :1
	  1,  // SYS_EXEC (*) :2
	  1,  // SYS_WAIT (*) :3
	  2,  // SYS_CREATE   :4
	  1,  // SYS_REMOVE   :5
	  1,  // SYS_OPEN     :6
	  1,  // SYS_FILESIZE :7
	  3,  // SYS_READ (*) :8
	  3,  // SYS_WRITE (*):9
	  2,  // SYS_SEEK     :10
	  1,  // SYS_TELL     :11
	  1,  // SYS_CLOSE    :12  (proj 2-2)
	  2,  // SYS_MMAP
	  1,  // SYS_MUNMAP
	  1,  // SYS_CHDIR
	  1,  // SYS_MKDIR
	  2,  // SYS_READDIR
	  1,  // SYS_ISDIR
	  1,  // SYS_INUMBER
	  1,  // SYS_PIBONACCI
	  4   // SYS_SUM_OF_FOUR_INTEGERS
  };
  int argc_size = argc_size_table[syscall_number];
  //printf("SYSCALL %d SIZE %d\n", syscall_number, argc_size);
  void *argc[4] = {NULL,};
  {
    int i;
    for(i = 0; i < argc_size; i++){
      now += 4; // sizeof(void *);  // IT WILL USE 4 Bytes. (ref:man38).
      argc[i] = now;
	  // XXX : Check argument's ptr;
	  if(!is_valid_ptr(argc[i]))
		syscall_exit(-1);
	 // printf("%x\n", now);
    }
  }
  switch(syscall_number){
	default:
	case -1:
		break;
	case 0:  // SYS_HALT
		syscall_halt();
		break;
	case 1:  // SYS_EXIT
		syscall_exit(*(int *)argc[0]);
		break;
	case 2:  // SYS_EXEC
		f->eax = syscall_exec(*(const char **)argc[0]);
		break;
	case 3:  // SYS_WAIT
		//printf("CALLED SYS_WAIT!\n");
		f->eax = syscall_wait(*(pid_t *)argc[0]);
		break;
	case 4:  // SYS_CREATE
		f->eax = syscall_create(*(const char **)argc[0],
		                        *(unsigned *)argc[1]);
		break;
	case 5:  // SYS_REMOVE
		f->eax = syscall_remove(*(const char **)argc[0]);
		break;
	case 6:  // SYS_OPEN
		f->eax = syscall_open(*(const char **)argc[0]);
		break;
	case 7:  // SYS_FILESIZE
		f->eax = syscall_filesize(*(int *)argc[0]);
		break;
	case 8:  // SYS_READ
		f->eax = syscall_read(
				*(int *)argc[0],
				*(void **)argc[1],
				*(unsigned *)argc[2]
		);
		break;
	case 9:  // SYS_WRITE
		//printf("CALLED WRITE! %d %x %u\n", *(int *)argc[0], argc[1], *(unsigned *)argc[2]);
		f->eax = syscall_write(
				*(int *)argc[0],
				*(const void **)argc[1],
				*(unsigned *)argc[2]
		);
		break;
	case 10: // SYS_SEEK
		syscall_seek(*(int *)argc[0],
					 *(unsigned *)argc[1]
		);
		break;
	case 11: // SYS_TELL
		f->eax = syscall_tell(*(int *)argc[0]);
		break;
	case 12: // SYS_CLOSE
		syscall_close(*(int *)argc[0]);
		break;
	case 20:  // SYS_PIBONACCI
		f->eax = syscall_pibonacci(*(int *)argc[0]);
		break;
	case 21:  // SYS_SUM_OF_FOUR_INTEGERS
		f->eax = syscall_sum_of_four_integers(
				*(int *)argc[0],
				*(int *)argc[1],
				*(int *)argc[2],
				*(int *)argc[3]
		);
		break;
	// case *:
  }
  // printf("SYSCALL_RETURN: %d\n", f->eax);
  // thread_exit ();
  // XXX
}
Beispiel #7
0
/**
 * Handle system calls. Interrupts are enabled when this function is
 * called.
 *
 * @param user_context The userland context (CPU registers as they
 * where when system call instruction was called in userland)
 */
void syscall_handle(context_t *user_context)
{
  /* When a syscall is executed in userland, register a0 contains
   * the number of the syscall. Registers a1, a2 and a3 contain the
   * arguments of the syscall. The userland code expects that after
   * returning from the syscall instruction the return value of the
   * syscall is found in register v0. Before entering this function
   * the userland context has been saved to user_context and after
   * returning from this function the userland context will be
   * restored from user_context.
   */
  switch (A0) {
  case SYSCALL_HALT:
    halt_kernel();
    break;
  case SYSCALL_READ: {
      int filehandle = (int)A1;
      if (filehandle == FILEHANDLE_STDIN || filehandle == FILEHANDLE_STDOUT
        || filehandle == FILEHANDLE_STDERR) {
        V0 = io_read((int) A1, (void*) A2, (int) A3);
      } else {
        V0 = syscall_read((openfile_t)A1, (void *)A2, (int)A3);
      }
    }
    break;
  case SYSCALL_WRITE: {
      int filehandle = (int)A1;
      if (filehandle == FILEHANDLE_STDIN || filehandle == FILEHANDLE_STDOUT
        || filehandle == FILEHANDLE_STDERR) {
        V0 = io_write((int) A1, (void*) A2, (int) A3);
      } else {
        V0 = syscall_write((openfile_t)A1, (void *)A2, (int)A3);
      }
    }
    break;
  case SYSCALL_EXEC:
    V0 = syscall_exec((char*) A1);
    break;
  case SYSCALL_EXIT:
    syscall_exit((int) A1);
    break;
  case SYSCALL_JOIN:
    V0 = syscall_join((process_id_t) A1);
    break;
  case SYSCALL_OPEN:
    V0 = syscall_open((char *) A1);
  break;
  case SYSCALL_CLOSE:
    V0 = syscall_close((openfile_t) A1);
  break;
  case SYSCALL_SEEK:
    V0 = syscall_seek((openfile_t)A1, (int)A2);
  break;
  case SYSCALL_CREATE:
    V0 = syscall_create((const char *)A1, (int)A2);
  break;
  case SYSCALL_REMOVE:
    V0 = syscall_remove((const char *)A1);
  break;
  case SYSCALL_TELL:
    V0 = syscall_tell((openfile_t)A1);
  break;
  case SYSCALL_SEM_OPEN:
    V0 = (uint32_t) usr_sem_open((char*) A1, A2);
    break;
  case SYSCALL_SEM_PROCURE:
    V0 = usr_sem_p((usr_sem_t*) A1);
    break;
  case SYSCALL_SEM_VACATE:
    V0 = usr_sem_v((usr_sem_t*) A1);
    break;
  case SYSCALL_SEM_DESTROY:
    V0 = usr_sem_destroy((usr_sem_t*) A1);
    break;
  default:
    KERNEL_PANIC("Unhandled system call\n");
  }

  /* Move to next instruction after system call */
  user_context->pc += 4;
}