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); }
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. */ }
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; }
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; }
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; }
/* * 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; }
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; }
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, ®)) { 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; }