diff options
author | Robert Morris <[email protected]> | 2019-05-31 12:43:20 -0400 |
---|---|---|
committer | Robert Morris <[email protected]> | 2019-05-31 12:43:20 -0400 |
commit | 7fd1f1eb0aab4d52852fc4f5e83eafc991f9a627 (patch) | |
tree | 321ae7c509d2b6286240ad181bc28a9dc3436704 /exec.c | |
parent | 5d34fa2a489940f19ee6c4728e4b11b6d8ffad01 (diff) | |
download | xv6-labs-7fd1f1eb0aab4d52852fc4f5e83eafc991f9a627.tar.gz xv6-labs-7fd1f1eb0aab4d52852fc4f5e83eafc991f9a627.tar.bz2 xv6-labs-7fd1f1eb0aab4d52852fc4f5e83eafc991f9a627.zip |
exec compiles but argstr() doesn't work yet
Diffstat (limited to 'exec.c')
-rw-r--r-- | exec.c | 74 |
1 files changed, 50 insertions, 24 deletions
@@ -1,14 +1,13 @@ #include "types.h" #include "param.h" #include "memlayout.h" -#include "mmu.h" +#include "riscv.h" #include "proc.h" #include "defs.h" -#include "traps.h" -#include "msr.h" -#include "x86.h" #include "elf.h" +static int loadseg(pde_t *pgdir, uint64 addr, struct inode *ip, uint offset, uint sz); + int exec(char *path, char **argv) { @@ -18,9 +17,11 @@ exec(char *path, char **argv) struct elfhdr elf; struct inode *ip; struct proghdr ph; - pde_t *pgdir, *oldpgdir; + pagetable_t pagetable = 0, oldpagetable; struct proc *p = myproc(); uint64 oldsz = p->sz; + + printf("EXEC\n"); begin_op(); @@ -29,7 +30,6 @@ exec(char *path, char **argv) return -1; } ilock(ip); - pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) != sizeof(elf)) @@ -37,7 +37,7 @@ exec(char *path, char **argv) if(elf.magic != ELF_MAGIC) goto bad; - if((pgdir = setupkvm()) == 0) + if((pagetable = proc_pagetable(p)) == 0) goto bad; // Load program into memory. @@ -51,11 +51,11 @@ exec(char *path, char **argv) goto bad; if(ph.vaddr + ph.memsz < ph.vaddr) goto bad; - if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) + if((sz = uvmalloc(pagetable, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(ph.vaddr % PGSIZE != 0) goto bad; - if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) + if(loadseg(pagetable, ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); @@ -63,11 +63,10 @@ exec(char *path, char **argv) ip = 0; // Allocate two pages at the next page boundary. - // Make the first inaccessible. Use the second as the user stack. + // Use the second as the user stack. sz = PGROUNDUP(sz); - if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) + if((sz = uvmalloc(pagetable, sz, sz + 2*PGSIZE)) == 0) goto bad; - clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. @@ -75,7 +74,7 @@ exec(char *path, char **argv) if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~(sizeof(uint64)-1); - if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) + if(copyout(pagetable, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } @@ -85,11 +84,12 @@ exec(char *path, char **argv) ustack[1] = argc; ustack[2] = sp - (argc+1)*sizeof(uint64); // argv pointer - p->sf->rdi = argc; - p->sf->rsi = sp - (argc+1)*sizeof(uint64); + // arguments to user main(argc, argv) + p->tf->a0 = argc; + p->tf->a1 = sp - (argc+1)*sizeof(uint64); sp -= (3+argc+1) * sizeof(uint64); - if(copyout(pgdir, sp, ustack, (3+argc+1)*sizeof(uint64)) < 0) + if(copyout(pagetable, sp, (char *)ustack, (3+argc+1)*sizeof(uint64)) < 0) goto bad; // Save program name for debugging. @@ -99,21 +99,47 @@ exec(char *path, char **argv) safestrcpy(p->name, last, sizeof(p->name)); // Commit to the user image. - oldpgdir = p->pgdir; - p->pgdir = pgdir; + oldpagetable = p->pagetable; + p->pagetable = pagetable; p->sz = sz; - p->sf->rcx = elf.entry; // main - p->sf->rsp = sp; - switchuvm(p); - freevm(oldpgdir, oldsz); + p->tf->epc = elf.entry; // initial program counter = main + p->tf->sp = sp; // initial stack pointer + proc_freepagetable(oldpagetable, oldsz); return 0; bad: - if(pgdir) - freevm(pgdir, sz); + if(pagetable) + proc_freepagetable(pagetable, sz); if(ip){ iunlockput(ip); end_op(); } return -1; } + +// Load a program segment into pagetable at virtual address va. +// va must be page-aligned +// and the pages from va to va+sz must already be mapped. +// Returns 0 on success, -1 on failure. +static int +loadseg(pagetable_t pagetable, uint64 va, struct inode *ip, uint offset, uint sz) +{ + uint i, n; + uint64 pa; + pte_t *pte; + + if((va % PGSIZE) != 0) + panic("loadseg: va must be page aligned"); + for(i = 0; i < sz; i += PGSIZE){ + pa = walkaddr(pagetable, va + i); + if(pa == 0) + panic("loadseg: address should exist"); + if(sz - i < PGSIZE) + n = sz - i; + else + n = PGSIZE; + if(readi(ip, (char *)pa, offset+i, n) != n) + return -1; + } + return 0; +} |