//PAGEBREAK: 32 // Set up first user process. void userinit(void) { struct proc *p; extern char _binary_initcode_start[], _binary_initcode_size[]; p = allocproc(); initproc = p; if((p->pgdir = setupkvm()) == 0) panic("userinit: out of memory?"); inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); p->sz = PGSIZE; memset(p->tf, 0, sizeof(*p->tf)); p->tf->cs = (SEG_UCODE << 3) | DPL_USER; p->tf->ds = (SEG_UDATA << 3) | DPL_USER; p->tf->es = p->tf->ds; p->tf->ss = p->tf->ds; p->tf->eflags = FL_IF; p->tf->esp = PGSIZE; p->tf->eip = 0; // beginning of initcode.S safestrcpy(p->name, "initcode", sizeof(p->name)); p->cwd = namei("/"); // this assignment to p->state lets other cores // run this process. the acquire forces the above // writes to be visible, and the lock is also needed // because the assignment might not be atomic. acquire(&ptable.lock); p->state = RUNNABLE; release(&ptable.lock); }
// Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz) { pde_t *d = setupkvm(); pte_t *pte; uint pa, i; char *mem; if(!d) return 0; for(i = 0; i < sz; i += PGSIZE){ if(!(pte = walkpgdir(pgdir, (void *)i, 0))) panic("copyuvm: pte should exist\n"); if(!(*pte & PTE_P)) panic("copyuvm: page not present\n"); pa = PTE_ADDR(*pte); if(!(mem = kalloc())) goto bad; memmove(mem, (char *)pa, PGSIZE); if(!mappages(d, (void *)i, PGSIZE, PADDR(mem), PTE_W|PTE_U)) goto bad; } return d; bad: freevm(d); return 0; }
// Set up first user process. void userinit(void) { struct proc *p; extern char _binary_initcode_start[], _binary_initcode_size[]; p = allocproc(); acquire(&ptable.lock); initproc = p; if((p->pgdir = setupkvm()) == 0) panic("userinit: out of memory?"); inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); p->sz = PGSIZE; memset(p->tf, 0, sizeof(*p->tf)); p->tf->cs = (SEG_UCODE << 3) | DPL_USER; p->tf->ds = (SEG_UDATA << 3) | DPL_USER; p->tf->es = p->tf->ds; p->tf->ss = p->tf->ds; p->tf->eflags = FL_IF; p->tf->esp = PGSIZE; p->tf->eip = 0; // beginning of initcode.S safestrcpy(p->name, "initcode", sizeof(p->name)); p->cwd = namei("/"); p->state = RUNNABLE; release(&ptable.lock); }
// Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz) { pde_t *d; pte_t *pte; uint pa, i, flags; char *mem; if((d = setupkvm()) == 0) return 0; for(i = 0; i < sz; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void *) i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); flags = PTE_FLAGS(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)p2v(pa), PGSIZE); if(mappages(d, (void*)i, PGSIZE, v2p(mem), flags) < 0) goto bad; } return d; bad: freevm(d); return 0; }
//PAGEBREAK: 32 // Set up first user process. void userinit(void) { struct proc *p; extern char _binary_initcode_start[], _binary_initcode_size[]; p = allocproc(); initproc = p; if ((p->pgdir = setupkvm()) == 0) panic("userinit: out of memory?"); inituvm(p->pgdir, _binary_initcode_start, (int) _binary_initcode_size); p->sz = PGSIZE; memset(p->tf, 0, sizeof(*p->tf)); p->tf->cs = (SEG_UCODE << 3) | DPL_USER; p->tf->ds = (SEG_UDATA << 3) | DPL_USER; p->tf->es = p->tf->ds; p->tf->ss = p->tf->ds; p->tf->eflags = FL_IF; p->tf->esp = PGSIZE; p->tf->eip = 0; // beginning of initcode.S safestrcpy(p->name, "initcode", sizeof(p->name)); p->cwd = namei("/"); p->parent=0; setpriority(p,0); SetProcessRunnable(p); }
// Allocate one page table for the machine for the kernel address // space for scheduler processes. void kvmalloc(void) { kpgdir = setupkvm(); if(kpgdir == 0) panic("kvmalloc: could not create kernel page table"); switchkvm(); }
void kvmalloc(void) { if ((kpgmap = setupkvm()) == nil) panic("kvmalloc"); switchkvm(); }
// Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz) { pde_t *d; pte_t *pte; uint pa, i; char *mem; if((d = setupkvm()) == 0) return 0; //<(- //CHANGED i = 0, < sz for(i = PGSIZE; i < sz; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 1)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)){ panic("copyuvm: page not present"); } else{ pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } } cprintf("Last addr copied from code: %x\n", i-PGSIZE); //copy stack for(i = USERTOP-proc->stacksz; i < USERTOP; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 1)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)){ panic("copyuvm: page not present"); } else{ pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } } cprintf("Last addr copied from code: %x\n", i-PGSIZE); return d; bad: freevm(d); return 0; }
// TODO(byan23): Copy the stack at the end of addr space. // Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz) { pde_t *d; pte_t *pte; uint pa, i; char *mem; if((d = setupkvm()) == 0) return 0; // Copy code + heap. if (proc->pid == 1) i = 0; else i = PGSIZE; for(; i < sz; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } //cprintf("before coping stack from pid %d.\n", proc->pid); // TODO(byan23): Copy more stack as it grows. // Copy stack. i = USERTOP - proc->ssz; //i = USERTOP - PGSIZE; if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; return d; bad: freevm(d); return 0; }
// Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz) { pde_t *d; pte_t *pte; uint pa, i; char *mem; if((d = setupkvm()) == 0) return 0; // cs537 for(i = PGSIZE; i < sz; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } // cs537 /* copy stack region */ for(i = proc->sb; i < USERTOP ; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } return d; bad: freevm(d); return 0; }
// Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz, uint s_sz) { pde_t *d; pte_t *pte; uint pa, i, stack_size; char *mem; if((d = setupkvm()) == 0) return 0; // Start at PGSIZE to make the first page invalid for(i = PGSIZE; i < sz; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } // We need to loop again to copy the stack over stack_size = s_sz; for(i = stack_size; i < USERTOP; i+= PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } return d; bad: freevm(d); return 0; }
//PAGEBREAK: 32 // Set up first user process. void userinit(void) { struct proc *p; extern char _binary_initcode_start[], _binary_initcode_size[]; #ifdef USE_CS333_SCHEDULER // Initialize free list acquire(&ptable.lock); int i; for (i=0; i<NPROC; i++) addToFreeList(&ptable.proc[i]); release(&ptable.lock); #endif p = allocproc(); initproc = p; if((p->pgdir = setupkvm()) == 0) panic("userinit: out of memory?"); inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); p->sz = PGSIZE; memset(p->tf, 0, sizeof(*p->tf)); p->tf->cs = (SEG_UCODE << 3) | DPL_USER; p->tf->ds = (SEG_UDATA << 3) | DPL_USER; p->tf->es = p->tf->ds; p->tf->ss = p->tf->ds; p->tf->eflags = FL_IF; p->tf->esp = PGSIZE; p->tf->eip = 0; // beginning of initcode.S safestrcpy(p->name, "initcode", sizeof(p->name)); p->cwd = namei("/"); p->uid = DEF_UID; p->gid = DEF_GID; #ifdef USE_CS333_SCHEDULER // Initialize ready list with init process acquire(&ptable.lock); p->state = RUNNABLE; if (!setPri(p, DEF_PRI)) cprintf("ERROR: DEF_PRI invalid. Must be between 0 and %d. Current value: %d.\n", N_PRI, DEF_PRI); addToPriQ(p, p->pri); release(&ptable.lock); #else p->state = RUNNABLE; #endif }
//PAGEBREAK: 32 // Set up first user process. void userinit(void) { struct proc *p; extern char _binary_initcode_start[], _binary_initcode_size[]; #ifdef CS333_SCHEDULER acquire(&ptable.lock); initFreeList(); ptable.timeToReset = COUNT; release(&ptable.lock); #endif p = allocproc(); initproc = p; if((p->pgdir = setupkvm()) == 0) panic("userinit: out of memory?"); inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); p->sz = PGSIZE; memset(p->tf, 0, sizeof(*p->tf)); p->tf->cs = (SEG_UCODE << 3) | DPL_USER; p->tf->ds = (SEG_UDATA << 3) | DPL_USER; p->tf->es = p->tf->ds; p->tf->ss = p->tf->ds; p->tf->eflags = FL_IF; p->tf->esp = PGSIZE; p->tf->eip = 0; // beginning of initcode.S p->uid = USERID; p->gid = GROUPID; safestrcpy(p->name, "initcode", sizeof(p->name)); p->cwd = namei("/"); p->state = RUNNABLE; #ifdef CS333_SCHEDULER acquire(&ptable.lock); int i; for (i = 0; i < 3; ++i) { ptable.readyList[i] = 0; } putOnReadyList(p, p->priority); release(&ptable.lock); #endif }
// Given a parent process's page table, create a copy // of it for a child. pde_t* copyuvm(pde_t *pgdir, uint sz, uint stack_addr) { pde_t *d; pte_t *pte; uint pa, i; char *mem; if((d = setupkvm()) == 0) return 0; for(i = PGSIZE; i < sz; i += PGSIZE){ if((pte = walkpgdir(pgdir, (void*)i, 0)) == 0) panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); pa = PTE_ADDR(*pte); if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); if(mappages(d, (void*)i, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0) goto bad; } // Copy the last page which is the new stack if((pte = walkpgdir(pgdir, (void*)(USERTOP-PGSIZE), 1)) == 0)//undestand what pgdir does panic("copyuvm: pte should exist"); if(!(*pte & PTE_P)) panic("copyuvm: page not present"); //cprintf(" last page is %d\n",pte); pa = PTE_ADDR(*pte);// what pa are they getting from pte if((mem = kalloc()) == 0) goto bad; memmove(mem, (char*)pa, PGSIZE); // copying some stuff.. figure out what 1 page is and copying it if(mappages(d, (void*)USERTOP-PGSIZE, PGSIZE, PADDR(mem), PTE_W|PTE_U) < 0)//mapping into new address space and making it valid goto bad; return d; bad: freevm(d); return 0; }
Pml4e * copyuvm(Pml4e *oldmap, usize sz) { uintptr a; Pml4e *newmap; Pte *pte; uchar *oldmem, *newmem; uint flags; newmap = setupkvm(); if (newmap == nil) return nil; for (a = 0; a < sz; a += PGSIZE) { pte = walkpgmap(oldmap, (void *)a, 0); if (pte == nil) panic("copyuvm - nil pte"); if (!*pte & PTE_P) panic("copyuvm - page not present"); oldmem = p2v(pte_addr(*pte)); flags = pte_flags(*pte); newmem = kalloc(); if (newmem == nil) goto bad; memmove(newmem, oldmem, PGSIZE); if (mappages(newmap, (void *)a, PGSIZE, v2p(newmem), flags) < 0) goto bad; } return newmap; bad: freeuvm(newmap); return nil; }
//PAGEBREAK: 32 // Set up first user process. void userinit(void) { struct proc *p; extern char _binary_initcode_start[], _binary_initcode_size[]; p = allocproc(); initproc = p; if((p->pgdir = setupkvm()) == 0) panic("userinit: out of memory?"); inituvm(p->pgdir, p->asid, _binary_initcode_start, (int)_binary_initcode_size); p->sz = PGSIZE; memset(p->tf, 0, sizeof(*p->tf)); p->tf->sp = PGSIZE; p->tf->status = (read_cop0_status() | STATUS_KSU_USER | STATUS_EXL | STATUS_IE) & ~STATUS_ERL; p->tf->epc = (uint)0; // beginning of initcode.S safestrcpy(p->name, "initcode", sizeof(p->name)); p->cwd = namei("/"); p->state = RUNNABLE; }
void userinit(void) { struct proc *p; extern char _binary_kernel_initcode_start[], _binary_kernel_initcode_size[]; char *mem; p = allocproc(); assert(p); initproc = p; if((p->pgdir = setupkvm(kalloc)) == NULL) panic("userinit: out of memory?"); if ((int)_binary_kernel_initcode_size > PGSIZE) panic("inituvm: initcode more than a page"); mem = kalloc(); memset(mem, 0, PGSIZE); mappages(p->pgdir, 0, PGSIZE, V2P(mem), PTE_W|PTE_U, kalloc); memcpy(mem, (char *)_binary_kernel_initcode_start, (int)_binary_kernel_initcode_size); safestrcpy(p->name, "initcode", sizeof(p->name)); p->brk = PGSIZE; memset(p->tf, 1, sizeof(*p->tf)); p->tf->cs = (SEG_UCODE << 3) | DPL_USER; p->tf->ss = (SEG_UDATA << 3) | DPL_USER; p->tf->ds = p->tf->es = p->tf->fs = p->tf->gs = p->tf->ss; p->tf->eflags = FL_IF; p->tf->esp = PGSIZE; p->tf->eip = 0; // beginning of initcode p->counter = p->priority = 10; p->state = RUNNABLE; }
static int load_proc(char *path, struct proc *p) { int i; struct proc np; //an inode describes a single unnamed file struct inode *ip; begin_op(); if ((ip = namei(path)) == 0) { end_op(); return -1; } ilock(ip); if((np.pgdir = setupkvm()) == 0) return -1; if((np.sz = allocuvm(np.pgdir, 0, p->sz)) == 0) return -1; for(i = 0; i < p->sz; i+=PGSIZE) { if(loaduvm(np.pgdir, (void *)i, ip, sizeof(struct proc) + i,PGSIZE) < 0) return -1; } iunlockput(ip); end_op(); ip = 0; np.tf->eax = proc->pid; np.tf->eip = p->tf->eip; np.tf->esp = p->tf->esp; np.tf->ebp = p->tf->ebp; proc->pgdir = np.pgdir; proc->sz = PGROUNDUP(np.sz); *proc->tf = *np.tf; switchuvm(proc); return 0; }
void swapIn(struct proc* p){ // cprintf("swapIN\n"); //create flie char id_as_str[3]; // need to pre determine number of digits in p->pid itoa(p->pid,id_as_str); char path[strlen(id_as_str) + 5]; path[6] = '\0'; // path[0] = '/'; strcat(path,0,id_as_str,".swap"); //cprintf("swapIn - passed strcat path: %s\n",path); release(&ptable.lock); int test; p->swapped_file = kernel_open(path,O_RDONLY); // p->swapped_file = p->ofile[p->swapped_file_fd]; // cprintf("swapIn - passed open pid %d p->sz %d\n",p->pid,p->sz); p->pgdir = setupkvm(); test = allocuvm(p->pgdir,0,p->sz); //changed from KERNBASE // cprintf("swapIn - passed allocuvm pid %d returned %d\n",p->pid,test); // cprintf("swapFile ip: %d\n",p->swapped_file->ip->size); test = loaduvm(p->pgdir,0,p->swapped_file->ip,0,p->sz); // cprintf("swapIn - passed loaduvm pid %d returned %d\n",p->pid,test); test++; int fd; for(fd = 0; fd < NOFILE; fd++){ if(p->ofile[fd] && p->ofile[fd] == p->swapped_file){ fileclose(p->ofile[fd]); p->ofile[fd] = 0; break; } } p->swapped_file = 0; // cprintf("swapIn - passed fileclose pid %d\n",p->pid); test = kernel_unlink(path); //test++; // cprintf("swapIn - passed kernel_unlink pid %d returned %d\n",p->pid,test); acquire(&ptable.lock); }
void createInternalProcess(const char *name, void (*entrypoint)()){ struct proc *np; // Allocate process. if((np = allocproc()) == 0) cprintf("createInternalProcess error in allocproc\n"); // Copy process state from p. if((np->pgdir = setupkvm(kalloc)) == 0) cprintf("createInternalProcess error in setupkvm\n"); memset(np->tf, 0, sizeof(*np->tf)); np->tf->cs = (SEG_UCODE << 3) | 0; np->tf->ds = (SEG_UDATA << 3) | 0; np->tf->es = np->tf->ds; np->tf->ss = np->tf->ds; np->tf->eflags = FL_IF; np->sz = initproc->sz; np->parent = initproc; *np->tf = *initproc->tf; // Clear %eax so that fork returns 0 in the child. //np->tf->eax = 0; // Set starting point of inswapper //np->cwd = idup(initproc->cwd); np->cwd = namei("/"); np->context->eip = (uint)entrypoint; np->state = RUNNABLE; safestrcpy(np->name, name, (strlen(name) + 1)); }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; //// section check (either exist interp section) //// needed libsample.so.1 if (strcmp("share_main", path) == 0) { // share loader process (dummy of load ld-linux.so.2) //// mmap share library (libsample.so). sz = 0; /////// alloc physical memory cprintf("start %d \n", sz); ph.vaddr = 0x08048000; ph.memsz = 0x031a4 + 0x00130; sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz); cprintf("start4 %d \n", sz); /////// map pages to physical memory ph.off = 0x0; ph.filesz = 0x21a4 + 0x00124; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; cprintf("start3 %d \n", sz); iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = 0x80486d4; //.text proc->tf->esp = sp; cprintf("start2 %d \n", sz); switchuvm(proc); freevm(oldpgdir); return 0; //// rewrite bss valiable. //// stay loader program for delayed load. } // Load program into memory. sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz,s_sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. sz = PGSIZE; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate a one-page stack one page away from USERTOP (at bottom // grow upwards) s_sz = (USERTOP - PGSIZE); if((s_sz = allocuvm(pgdir, s_sz, s_sz + PGSIZE)) == 0) goto bad; // Push argument strings, prepare rest of stack in ustack. sp = s_sz; for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); s_sz = USERTOP - PGSIZE; // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->s_sz =s_sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); // cprintf("finish exec%d\t%d\n",sz,s_sz); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; // namei converts given path into inode begin_op(); if((ip = namei(path)) == 0){ end_op(); return -1; } ilock(ip); pgdir = 0; // Check ELF header // if the file is smaller than the size of an elf header, // then it doesn't hold an elf header. (ERROR) if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. // do this for each section of the elf file (chunk size dlineated // by sizeof program header) // allocate user virtual memory // load program into user virtual memory // in linux, run readelf -a /bin/ls and see the the offset and size // column program section header being loaded sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); end_op(); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); // This is macro function that jumps to the next page boundary if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; // this makes the inaccessible page clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. // This code is building the stack frame of the application. // since argc is not passed into this function, to find the max // num of args, we need to step through the argv string until the // item returned is NULL or the end of the string. // This means that we have found all of the arguments. // Next, we need to copy each argument into the stack and keep // references to it in a local stack. Once this is done, we can // set the stack pointer to point to the first argument on the stack. // now, we can put the return value and the total number of args onto our // local stack. Then, we must prepare local stack for the copy into the // real stack. Next, we adjust the real stack pointer to make // room for our local stack and then we copy our stack that contains // pointers to each argument onto the stack. // We need this for quick lookup of each argument -- without the poitners // we can't efficiently get the args back. we also need the // the total number of arguments to make sure that we are growing the // stack properly. // think about this: int main(int argc, char **argv); // this code defends why we need a double pointer to a char. // we are giving an array of char *. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; // explain of ~3 in following line: // to make memory align with 4 bits, we the two lower order bit // which are the oly two bits that aren't divisibile by 4. // this is to keep the compiler aligned with the system sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; // This is getting the real stack ready for the copy // of the local stack, ustack[] ustack[2] = sp - (argc+1)*4; // argv pointer // this is moving the stack pointer to the location of first argument. sp -= (3+argc+1) * 4; // This is copying the ustack[] into the real stack if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // done buildng the stack frame // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip){ iunlockput(ip); end_op(); } return -1; }
// Allocate one page table for the machine for the kernel address // space for scheduler processes. void kvmalloc(struct cpu *c) { c->kpgdir = setupkvm(); switchkvm(c); }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. // Skip first page sz = PGSIZE; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate a one-page stack at the next page boundary sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + PGSIZE)) == 0) goto bad; // Push argument strings, prepare rest of stack in ustack. sp = sz; for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; // Set end of shared pages address to USERTOP proc->endSP = USERTOP; proc->sz = sz; // For each shared page set the shared page count to the memory count for (i = 0; i < SHMEM_PAGES; i++) { proc->shared_count[i] = mem_count[i]; } proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; begin_op(); if((ip = namei(path)) == 0){ end_op(); return -1; } ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); end_op(); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip){ iunlockput(ip); end_op(); } return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm(kalloc)) == 0) goto bad; // Load program into memory. // leave first page inaccessible (to make NULL ref fail) sz = PGSIZE-1; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // hook up the old shared memory to the new addr space // (no need to change refcount, because the old ref goes away with // this exec, so it's +1 then -1 => 0 change if (proc->shared) { extern void mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm); mappages(pgdir, (char *)SHARED_V, PGSIZE, v2p(proc->shared->page), PTE_W|PTE_U); } // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; char tmp_path[MAX_LNK_NAME]; /* A&T */ /* A&T use readlink to de-reference symbolic links */ if (k_readlink(path, tmp_path, MAX_LNK_NAME) != -1) { if((ip = namei(tmp_path)) == 0) return -1; } else { if((ip = namei(path)) == 0) return -1; } ilock(ip); //A&T checks if symlink /* for (i=0;i < 16 ; i++) { //prevents loops ,up to 16 chain links */ /* if (ip->flags & I_SYMLNK) { */ /* if((sym_ip = namei((char*)ip->addrs)) == 0) { */ /* iunlock(ip); */ /* return -1; */ /* } */ /* iunlock(ip); */ /* ip = sym_ip; */ /* ilock(ip); */ /* } else */ /* break; */ /* } */ /* if (i == 16) { */ /* panic("symbolic link exceeds 16 links "); */ /* } */ //A&T - end pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm(kalloc)) == 0) goto bad; // Load program into memory. sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
// Allocate one page table for the machine for the kernel address // space for scheduler processes. void kvmalloc(void) { kpgdir = setupkvm(); }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sz_stk, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. sz = PGSIZE; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; sz = PGROUNDUP(sz); // CHANGE: Allocates the first page of the stack at the end of the user programs address space if((allocuvm(pgdir, USERTOP - PGSIZE, USERTOP)) == 0) goto bad; /* CHANGE: sets the sz_stk field equal to the top address of the stack */ sz_stk = USERTOP - PGSIZE; // Push argument strings, prepare rest of stack in ustack. sp = USERTOP; /* CHANGE: sets the stack pointer to the botom of the user space. */ for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->sz_stk = sz_stk; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }