Example #1
0
int sys_fork(struct trapframe* tf, pid_t* retval) {
	int errcheck;    //this is to check if there's error in some funcitons
	//first creating a new proc
	struct proc* child = proc_create_runprogram("child123");
   //proctable_insert(child);
	if(child == NULL) {
		return ENOMEM;
	}
	curproc->child_pid = child->pid;
	curproc->child = child;      ///////////////
	child->parent = curproc;     //////////////
	
	//now, copying the address space
	struct addrspace* newas;
	errcheck = as_copy(curproc_getas(), &newas);
	if(errcheck != 0) {    //there's an error
		return errcheck;
	}
	child->p_addrspace = newas;
	
	//now copying the trapframe to the child
	struct trapframe* newtf = kmalloc(sizeof(struct trapframe));
	if(newtf == NULL) {
		return ENOMEM;
	}
	*newtf = *tf;
	//now, do the thread_fork
	errcheck = thread_fork("child2", child, enter_forked_process, newtf, 0);
	if(errcheck != 0) {
		return errcheck;
	}
	*retval = child->pid;
	return(0);
}
Example #2
0
int sys_read(int fd, void *buf, size_t buflen) {
    struct fd* tmp;
    if (!buf || buf == NULL || !valid_address_check(curproc->p_addrspace, (vaddr_t)buf)){      // else if invalid buffer
        errno = EFAULT;
        return -1;
    }
    if (fd < 0 || fd >= MAX_fd_table){       // if fd < 0 || fd > MAX_fd_table or 
        errno = EBADF;
        return -1;
    }
	else if (fd == STDOUT_FILENO || fd == STDERR_FILENO){      // fd == STDOUT_FILENO || STDERR_FILENO
            errno = EIO;
            return -1;
        }
        else if (fd >= 3 && fd < MAX_fd_table){
            tmp = curproc->fd_table[fd];
            if (tmp == NULL || (tmp->file_flag & O_WRONLY)){        // or if file is not readable
                errno = EBADF;  // error
                return -1;
            }
        }

        struct uio u;
        struct iovec iov;
        struct addrspace *as ;
        as = as_create();

        iov.iov_ubase = buf;
        iov.iov_len = buflen;

        u.uio_iov = &iov;
        u.uio_iovcnt = 1;
        u.uio_offset = tmp->offset;
        u.uio_resid = buflen;
        u.uio_segflg = UIO_USERSPACE;
        u.uio_rw = UIO_READ;
        u.uio_space = curproc_getas();
	
	if (fd == STDIN_FILENO){
		struct vnode *vn;
		char *console = NULL; // console string ("con:")
            console = kstrdup("con:"); // set to console
            vfs_open(console,O_RDONLY,0,&vn); // open the console vnode
            kfree(console); // free the console
            int result = VOP_READ(vn,&u);
            if(result < 0){
                    errno = EIO; //A hardware I/O error occurred writing the data
                    return -1;
            }
	} else{
	        int retval = VOP_READ(tmp->file, &u);
		if (retval < 0){
			errno = EIO;
			return -1;
		}
	}
	return buflen - u.uio_resid ;
}
Example #3
0
int
runprogram(char *progname)
{
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int result;

	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}

	/* We should be a new process. */
	KASSERT(curproc_getas() == NULL);

	/* Create a new address space. */
	#if OPT_A3
	as = as_create(progname);
	#else
	as = as_create();
	#endif
	if (as ==NULL) {
		vfs_close(v);
		return ENOMEM;
	}

	/* Switch to it and activate it. */
	curproc_setas(as);
	as_activate();

	/* Load the executable. */
	result = load_elf(v, &entrypoint);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		vfs_close(v);
		return result;
	}

	/* Done with the file now. */
	vfs_close(v);

	/* Define the user stack in the address space */
	result = as_define_stack(as, &stackptr);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		return result;
	}

	/* Warp to user mode. */
	enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/,
			  stackptr, entrypoint);
	
	/* enter_new_process does not return. */
	panic("enter_new_process returned\n");
	return EINVAL;
}
Example #4
0
/*
  Duplicates the currently running process
  The two copies are identical except for the child having a new pid
*/
int
sys_fork(struct trapframe *tf, int32_t *retval) {

  // Prevent interrupts so address space doesn't change before getting
  // copied
  int spl = splhigh();

  // Store trapframe on the heap for copying to child
  // thread later
  struct trapframe *child_tf;
  child_tf = kmalloc(sizeof(tf));
  if (child_tf == NULL) {
    splx(spl);
    return ENOMEM;
  }

  //memcpy(child_tf, tf, sizeof(tf));
  child_tf = tf;

  // Copy parent address space
  struct addrspace *original_as;
  struct addrspace *new_as;
  original_as = curproc_getas();
  int result = as_copy(original_as, &new_as);
  if (result) {
    splx(spl);
    return ENOMEM;
  }

  // Create new process
  struct proc *new_proc = proc_create(curproc->p_name);

  // Copy process fdlist
  for (int i = 0; i < __OPEN_MAX; i++) {
    if (curproc->p_fdlist[i] != NULL) {
      new_proc->p_fdlist[i] = curproc->p_fdlist[i];
      // Increment reference count
      new_proc->p_fdlist[i]->fd_vfile->vn_refcount++;
    }
  }

  //Child process needs to have parent pid attached to it
  set_parent(curproc->pid, new_proc->pid);

  // Fork new thread, attach to new proc
  result = thread_fork("Child process", new_proc, enter_forked_process, (void *)child_tf, (unsigned long)new_as);
  if (result) {
    kfree(child_tf);
    splx(spl);
    return result;  // Error code will be returned from thread_fork
  }

  // Set retval to child process pid
  *retval = new_proc->pid;
  splx(spl);
  return 0;
}
Example #5
0
void
as_activate(void)
{
	struct addrspace *as;

	as = curproc_getas();
	if (as == NULL) {
		/*
		 * Kernel thread without an address space; leave the
		 * prior address space in place.
		 */
		return;
	}

	/*
	 * Write this.
	 */
}
Example #6
0
/*
 * Load an ELF executable user program into the current address space.
 *
 * Returns the entry point (initial PC) for the program in ENTRYPOINT.
 */
int
load_elf(struct vnode *v, vaddr_t *entrypoint)
{
	Elf_Ehdr eh;   /* Executable header */
	Elf_Phdr ph;   /* "Program header" = segment header */
	int result, i;
	struct iovec iov;
	struct uio ku;
	struct addrspace *as;

	as = curproc_getas();

	/*
	 * Read the executable header from offset 0 in the file.
	 */

	uio_kinit(&iov, &ku, &eh, sizeof(eh), 0, UIO_READ);
	result = VOP_READ(v, &ku);
	if (result) {
		return result;
	}

	if (ku.uio_resid != 0) {
		/* short read; problem with executable? */
		kprintf("ELF: short read on header - file truncated?\n");
		return ENOEXEC;
	}

	/*
	 * Check to make sure it's a 32-bit ELF-version-1 executable
	 * for our processor type. If it's not, we can't run it.
	 *
	 * Ignore EI_OSABI and EI_ABIVERSION - properly, we should
	 * define our own, but that would require tinkering with the
	 * linker to have it emit our magic numbers instead of the
	 * default ones. (If the linker even supports these fields,
	 * which were not in the original elf spec.)
	 */

	if (eh.e_ident[EI_MAG0] != ELFMAG0 ||
	    eh.e_ident[EI_MAG1] != ELFMAG1 ||
	    eh.e_ident[EI_MAG2] != ELFMAG2 ||
	    eh.e_ident[EI_MAG3] != ELFMAG3 ||
	    eh.e_ident[EI_CLASS] != ELFCLASS32 ||
	    eh.e_ident[EI_DATA] != ELFDATA2MSB ||
	    eh.e_ident[EI_VERSION] != EV_CURRENT ||
	    eh.e_version != EV_CURRENT ||
	    eh.e_type!=ET_EXEC ||
	    eh.e_machine!=EM_MACHINE) {
		return ENOEXEC;
	}

	/*
	 * Go through the list of segments and set up the address space.
	 *
	 * Ordinarily there will be one code segment, one read-only
	 * data segment, and one data/bss segment, but there might
	 * conceivably be more. You don't need to support such files
	 * if it's unduly awkward to do so.
	 *
	 * Note that the expression eh.e_phoff + i*eh.e_phentsize is 
	 * mandated by the ELF standard - we use sizeof(ph) to load,
	 * because that's the structure we know, but the file on disk
	 * might have a larger structure, so we must use e_phentsize
	 * to find where the phdr starts.
	 */

	for (i=0; i<eh.e_phnum; i++) {
		off_t offset = eh.e_phoff + i*eh.e_phentsize;
		uio_kinit(&iov, &ku, &ph, sizeof(ph), offset, UIO_READ);

		result = VOP_READ(v, &ku);
		if (result) {
			return result;
		}

		if (ku.uio_resid != 0) {
			/* short read; problem with executable? */
			kprintf("ELF: short read on phdr - file truncated?\n");
			return ENOEXEC;
		}

		switch (ph.p_type) {
		    case PT_NULL: /* skip */ continue;
		    case PT_PHDR: /* skip */ continue;
		    case PT_MIPS_REGINFO: /* skip */ continue;
		    case PT_LOAD: break;
		    default:
			kprintf("loadelf: unknown segment type %d\n", 
				ph.p_type);
			return ENOEXEC;
		}

		result = as_define_region(as,
					  ph.p_vaddr, ph.p_memsz,
					  ph.p_flags & PF_R,
					  ph.p_flags & PF_W,
					  ph.p_flags & PF_X);
		if (result) {
			return result;
		}
	}

	result = as_prepare_load(as);
	if (result) {
		return result;
	}

	/*
	 * Now actually load each segment.
	 */

	for (i=0; i<eh.e_phnum; i++) {
		off_t offset = eh.e_phoff + i*eh.e_phentsize;
		uio_kinit(&iov, &ku, &ph, sizeof(ph), offset, UIO_READ);

		result = VOP_READ(v, &ku);
		if (result) {
			return result;
		}

		if (ku.uio_resid != 0) {
			/* short read; problem with executable? */
			kprintf("ELF: short read on phdr - file truncated?\n");
			return ENOEXEC;
		}

		switch (ph.p_type) {
		    case PT_NULL: /* skip */ continue;
		    case PT_PHDR: /* skip */ continue;
		    case PT_MIPS_REGINFO: /* skip */ continue;
		    case PT_LOAD: break;
		    default:
			kprintf("loadelf: unknown segment type %d\n", 
				ph.p_type);
			return ENOEXEC;
		}

		result = load_segment(as, v, ph.p_offset, ph.p_vaddr, 
				      ph.p_memsz, ph.p_filesz,
				      ph.p_flags & PF_X);
		if (result) {
			return result;
		}
	}

	result = as_complete_load(as);
	if (result) {
		return result;
	}

	*entrypoint = eh.e_entry;

	return 0;
}
Example #7
0
runprogram(char *progname)
#endif
{
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int result;

	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}

	/* We should be a new process. */
	KASSERT(curproc_getas() == NULL);

	/* Create a new address space. */
	as = as_create();
	if (as ==NULL) {
		vfs_close(v);
		return ENOMEM;
	}

	/* Switch to it and activate it. */
  curproc_setas(as);
  as_activate();

	/* Load the executable. */
	result = load_elf(v, &entrypoint);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		vfs_close(v);
		return result;
	}

	/* Done with the file now. */
	vfs_close(v);

	/* Define the user stack in the address space */
	result = as_define_stack(as, &stackptr);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		return result;
	}

