void
as_activate(void)
{
    struct addrspace *as;

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

    /*
     * Write this.
     */

    int i, spl;
    spl = splhigh();

    for (i=0; i<NUM_TLB; i++) {
        tlb_write(TLBHI_INVALID(i), TLBLO_INVALID(), i);
    }

    splx(spl);
}
Example #2
0
void
as_activate(void)
{
	struct addrspace *as;

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

	/*
	 * Write this.
	 */
}
Example #3
0
void
as_activate(void)
{
	struct addrspace *as;

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

	// Context switch happens, shootdown everything
	// ipi_tlbshootdown_allcpus(&(const struct tlbshootdown){vaddr, sem_create("Shootdown", 0)});
	vm_tlbflush_all();
}
/* Fault handling function called by trap code */
int vm_fault(int faulttype, vaddr_t faultaddress) {
	struct addrspace* as = proc_getas();
	if (as == NULL) {
		//kprintf("AS was null\n");
		return EFAULT;
	}
	struct region* reg = findRegionForFaultAddress(as, faultaddress);
	if (reg == NULL) {
		//kprintf("Region not found\n");
		return EFAULT;
	}
	// TODO Check if it is a permission issue and return an error code in that case.

	// get page
	struct page* pg = findPageForFaultAddress(as, faultaddress);
	if (pg == NULL) {
		struct page* newpage = page_create(as, faultaddress);
		pg = newpage;
	}
	if (pg == NULL) {
		//kprintf("Failed to create a page\n");
		return EFAULT;
	}
	if (pg->pt_state == PT_STATE_SWAPPED) {
		//kprintf("Trying swap out from %x\n",pg->pt_pagebase);
		//kprintf("Swap out page Vaddr = %x\n",pg->pt_virtbase);
		swapout(as, pg);
		//kprintf("after swap out paddr = %x\n",pg->pt_pagebase);
		//kprintf("after Swap out Vaddr = %x\n", pg->pt_virtbase);
		//kprintf("after Swap out state = %d\n",pg->pt_state);
	}

	// load page address to tlb
	int spl = splhigh();
	tlb_random(pg->pt_virtbase * PAGE_SIZE,
			(pg->pt_pagebase * PAGE_SIZE) | TLBLO_DIRTY | TLBLO_VALID);
	splx(spl);
	(void) faulttype;
	return 0;
}
int sys_sbrk(userptr_t amount, int32_t* retval) {
	*retval = 0;
	if ((int) amount % PAGE_SIZE != 0) {
		*retval = -1;
		return EINVAL;
	}
	if ((int) amount > 1024 * 256 * PAGE_SIZE) {
		*retval = -1;
		return ENOMEM;
	}
	struct addrspace* as = proc_getas();
	//kprintf("SBRK CALLED WITH PARAMS %x, newregion start = %x\n", (int) amount,
	//				as->as_addrPtr);
	if (as->as_heapBase == 0) {
		as->as_heapBase = as->as_addrPtr;
	}
	if (amount == 0) {
		*retval = as->as_addrPtr;
		return 0;
	}

	if ((int) amount < 0) {
		if ((int) (amount + as->as_addrPtr) < (int) (as->as_heapBase)) {
			*retval = -1;
			return EINVAL;
		}
		return reduceHeapSize(amount, retval, as);

	}

	vaddr_t newRegionStart = as->as_addrPtr;
	as_define_region(as, newRegionStart, (int) amount, 1, 1, 0);

	*retval = newRegionStart;
	return 0;
}
Example #6
0
int sys_execv(char* progname, char** args, int *retval, bool iskernel) {
	int result;
	int *args_len;
	size_t len;
	size_t total_len = 0;
	char *temp;
	char **kern_args;
	int nargs = 0;
	userptr_t *usr_argv = NULL;
	char *kern_progname = kmalloc(PATH_MAX);
	args_len = kmalloc(sizeof(int) * ARG_MAX);
	temp = kmalloc(sizeof(char) * ARG_MAX);

	if (kern_progname == NULL || args_len == NULL || temp == NULL){
		*retval = -1;
		return ENOMEM;
	}

	if (args == NULL || progname == NULL) {
		*retval = -1;
		return EFAULT;
	}

	if (!iskernel) {
		result = copyinstr((userptr_t)args, temp, ARG_MAX, &len);
		if (result) {
			*retval = -1;
			return result;
		}
	}

	// Figure out nargs, and the length for each arg string
	while(args[nargs] != NULL) {
		if (iskernel) {
			len = strlen(args[nargs]) + 1;
			if (len == 1) {
				nargs--;
				break;
			}
			strcpy(temp, args[nargs]);
		} else {
			result = copyinstr((userptr_t)args[nargs], temp, ARG_MAX, &len);
			if (result) {
				*retval = -1;
				return result;
			}
		}
		args_len[nargs] = len;
		total_len += len;
		nargs += 1;
	}
	kfree(temp);

	if (total_len > ARG_MAX) {
		*retval = -1;
		return E2BIG;
	}

	kern_args = kmalloc(sizeof(char*) * nargs);

	// Go through args and copy everything over to kern_args using copyinstr
	for (int i = 0; i < nargs; i++) {
		kern_args[i] = kmalloc(sizeof(char) * args_len[i]);
		if (kern_args[i] == NULL) {
			*retval = -1;
			return ENOMEM;
		}

		if (iskernel) {
			strcpy(kern_args[i], args[i]);
			len = strlen(kern_args[i]);
		} else {
			copyinstr((userptr_t)args[i], kern_args[i], ARG_MAX, NULL);
		}
	}

	// This is from runprogram 
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;


	if (iskernel) {
		strcpy(kern_progname, progname);
		len = strlen(kern_progname);
	} else {
		result = copyinstr((userptr_t)progname, kern_progname, PATH_MAX, NULL);
	}

	if (*kern_progname == 0) {
		*retval = -1;
		return EISDIR;
	}
	if (result) {
		kfree(kern_progname);
		*retval = -1;
		return result;
	}

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

	// Blow up the current addrspace. TODO, this may be problematic
	if (!iskernel) {
		as_destroy(curproc->p_addrspace);
		curproc->p_addrspace = NULL;
	}

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

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

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

	/* Intialize file table, not needed for execv */
	if (iskernel)
		filetable_init();

	/* Load the executable. */
	result = load_elf(v, &entrypoint);
	if (result) {
		/* p_addrspace will go away when curproc is destroyed */
		vfs_close(v);
		*retval = -1;
		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 */
		*retval = -1;
		return result;
	}

	// Clear space for arg pointers +1 for NULL terminator
	stackptr -= (sizeof(char*)) * (nargs + 1);

	// Convenience method for indexing
	usr_argv = (userptr_t*)stackptr;

	for(int i = 0; i < nargs; i++ ) {
		// Clear out space for an arg string
		stackptr -= sizeof(char) * (strlen(kern_args[i]) + 1);
		// Assign the string's pointer to usr_argv
		usr_argv[i] = (userptr_t)stackptr;
		// Copy over string
		copyout(kern_args[i], usr_argv[i],
			sizeof(char) * (strlen(kern_args[i]) + 1));
	}

	// NULL terminate usr_argv
	usr_argv[nargs] = NULL;

	// Free memory
	for(int i = 0; i < nargs; i++) {
		kfree(kern_args[i]);
	}
	kfree(kern_args);

	/* Warp to user mode. */
	enter_new_process(nargs /*argc*/, (userptr_t)usr_argv /*userspace addr of argv*/,
			  NULL /*userspace addr of environment*/,
			  stackptr, entrypoint);

	/* enter_new_process does not return. */
	panic("enter_new_process returned\n");
	return EINVAL;
}
Example #7
0
int
uiomove(void *ptr, size_t n, struct uio *uio)
{
	struct iovec *iov;
	size_t size;
	int result;

	if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) {
		panic("uiomove: Invalid uio_rw %d\n", (int) uio->uio_rw);
	}
	if (uio->uio_segflg==UIO_SYSSPACE) {
		KASSERT(uio->uio_space == NULL);
	}
	else {
		KASSERT(uio->uio_space == proc_getas());
	}

	while (n > 0 && uio->uio_resid > 0) {
		/* get the first iovec */
		iov = uio->uio_iov;
		size = iov->iov_len;

		if (size > n) {
			size = n;
		}

		if (size == 0) {
			/* move to the next iovec and try again */
			uio->uio_iov++;
			uio->uio_iovcnt--;
			if (uio->uio_iovcnt == 0) {
				/*
				 * This should only happen if you set
				 * uio_resid incorrectly (to more than
				 * the total length of buffers the uio
				 * points to).
				 */
				panic("uiomove: ran out of buffers\n");
			}
			continue;
		}

		switch (uio->uio_segflg) {
		    case UIO_SYSSPACE:
			    result = 0;
			    if (uio->uio_rw == UIO_READ) {
				    memmove(iov->iov_kbase, ptr, size);
			    }
			    else {
				    memmove(ptr, iov->iov_kbase, size);
			    }
			    iov->iov_kbase = ((char *)iov->iov_kbase+size);
			    break;
		    case UIO_USERSPACE:
		    case UIO_USERISPACE:
			    if (uio->uio_rw == UIO_READ) {
				    result = copyout(ptr, iov->iov_ubase,size);
			    }
			    else {
				    result = copyin(iov->iov_ubase, ptr, size);
			    }
			    if (result) {
				    return result;
			    }
			    iov->iov_ubase += size;
			    break;
		    default:
			    panic("uiomove: Invalid uio_segflg %d\n",
				  (int)uio->uio_segflg);
		}

		iov->iov_len -= size;
		uio->uio_resid -= size;
		uio->uio_offset += size;
		ptr = ((char *)ptr + size);
		n -= size;
	}

	return 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(proc_getas() == NULL);

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

    /* Switch to it and activate it. */
    proc_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;
    }

    struct vnode* v1;
    struct vnode* v2;
    struct vnode* v3;

    const char* name = "con:";


    char *con_name = kstrdup(name);
    char *con_name2 = kstrdup(name);
    char *con_name3 = kstrdup(name);



    /*char con_name[5];
    char con_name2[5];
    char con_name3[5];

    strcpy(con_name,name);
    strcpy(con_name2,name);
    strcpy(con_name3,name);
    */

    result = vfs_open(con_name, O_RDONLY, 0664, &v1);
    if(result)
    {
        return result;
    }

    result = vfs_open(con_name2, O_WRONLY, 0664, &v2);
    if(result)
    {
        return result;
    }
    result = vfs_open(con_name3, O_WRONLY, 0664, &v3);
    if(result)
    {
        return result;
    }
    kfree(con_name);
    kfree(con_name2);
    kfree(con_name3);
    struct file_handle* fh1 = file_handle_create();
    fh1->file = v1;
    fh1->openflags = O_RDONLY;
    fh1->ref_count  = 1;
    strcpy(fh1->file_name,"con:");
    curproc->t_file_table[0] = fh1;

    struct file_handle* fh2 = file_handle_create();
    fh2->file = v2;
    fh2->openflags = O_WRONLY;
    fh2->ref_count = 1;
    strcpy(fh2->file_name, "con:");
    curproc->t_file_table[1] = fh2;

    struct file_handle* fh3 = file_handle_create();
    fh3->file = v3;
    fh3->openflags = O_WRONLY;
    fh3->ref_count = 1;
    strcpy(fh3->file_name, "con:");
    curproc->t_file_table[2] = fh3;

    /* Warp to user mode. */
    //kprintf("[run program] releasing semaphore \n");
    enter_new_process(0 /*argc*/, 0 /*userspace addr of argv*/,
                      NULL /*userspace addr of environment*/,
                      stackptr, entrypoint);

    /* enter_new_process does not return. */
    panic("enter_new_process returned\n");
    return EINVAL;
}
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)
{
	struct addrspace *as;
	struct vnode *v;
	vaddr_t entrypoint, stackptr;
	int result;

  /** Initialize the file descriptors for console**/
	if (curthread->t_fdtable[0] == NULL) {
			result = init_file_descriptor();
			if (result ) { // file descriptors not initialized
				 kprintf_n("init_file_descriptor failed");
				 return result;
			}
	}
	/* Open the file. */
	result = vfs_open(progname, O_RDONLY, 0, &v);
	if (result) {
		return result;
	}

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

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

	/* Switch to it and activate it. */
	proc_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*/,
			  NULL /*userspace addr of environment*/,
			  stackptr, entrypoint);

	/* enter_new_process does not return. */
	panic("enter_new_process returned\n");
	return EINVAL;
}
int sys_read(int fd, userptr_t buf, int len, int* retval)
{
	// argument checks.

	if(fd <0 || fd>= OPEN_MAX)
		return EBADF;
	
	int result;
	char kern_buffer[len + 1];

	// are we using this properly?.. check jinghao's blog for example
	// no actual use for the kern buffer, just doing this to check if memory location is valid.

	if(buf!= NULL)
	{
		result = copyin(buf, kern_buffer, len); // using this because users are stupid/malicious and can pass invalid memory addresses to the kernel.
	
		if(result)
		{
			kprintf("read copy in bad \n");
			return result;

		}
	}

	struct file_handle* fh = get_file_handle(curproc->t_file_table, fd);
	
	if(fh == NULL)
		return EBADF;

	if(!can_read(fh->openflags)) // could have other flags Or'd with O_RDONLY, need to change this.
		return EBADF;
	

// !!!! Should we do copyin's to kernel space, or will the VOP_WRITE take care of the invalid address issue for us.

	lock_acquire(fh->fh_lock); // IS this really necessary??.. turns out it is , offset should be synchronized. imagine if parent and child call this at the same time.
	struct iovec iov;
	struct uio u;

	iov.iov_ubase = (userptr_t)buf;
	iov.iov_len = len;		 // length of the memory space
	u.uio_iov = &iov;
	u.uio_iovcnt = 1;
	u.uio_resid = len;          // amount to read from the file
	u.uio_offset = fh->offset;
	u.uio_segflg =  UIO_USERSPACE;
	u.uio_rw = UIO_READ;
	u.uio_space = proc_getas(); // lifted from loadelf.c, is this the right way to do it?

	result = VOP_READ(fh->file, &u);
	if (result) {
		lock_release(fh->fh_lock);
		return result;
	}

	if (u.uio_resid != 0) {
//		kprintf("ELF: short read on segment - file truncated?\n");
	}

	// should update offset in the file handle.use lock. uio_offset will be updated. can use it directly.
	fh->offset = u.uio_offset;

	lock_release(fh->fh_lock);

	*retval = len - u.uio_resid; // number of bytes gets returned to the user
	return 0; 


}
Example #11
0
int
sys_execv(char *progname, char **args, int *err) {

    struct addrspace *as;
    struct vnode *v;
    vaddr_t entrypoint, stackptr;
    int result;

    /* Validations */
    if (progname == NULL) {
        *err = EFAULT;
        return -1;
    }

    if (args == NULL || (int *)args == (int *)0x40000000 || (int *)args == (int *)0x80000000) {
        *err = EFAULT;
        return -1;
    }

    /* Count number of arguments and total size of input */
    int args_count = 0;
    for (;args_count < ARG_MAX && args[args_count] != NULL; args_count++);

    if (args_count > ARG_MAX) {
        *err = E2BIG;
        return -1;
    }

    /* Copy File name */
    char *progname_copy = (char *) kmalloc(sizeof(char) * NAME_MAX);
    size_t actual = 0;
    result = copyinstr((userptr_t)progname, progname_copy, NAME_MAX, &actual);

    if (result) {
        kfree(progname_copy);
        *err = result;
        return -1;
    }

    if (strlen(progname_copy) == 0) {
        kfree(progname_copy);
        *err = EINVAL;
        return -1;
    }

    /* Allocate Kernel Memory for arguments */
    char **args_copy = (char **) kmalloc(sizeof(char *) * args_count);

    int c_args_count = 0,
            arg_size = 0,
            padded_size = 0;

    for (;c_args_count < args_count; c_args_count++) {
        if ((int *)args[c_args_count] == (int *)0x40000000 || (int *)args[c_args_count] == (int *)0x80000000) {
            kfree(progname_copy);
            *err = EFAULT;
            return -1;
        }
    }

    c_args_count = 0;
    /* Calculate total length accounting for padding */
    for (;c_args_count < args_count; c_args_count++) {
        arg_size = strlen(args[c_args_count]) + 1;

        args_copy[c_args_count] = (char *) kmalloc(sizeof(char) * arg_size);
        copyinstr((userptr_t)args[c_args_count], args_copy[c_args_count], arg_size, &actual);

        padded_size += arg_size;
        if (padded_size % 4) {
            padded_size += (4 - (padded_size % 4)) % 4;
        }
    }

    /* Open the file. */
    result = vfs_open(progname_copy, O_RDONLY, 0, &v);
    if (result) {
        kfree(progname_copy);
        *err = result;
        return -1;
    }

    /* Destroy the current process's address space to create a new one. */
    as = curproc->p_addrspace;
    curproc->p_addrspace = NULL;

    as_destroy(as);

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

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

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

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

    /* 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 */
        kfree(progname_copy);
        *err = result;
        return -1;
    }

    stackptr -= padded_size;
    char **arg_address = (char **) kmalloc(sizeof(char *) * args_count + 1);

    /* Copy arguments into user stack */
    for(int i = 0; i < args_count; i++) {
        arg_size = strlen(args_copy[i]) + 1;

        if (arg_size % 4) {
            arg_size += (4 - arg_size % 4) % 4;
        }

        /* Store address of arguments */
        arg_address[i] = (char *)stackptr;

        copyoutstr(args_copy[i], (userptr_t)stackptr, arg_size, &actual);
        stackptr += arg_size;
    }

    /* Add Null Pointer at the end */
    arg_address[args_count] = 0;

    stackptr -= padded_size;
    stackptr -= (args_count + 1) * sizeof(char *);

    /* Copy address locations into user stack*/
    for (int i = 0; i < args_count + 1; i++) {
        copyout((arg_address + i), (userptr_t)stackptr, sizeof(char *));
        stackptr += sizeof(char *);
    }

    /* Reset pointer to start of the stack */
    stackptr -= ((args_count + 1) * sizeof(char *));

    kfree(progname_copy);

    c_args_count = 0;
    for (;c_args_count < args_count; c_args_count++) {
        kfree(args_copy[c_args_count]);
    }

    kfree(args_copy);
    kfree(arg_address);

    /* Warp to user mode. */
    enter_new_process(args_count /*argc*/, (userptr_t) stackptr /*userspace addr of argv*/,
                      (userptr_t) stackptr /*userspace addr of environment*/, stackptr, entrypoint);

    /* enter_new_process does not return. */
    panic("enter_new_process returned\n");

    *err = EINVAL;
    return -1;
}
int sys_execv(userptr_t progname, userptr_t *arguments) {
    struct proc *proc = curproc;
    struct addrspace *as;
    struct vnode *v;
    vaddr_t entrypoint, stackptr;
    int result;

    //kprintf("****EXECV]***** process-%d trying to exec", proc->pid);

    //lock_acquire(execlock);
    //kprintf("****EXECV]***** process-%d acquired exec lock", proc->pid);
	if(progname == NULL || progname == (void *)0x80000000 || progname == (void *)0x40000000) {
		return EFAULT;
	}

    if(arguments == NULL || arguments == (void *)0x80000000 || arguments == (void *)0x40000000) {
        return EFAULT;
    }
    /* This process should have an address space copied during fork */
    KASSERT(proc != NULL);
    char *_progname;
    size_t size;
    int i=0, count=0;
    _progname = (char *) kmalloc(sizeof(char)*PATH_MAX);
    result = copyinstr(progname, _progname, PATH_MAX, &size);
    if(result) {
        kfree(_progname);
        return EFAULT;
    }
    if(strlen(_progname) == 0) {
        kfree(_progname);
        return EINVAL;
    }
	if(swapping_started == true) {
    }
    kfree(_progname);

    char *args = (char *) kmalloc(sizeof(char)*ARG_MAX);
    result = copyinstr((const_userptr_t)arguments, args, ARG_MAX, &size);
    if(result) {
        kfree(args);
        return EFAULT;
    }
    /* Copy the user arguments on to the kernel */
   
    int offset = 0;
    while((char *) arguments[count] != NULL) {
        result = copyinstr((const_userptr_t) arguments[count], args+offset, ARG_MAX, &size);
        if(result) {
            kfree(args);
            return EFAULT;
        }
        offset += size;
        count++;
    }

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

    /* Destroy the current address space and Create a new address space */
    as_destroy(proc->p_addrspace);
    proc->p_addrspace = NULL;
    
    KASSERT(proc_getas() == NULL);

    as = as_create();
    if(as == NULL) {
        kfree(args);
        vfs_close(v);
        return ENOMEM;
    }
    /* Switch to it and activate it */
    proc_setas(as);
    as_activate();

    /* Load the executable. */

  //  kprintf("free pages available before load_elf : %d \n", coremap_free_bytes()/4096);
    result = load_elf(v, &entrypoint);
    if(result) {
        kfree(args);
        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) {
        kfree(args);
        return result;
    }

    i = 0;
    int prevlen = 0, cur = 0;
    char **stkargs=(char**) kmalloc(sizeof(char*)*(count+1));
    while(i < offset) {
        int len=0, olen;
        for(len=0; args[i] != '\0'; len++, i++);
        olen = len;
        len = len + (4 - len%4);

        char *arg = kmalloc(len);
        //arg = kstrdup(args+prevlen);

        //kprintf("%s\n", arg);
        int j = prevlen;
        for(int k=0; k<len; k++) {
            if(k >= olen)
                arg[k] = '\0';
            else
                arg[k] = args[j++];
        }

        //kprintf("%s\n", arg);
        stackptr -= len;
        result = copyout((const void *)arg, (userptr_t)stackptr, (size_t)len);
        if(result) {
            kfree(args);
            kfree(stkargs);
            return result;
        }
        kfree(arg);
        stkargs[cur++] = (char *)stackptr;
        prevlen += olen + 1;
        i++;
    }
    stkargs[cur] = NULL;
    kfree(args);

    for(i=(cur) ; i>=0; i--) {
        stackptr = stackptr - sizeof(char *);
        //kprintf("copying arg %d at [%p]\n", i, *(stkargs+i));
        result = copyout((const void *)(stkargs+i), (userptr_t) stackptr, (sizeof(char *)));
        if(result) {
            kfree(stkargs);
            return result;
        }
        prevlen += 4;
    }
    kfree(stkargs);
    
    //unsigned int free = coremap_free_bytes();
  //  unsigned int free_pages = free/4096;

  //  kprintf("free pages available : %d \n", free_pages);

    //lock_release(execlock);
    //kprintf("****EXECV]***** process-%d released exec lock", proc->pid);
    enter_new_process(count, (userptr_t) stackptr, NULL, stackptr, entrypoint);

    panic("enter_new_process returned\n");
    return EINVAL;
}
Example #13
0
File: vm.c Project: gapry/AOS
void
sos_VMFaultHandler(seL4_CPtr reply_cap, seL4_Word fault_addr, seL4_Word fsr, bool is_code){
    dprintf(3, "sos vmfault handler \n");

    int err;

    dprintf(3, "sos vmfault handler, getting as \n");
    addrspace_t *as = proc_getas();
    dprintf(3, "sos vmfault handler, gotten as \n");
    if (as == NULL) {
        dprintf(3, "app as is NULL\n");
        /* Kernel is probably failed when bootstraping */
        set_cur_proc(PROC_NULL);
        cspace_free_slot(cur_cspace, reply_cap);
        return;
    }

    region_t *reg;

    /* Is this a segfault? */
    if (_check_segfault(as, fault_addr, fsr, &reg)) {
        dprintf(3, "vmf: segfault\n");
        proc_destroy(proc_get_id());
        set_cur_proc(PROC_NULL);
        cspace_free_slot(cur_cspace, reply_cap);
        return;
    }

    /*
     * If it comes here, this must be a valid address Therefore, this page is
     * either swapped out has never been mapped in
     */

    VMF_cont_t *cont = malloc(sizeof(VMF_cont_t));
    if (cont == NULL) {
        dprintf(3, "vmfault out of mem\n");
        /* We cannot handle the fault but the process still can run
         * There will be more faults coming though */
        set_cur_proc(PROC_NULL);
        seL4_MessageInfo_t reply = seL4_MessageInfo_new(0, 0, 0, 0);
        seL4_Send(reply_cap, reply);
        cspace_free_slot(cur_cspace, reply_cap);
        return;
    }

    cont->reply_cap = reply_cap;
    cont->as        = as;
    cont->vaddr     = fault_addr;
    cont->is_code   = is_code;
    cont->reg       = reg;
    cont->pid       = proc_get_id();

    /* Check if this page is an new, unmaped page or is it just swapped out */
    if (sos_page_is_inuse(as, fault_addr)) {
        if (sos_page_is_swapped(as, fault_addr)) {
            dprintf(3, "vmf tries to swapin\n");
            /* This page is swapped out, we need to swap it back in */
            err = swap_in(cont->as, cont->reg->rights, cont->vaddr,
                      cont->is_code, _sos_VMFaultHandler_reply, cont);
            if (err) {
                _sos_VMFaultHandler_reply((void*)cont, err);
                return;
            }
            return;
        } else {
            if (sos_page_is_locked(as, fault_addr)) {
                dprintf(3, "vmf page is locked\n");
                _sos_VMFaultHandler_reply((void*)cont, EFAULT);
                return;
            }

            dprintf(3, "vmf second chance mapping page back in\n");
            err = _set_page_reference(cont->as, cont->vaddr, cont->reg->rights);
            _sos_VMFaultHandler_reply((void*)cont, err);
            return;
        }
    } else {
        /* This page has never been mapped, so do that and return */
        dprintf(3, "vmf tries to map a page\n");
        inc_proc_size_proc(cur_proc());
        err = sos_page_map(proc_get_id(), as, fault_addr, reg->rights, _sos_VMFaultHandler_reply, (void*)cont, false);
        if(err){
            dec_proc_size_proc(cur_proc());
            _sos_VMFaultHandler_reply((void*)cont, err);
        }
        return;
    }
    /* Otherwise, this is not handled */
    dprintf(3, "vmf error at the end\n");
    _sos_VMFaultHandler_reply((void*)cont, EFAULT);
    return;
}