summaryrefslogtreecommitdiff
path: root/exec.c
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2019-05-31 12:43:20 -0400
committerRobert Morris <[email protected]>2019-05-31 12:43:20 -0400
commit7fd1f1eb0aab4d52852fc4f5e83eafc991f9a627 (patch)
tree321ae7c509d2b6286240ad181bc28a9dc3436704 /exec.c
parent5d34fa2a489940f19ee6c4728e4b11b6d8ffad01 (diff)
downloadxv6-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.c74
1 files changed, 50 insertions, 24 deletions
diff --git a/exec.c b/exec.c
index 6d0ef24..a9776bc 100644
--- a/exec.c
+++ b/exec.c
@@ -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;
+}