#if OPT_A2
  // How much space do we need for args in stack?
  // We need space for each pointer (4argc)
  // We need space for each character, including NULL termination, plus
  // padding to make multiples of 4
  int stringSpace = 0;
  for (unsigned long i = 0; i < argc; i++) {
    stringSpace += strlen(argv[i]) + 1;
  }

  // Align stack pointer to an 8-byte alignment
  while ((stackptr - (4*argc) - stringSpace) % 8 != 0) {
    stackptr--;
  }

  // Use a vaddr array to track the addresses the strings end up in
  // One bigger than argc to also have the pointer to the final NULL
  // value
  vaddr_t stringAddr[argc+1];

  // Copy argument strings onto stack
  // Array must end with NULL pointer, so do that first
  stackptr -= 4;
  copyout((void *)NULL, (userptr_t)stackptr, (size_t)4);
  stringAddr[argc] = stackptr;
  for (int i = argc-1; i >= 0; i--) {
    stackptr -= strlen(argv[i]) + 1;
    while (stackptr % 4 != 0) stackptr--;
    copyoutstr(argv[i], (userptr_t)stackptr, (size_t)strlen(argv[i]), NULL);
    stringAddr[i] = stackptr;
  }

  // Now use the stored addresses of the string to add the appropriate
  // pointers to the stack
  for (int i = argc; i >= 0; i--) {
    stackptr -= sizeof(vaddr_t);
    copyout(&stringAddr[i], (userptr_t)stackptr, sizeof(vaddr_t));
  }

	/* Warp to user mode. */
	enter_new_process(argc /*argc*/, (userptr_t)stackptr /*userspace addr of argv*/,
			  stackptr, entrypoint);
