diff options
author | Frans Kaashoek <[email protected]> | 2010-07-02 14:51:53 -0400 |
---|---|---|
committer | Frans Kaashoek <[email protected]> | 2010-07-02 14:51:53 -0400 |
commit | 40889627ba50db29a64bc6a1553c2b21e6a99b78 (patch) | |
tree | 7cb8f51492af706cafdcaf1b01a5cac8073d5a38 /exec.c | |
parent | b7a517f2277670e156f150ee2cb7aae6426c6aef (diff) | |
download | xv6-labs-40889627ba50db29a64bc6a1553c2b21e6a99b78.tar.gz xv6-labs-40889627ba50db29a64bc6a1553c2b21e6a99b78.tar.bz2 xv6-labs-40889627ba50db29a64bc6a1553c2b21e6a99b78.zip |
Initial version of single-cpu xv6 with page tables
Diffstat (limited to 'exec.c')
-rw-r--r-- | exec.c | 90 |
1 files changed, 40 insertions, 50 deletions
@@ -11,12 +11,13 @@ exec(char *path, char **argv) { char *mem, *s, *last; int i, argc, arglen, len, off; - uint sz, sp, argp; + uint sz, sp, spoffset, argp; struct elfhdr elf; struct inode *ip; struct proghdr ph; + pde_t *pgdir, *oldpgdir; - mem = 0; + pgdir = 0; sz = 0; if((ip = namei(path)) == 0) @@ -29,37 +30,8 @@ exec(char *path, char **argv) if(elf.magic != ELF_MAGIC) goto bad; - // Compute memory size of new process. - // Program segments. - 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; - sz += ph.memsz; - } - - // Arguments. - arglen = 0; - for(argc=0; argv[argc]; argc++) - arglen += strlen(argv[argc]) + 1; - arglen = (arglen+3) & ~3; - sz += arglen; - sz += 4*(argc+1); // argv data - sz += 4; // argv - sz += 4; // argc - - // Stack. - sz += PAGE; - - // Allocate program memory. - sz = (sz+PAGE-1) & ~(PAGE-1); - mem = kalloc(sz); - if(mem == 0) + if (!(pgdir = setupkvm())) goto bad; - memset(mem, 0, sz); // Load program into memory. for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ @@ -67,37 +39,48 @@ exec(char *path, char **argv) goto bad; if(ph.type != ELF_PROG_LOAD) continue; - if(ph.va + ph.memsz < ph.va || ph.va + ph.memsz > sz) - goto bad; if(ph.memsz < ph.filesz) goto bad; - if(readi(ip, mem + ph.va, ph.offset, ph.filesz) != ph.filesz) + if (!allocuvm(pgdir, (char *)ph.va, ph.memsz)) + goto bad; + sz += PGROUNDUP(ph.memsz); + if (!loaduvm(pgdir, (char *)ph.va, ip, ph.offset, ph.filesz)) goto bad; - memset(mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz); } iunlockput(ip); - - // Initialize stack. + + // Allocate and initialize stack at sz + if (!allocuvm(pgdir, (char *)sz, PGSIZE)) + goto bad; + mem = uva2ka(pgdir, (char *)sz); + spoffset = sz; + sz += PGSIZE; + + arglen = 0; + for(argc=0; argv[argc]; argc++) + arglen += strlen(argv[argc]) + 1; + arglen = (arglen+3) & ~3; + sp = sz; argp = sz - arglen - 4*(argc+1); // Copy argv strings and pointers to stack. - *(uint*)(mem+argp + 4*argc) = 0; // argv[argc] + *(uint*)(mem+argp-spoffset + 4*argc) = 0; // argv[argc] for(i=argc-1; i>=0; i--){ len = strlen(argv[i]) + 1; sp -= len; - memmove(mem+sp, argv[i], len); - *(uint*)(mem+argp + 4*i) = sp; // argv[i] + memmove(mem+sp-spoffset, argv[i], len); + *(uint*)(mem+argp-spoffset + 4*i) = sp; // argv[i] } // Stack frame for main(argc, argv), below arguments. sp = argp; sp -= 4; - *(uint*)(mem+sp) = argp; + *(uint*)(mem+sp-spoffset) = argp; sp -= 4; - *(uint*)(mem+sp) = argc; + *(uint*)(mem+sp-spoffset) = argc; sp -= 4; - *(uint*)(mem+sp) = 0xffffffff; // fake return pc + *(uint*)(mem+sp-spoffset) = 0xffffffff; // fake return pc // Save program name for debugging. for(last=s=path; *s; s++) @@ -105,18 +88,25 @@ exec(char *path, char **argv) last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); - // Commit to the new image. - kfree(proc->mem, proc->sz); - proc->mem = mem; + // Commit to the user image. + oldpgdir = proc->pgdir; + proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; - usegment(); + + // printstack(); + + loadvm(proc); + + freevm(oldpgdir); + + // printstack(); + return 0; bad: - if(mem) - kfree(mem, sz); + freevm(pgdir); iunlockput(ip); return -1; } |