#else
	/* Warp to user mode. */
	enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/,
			  stackptr, entrypoint);
#endif

	/* enter_new_process does not return. */
	panic("enter_new_process returned\n");
	return EINVAL;
}
Example #8
0
int sys_execv(userptr_t progname_ptr, userptr_t args_ptr){

	
	char* prog_name = kmalloc(PATH_MAX); 
	size_t prog_name_len;
	if((char*)progname_ptr == NULL || (char**)args_ptr == NULL){
		return EFAULT;
	}
	int argc = 0;
	char** args_ptrs = kmalloc(ARG_MAX);
        while(1){
                char* arg = NULL;
                copyin(args_ptr+argc*sizeof(char*), &arg, sizeof(char*));
		args_ptrs[argc] = arg;
		if(arg != NULL){
			argc++;
		}else{
			break;
		}
	}
	if(argc> 64){
		return E2BIG;
	}

	int result_prog_name = copyinstr(progname_ptr,prog_name,PATH_MAX, &prog_name_len);
	if(result_prog_name != 0){
		return result_prog_name;
	}


	char* argv = kmalloc(ARG_MAX);
	size_t * arg_offsets = kmalloc(argc * sizeof(size_t));
        int offset = 0;
	for(int i = 0; i < argc; i++){
		//char* arg = kmalloc(ARG_MAX);
		size_t arg_len;
		int result = copyinstr((userptr_t)args_ptrs[i],
				 argv+offset, ARG_MAX - offset, &arg_len );
		if(result != 0){
			return result;
		}
		arg_offsets[i] = offset;
		offset += ROUNDUP(arg_len+1,8);
		//argv[i] = arg;
	}

	// prog_name (char*)   AND   argv (char*)

	struct addrspace *curproc_as = curproc_getas();
	

	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	vaddr_t cur_ptr;
	int result;
	/* Open the file. */
	result = vfs_open(prog_name, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}

	/* Create a new address space. */
	as = as_create();
	if (as ==NULL) {
		vfs_close(v);
		return ENOMEM;
	}
	/* Switch to it and activate it. */
	curproc_setas(as);
	as_activate();
	/* Load the executable. */
	result = load_elf(v, &entrypoint);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		vfs_close(v);
		return result;
	}
	/* Done with the file now. */
	vfs_close(v);
	/* Define the user stack in the address space */
	result = as_define_stack(as, &stackptr);

	// Have both argc and prog_name ready for runprogram
	cur_ptr = stackptr;
	cur_ptr -= offset;
	result = copyout(argv, (userptr_t)cur_ptr, offset);
	if(result != 0){
		return result;
	}

	userptr_t * arg_offsets_up = kmalloc(sizeof(userptr_t) * (argc+1));
	for(int i = 0; i < argc; i++){
		userptr_t ptr = (userptr_t)cur_ptr +  arg_offsets[i];
		arg_offsets_up[i] = ptr;
	}
	arg_offsets_up[argc] = NULL;

	cur_ptr -= sizeof(userptr_t) * (argc+1);

	result = copyout(arg_offsets_up, (userptr_t)cur_ptr, sizeof(userptr_t) * (argc+1) );

	if(result != 0){
		return result;
	}

	as_destroy(curproc_as);
	kfree(arg_offsets);
	kfree(arg_offsets_up);
	kfree(argv);
	kfree(args_ptrs);
	kfree(prog_name);

	enter_new_process(argc /*argc*/, (userptr_t)cur_ptr /*userspace addr of argv*/,
	cur_ptr, entrypoint);
	/* enter_new_process does not return. */
	panic("enter_new_process returned\n");
	return EINVAL;

	//return 0;
}
Example #9
0
/*
 * Load program "progname" and start running it in usermode.
 * Does not return except on error.
 *
 * Calls vfs_open on progname and thus may destroy it.
 */
int
runprogram(char *progname, char **args, unsigned int nargs)
{
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int result;

        int argc = nargs;
        char **argv = (char **)kmalloc((argc + 1) * sizeof(char *));
        if(argv == NULL)
        {
            return ENOMEM;
        }

        for(int i = 0; i < argc; ++i)
        {
            argv[i] = args[i];
        }
        argv[argc] = NULL;
       
       
	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}

	/* We should be a new process. */
	KASSERT(curproc_getas() == NULL);

	/* Create a new address space. */
	as = as_create();
	if (as ==NULL) {
		vfs_close(v);
		return ENOMEM;
	}

	/* Switch to it and activate it. */
	curproc_setas(as);
	as_activate();

	/* Load the executable. */
	result = load_elf(v, &entrypoint);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		vfs_close(v);
		return result;
	}

	/* Done with the file now. */
	vfs_close(v);

	/* Define the user stack in the address space */
	result = as_define_stack(as, &stackptr);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		return result;
	}

        /*------copy args to user stack-----------*/
        
        vaddr_t *argPtrs = (vaddr_t *)kmalloc((argc + 1) * sizeof(vaddr_t));
        if(argPtrs == NULL)
        {
            for(int i = 0; i < argc; ++i)
            {
                kfree(argv[i]);
            }
            kfree(argv);
            as_deactivate();
            as = curproc_setas(NULL);
            as_destroy(as);
            return ENOMEM;
        }
        
        for(int i = argc-1; i >= 0; --i)
        {
            //arg length with null
            size_t curArgLen = strlen(argv[i]) + 1;
            
            size_t argLen = ROUNDUP(curArgLen,4);
            
            stackptr -= (argLen * sizeof(char));
            
            //kprintf("copying arg: %s to addr: %p\n", temp, (void *)stackptr);
            
            //copy to stack
            result = copyout((void *) argv[i], (userptr_t)stackptr, curArgLen);
            if(result)
            {
                kfree(argPtrs);
                for(int i = 0; i < argc; ++i)
                {
                    kfree(argv[i]);
                }
                kfree(argv);
                as_deactivate();
                as = curproc_setas(NULL);
                as_destroy(as);
                return result;
            }
            
            argPtrs[i] = stackptr;        
        }    
        
        argPtrs[argc] = (vaddr_t)NULL;
        
        //copy arg pointers
        for(int i = argc; i >= 0; --i)
        {
            stackptr -= sizeof(vaddr_t);
            result = copyout((void *) &argPtrs[i], ((userptr_t)stackptr),sizeof(vaddr_t));
            if(result)
            {
                kfree(argPtrs);
                for(int i = 0; i < argc; ++i)
                {
                    kfree(argv[i]);
                }
                kfree(argv);
                as_deactivate();
                as = curproc_setas(NULL);
                as_destroy(as);
                return result;
            }
        }
        
        
        kfree(argPtrs);
        
        
        
        
        vaddr_t baseAddress = USERSTACK;
        
        vaddr_t argvPtr = stackptr;
        
        vaddr_t offset = ROUNDUP(USERSTACK - stackptr,8);
        
        stackptr = baseAddress - offset;
        
/*
        for(vaddr_t i = baseAddress; i >= stackptr; --i)
        {
            char *temp;
            temp = (char *)i;
            //kprintf("%p: %c\n",(void *)i,*temp);
            
            kprintf("%p: %x\n", (void *)i, *temp & 0xff);
        }
*/
        
        
        /*-done-copy args to user stack-----------*/
        
	/* Warp to user mode. */
	enter_new_process(argc /*argc*/, (userptr_t)argvPtr /*userspace addr of argv*/,
			  stackptr, entrypoint);
	
	/* enter_new_process does not return. */
	panic("enter_new_process returned\n");
	return EINVAL;
}
Example #10
0
runprogram(char *progname)
#endif
{
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int result;

	//kprintf("bla0\n");
	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}
	//kprintf("bla1\n");
	/* We should be a new process. */
	KASSERT(curproc_getas() == NULL);
	//kprintf("bla2\n");
	/* Create a new address space. */
	as = as_create();
	if (as ==NULL) {
		vfs_close(v);
		return ENOMEM;
	}
	//kprintf("bla3\n");
	/* Switch to it and activate it. */
	curproc_setas(as);
	as_activate();
	//kprintf("bla4\n");
	/* Load the executable. */
	result = load_elf(v, &entrypoint);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		vfs_close(v);
		return result;
	}
	//kprintf("bla5\n");
	/* Done with the file now. */
	vfs_close(v);

	/* Define the user stack in the address space */
	result = as_define_stack(as, &stackptr);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		return result;
	}

#if OPT_A2
	//kprintf("bla6\n");
	if(args == NULL){
		return EFAULT;
	}	
	// copy args to user
	size_t len = sizeof(char *) * (num + 1);
	char **copyargs = kmalloc(len);
 	for(unsigned long int i = 0; i < num; i++){
    	len = strlen(args[i]) + 1;
    	stackptr = stackptr - ROUNDUP(len, 8);//? limit or valid stackptr //new

    	result = copyoutstr(args[i], (userptr_t)stackptr, len, NULL);//new
    	if(result){
    		kfree(copyargs);
      		return result;
    	}

    	copyargs[i] = (char *)stackptr;
  	}
  	copyargs[num] = NULL;

  	// copy arr
  	len = sizeof(char *) * (num + 1);
 	stackptr = stackptr - ROUNDUP(len, 8);
  	result = copyout(copyargs, (userptr_t)stackptr, len);
  	kfree(copyargs);
  	if(result){
    	return result;
  	}

  	userptr_t stackk = (userptr_t)stackptr;

  	enter_new_process(num /*argc*/, stackk /*userspace addr of argv*/,
			  stackptr, entrypoint);
#else
	/* Warp to user mode. */
	enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/,
			  stackptr, entrypoint);
#endif
	
	/* enter_new_process does not return. */
	panic("enter_new_process returned\n");
	return EINVAL;
}
Example #11
0
/*
 * Load program "progname" and start running it in usermode.
 * Does not return except on error.
 *
 * Calls vfs_open on progname and thus may destroy it.
 */
int
runprogram(char *progname, char** args, size_t nargs)
{
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int result;
	int argc = 0;

	while(args[argc] != NULL) {
	    argc++;
	}



	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}

	/* We should be a new process. */
	KASSERT(curproc_getas() == NULL);

	/* Create a new address space. */
	as = as_create();
	if (as ==NULL) {
		vfs_close(v);
		return ENOMEM;
	}

	/* Switch to it and activate it. */
	curproc_setas(as);
	as_activate();

	/* Load the executable. */
	result = load_elf(v, &entrypoint);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		vfs_close(v);
		return result;
	}

	/* Done with the file now. */
	vfs_close(v);

	/* Define the user stack in the address space */
	result = as_define_stack(as, &stackptr);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		return result;
	}

	#if OPT_A2

	while(stackptr %8 != 0)
		stackptr--;

	vaddr_t argptr[argc + 1];
	for (int i = argc - 1; i >= 0; i--)
	{
		stackptr -= strlen(args[i]) + 1;
		result = copyoutstr(args[i], (userptr_t) stackptr, strlen(args[i]) + 1, NULL);
		if(result)
			return result;
		argptr[i] = stackptr;
	}

	while(stackptr % 4 != 0)
		stackptr--;
	//int hack = (int) nargs;

	argptr[nargs] = 0;

	for (int i = argc; i >= 0; i--)
	{
		stackptr -= ROUNDUP(sizeof(vaddr_t), 4);
		result = copyout(&argptr[i], (userptr_t) stackptr, sizeof(vaddr_t));
		if(result)
			return result;
	}
	#endif
	/* Warp to user mode. */
	enter_new_process(nargs /*argc*/, (userptr_t) stackptr /*userspace addr of argv*/,
			  stackptr, entrypoint);
	
	/* enter_new_process does not return. */
	panic("enter_new_process returned\n");
	return EINVAL;
}
Example #12
0
File: coremap.c Project: mellwa/os
paddr_t coremap_getFrames(unsigned long n, bool swappable, int seg_type) {
	paddr_t paddr;
    paddr = 0;
	// requesting too many pages
	if(n*PAGE_SIZE + lo_paddr > hi_paddr) {
        paddr = 0;
	}
    (void) seg_type;
	
	struct coremap_entry ** coremap = get_global_coremap();
	
	// grab lock for synchronization
	lock_acquire(coremap_lk);

	for(unsigned int i = 0; i < max_pages; i++) {
		if(!coremap[i]->cm_occupied) {
			// set in page table global_coremap[i];
			bool lengthFree = true;
			// try and find n continous frames
			for(unsigned int j = i + 1; (j < i + n) && (j < max_pages); j++) {
				// if its not n continous frames
				if(coremap[j]->cm_occupied) {
					lengthFree = false;
					break;
				}
			}
			
			// after found n continous frames, allocate them
			if(lengthFree && (i + n < max_pages)) {
				paddr = coremap[i]->cm_paddr;
				for(unsigned int j = i; j < i + n; j++) {
					coremap[j]->cm_occupied = true;
					coremap[j]->cm_length = n - (j - i);
					coremap[j]->cm_proc = curproc;
					coremap[j]->cm_swappable = swappable;
                    coremap[j]->seg_type = seg_type;
				}
				lock_release(coremap_lk);
                return paddr;
			}
		}
	}
	
	// if paddr = 0 at this point, we want to evict something
	// from physical memory
    struct addrspace *as;
    as = curproc_getas();
    if(as == NULL) {
	    // debug
	    // printCoremap();
    }
    
    // else the coremap is full
    struct pt_entry* pte;
	if(paddr == 0){
		// find a page victim
        pte = Pvictim(as, seg_type);
        // claim it
        coremap[pte->cm_index]->cm_proc = curproc;
        coremap[pte->cm_index]->cm_swappable = swappable;
        
        paddr = coremap[pte->cm_index]->cm_paddr;
        lock_release(coremap_lk);
        // write it to the swapfile
        write_to_swap(pte);
    }
    
	return paddr;
}
Example #13
0
int sys_write(int fd, const void *buf, size_t nbytes) {
	if (!buf || buf == NULL || !valid_address_check(curproc->p_addrspace, (vaddr_t)buf)){      // invalid buffer OR buffer out of range
	        errno = EFAULT;
	        return -1;
	}
	if(fd < 0 || fd >= MAX_fd_table){
	        errno = EBADF;
	        return -1;
	} else if (fd == STDIN_FILENO){	// fd == STDIN_FILENO
		errno = EIO;
		return -1;
	} else if (fd >= 3 && fd < MAX_fd_table){		// have valid fd
		struct fd* tmp = curproc->fd_table[fd];
//                if (tmp == NULL || (tmp->file_flag & O_RDONLY)){	// but have no file at fd OR file at fd is RDONLY
		if (tmp == NULL){ 
			errno = EBADF;
			return -1;
		}
		switch(tmp->file_flag & O_ACCMODE){
			case O_WRONLY: break;
			case O_RDWR:   break;
			default:
				errno = EBADF;
				return -1;
		}
	}

	struct vnode *vn; // creating vnode (temp)
	struct uio u;
	struct iovec iov;
	struct addrspace *as;

	as = as_create();

	iov.iov_ubase = (void *)buf;
	iov.iov_len = nbytes;

	u.uio_iov = &iov;
	u.uio_resid = nbytes;
    u.uio_rw = UIO_WRITE;
    u.uio_segflg = UIO_USERSPACE;
    u.uio_space = curproc_getas();

	if(fd == STDOUT_FILENO || fd == STDERR_FILENO){
		char *console = NULL; // console string ("con:")
		console = kstrdup("con:"); // set to console
		vfs_open(console,O_WRONLY,0,&vn); // open the console vnode
		kfree(console); // free the console
		int result = VOP_WRITE(vn,&u);
		if(result < 0){
			errno = EIO; //A hardware I/O error occurred writing the data
			return -1;
		}
	}
	else{
		u.uio_offset = curproc->fd_table[fd]->offset;
		VOP_WRITE(curproc->fd_table[fd]->file, &u);
		if(u.uio_resid){
			errno = ENOSPC; //There is no free space remaining on the filesystem containing the file
			return -1;
		}
		curproc->fd_table[fd]->offset += nbytes - u.uio_resid;
		curproc->fd_table[fd]->buflen += nbytes - u.uio_resid; //update buflength of fd
	}
	
	return nbytes - u.uio_resid;
}
Example #14
0
int
runprogram(char *progname, unsigned long argc, char **argv)
{	
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int result;
    
	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}
    
	/* We should be a new process. */
	KASSERT(curproc_getas() == NULL);
    
	/* Create a new address space. */
	#if OPT_A3
	as = as_create(progname);
	#else
	as = as_create();
	#endif
	if (as ==NULL) {
		vfs_close(v);
		return ENOMEM;
	}

    
	/* Switch to it and activate it. */
	curproc_setas(as);
	as_activate();
    

    
	/* Load the executable. */
	result = load_elf(v, &entrypoint);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		vfs_close(v);
		return result;
	}

	/* Done with the file now. */
	vfs_close(v);
    
 
	/* Define the user stack in the address space */
	result = as_define_stack(as, &stackptr); // find the stack pointer
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		return result;
	}

    
    //add stuff
    stackptr = stackptr - (argc + 1)*sizeof(vaddr_t); //subtract number of arguments + 1 (space for pointers)
    
    unsigned long i;
    unsigned int len;
    unsigned int len2;
    char **buf = (char **)stackptr; // argv

    for(i=0; i<argc; i++){
        len = (strlen(argv[i])+1)*(sizeof(char)); // first str length + null char
        stackptr = stackptr - len; // adjust stack pointer for length of str

        buf[i] = (char*)stackptr; // assign pointer to argv[i]
        copyoutstr((void *)argv[i],(userptr_t)buf[i],len,&len2); // copy to userstack
    }
    unsigned int remainder = stackptr % 8;
	if(remainder != 0){
		stackptr = stackptr - remainder;
	}
    
    // pass arguments to user program
	/* Warp to user mode. */
	enter_new_process(argc, (userptr_t)buf /*userspace addr of argv*/,
                      stackptr, entrypoint);

	// stores into trap->a0 as argc
	// stores trap->a1 as argv
	// sets stack pointer
	
    
	/* enter_new_process does not return. */
	panic("enter_new_process returned\n");
	return EINVAL;
}
Example #15
0
int sys_execv(userptr_t progname, userptr_t args) {
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int result;
	
	char * path = kmalloc(PATH_MAX);

	as = curproc_getas();

	if (as != NULL && !valid_address_check(as, (vaddr_t)args)) { // out of vaddr boundary for this proc
		errno = EFAULT;
		return -1;
	}
	if (as != NULL && !valid_address_check(as, (vaddr_t)progname)) { // out of vaddr boundary for this proc
		errno = EFAULT;
		return -1;
	}

	result = copyinstr(progname, path, PATH_MAX, NULL);
	if(result) {
		return result;
	}
	if(*path == '\0') {
		errno = EISDIR;
		return -1;
	}

	// Open the executable, create a new address space and load the elf into it

	result = vfs_open((char *)path, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}
	// KASSERT(curproc_getas() == NULL);

	as = as_create();
	if (as == NULL) {
		vfs_close(v);
		return ENOMEM;
	}

	curproc_setas(as);
	as_activate();

	result = load_elf(v, &entrypoint);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		vfs_close(v);
		return result;
	}
	vfs_close(v);

	result = as_define_stack(as, &stackptr); // stackptr set
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		return result;
	}
	kfree(path);

	userptr_t karg, uargs, argbase;
	char * buffer, * bufend;
	buffer = kmalloc(sizeof(ARG_MAX));
	if(buffer == NULL) {
		errno = ENOMEM;
		return -1;
	}
	bufend = buffer;
	size_t resid, bufsize;
	size_t alen;
	size_t *offsets = kmalloc(NARG_MAX * sizeof(size_t));
	if(offsets == NULL) {
		errno = ENOMEM;
		return -1;
	}
	int size = 0;
	userptr_t arg;


	resid = bufsize = ARG_MAX;

	for(int i = 0 ; i < NARG_MAX ; i++) { // copyin from user.
		copyin(args, &karg, sizeof(userptr_t)); // copy the pointer.
		if(karg == NULL) break; // if NULL, break.
		copyinstr(karg, bufend, resid, &alen);
		offsets[i] = bufsize - resid;
		bufend += alen;
		resid -= alen;
		args += sizeof(userptr_t);
		size++;
	}

	size_t buflen = bufend - buffer; // length of buffer.
	vaddr_t stack = stackptr - buflen; // current stack position.
	stack -= (stack & (sizeof(void *) - 1)); // alignment
	argbase = (userptr_t)stack; // argbase.

	copyout(buffer, argbase, buflen); // copy the arguments into stack.

	stack -= (size + 1)*sizeof(userptr_t); // go to array pointer (bottom of stack).
	uargs = (userptr_t)stack; // got stack.

	for(int i = 0 ; i < size ; i++) { // copy the elements
		arg = argbase + offsets[i];
		copyout(&arg, uargs, sizeof(userptr_t));
		uargs += sizeof(userptr_t); // 4
	}
	arg = NULL;
	copyout(&arg, uargs, sizeof(userptr_t)); // copy the NULL pointer.



	kfree(buffer);
	kfree(offsets);

	enter_new_process(size /*argc*/, (userptr_t)stack /*userspace addr of argv*/,
			  stack, entrypoint);

	return 0;

}