annotate source/exec.c @ 0:ed10291ff195

first commit
author mir3636
date Sun, 06 Jan 2019 19:27:03 +0900
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
ed10291ff195 first commit
mir3636
parents:
diff changeset
1 #include "types.h"
ed10291ff195 first commit
mir3636
parents:
diff changeset
2 #include "param.h"
ed10291ff195 first commit
mir3636
parents:
diff changeset
3 #include "memlayout.h"
ed10291ff195 first commit
mir3636
parents:
diff changeset
4 #include "mmu.h"
ed10291ff195 first commit
mir3636
parents:
diff changeset
5 #include "proc.h"
ed10291ff195 first commit
mir3636
parents:
diff changeset
6 #include "defs.h"
ed10291ff195 first commit
mir3636
parents:
diff changeset
7 #include "arm.h"
ed10291ff195 first commit
mir3636
parents:
diff changeset
8 #include "elf.h"
ed10291ff195 first commit
mir3636
parents:
diff changeset
9
ed10291ff195 first commit
mir3636
parents:
diff changeset
10 int
ed10291ff195 first commit
mir3636
parents:
diff changeset
11 exec(char *path, char **argv)
ed10291ff195 first commit
mir3636
parents:
diff changeset
12 {
ed10291ff195 first commit
mir3636
parents:
diff changeset
13 char *last;
ed10291ff195 first commit
mir3636
parents:
diff changeset
14 int i, off;
ed10291ff195 first commit
mir3636
parents:
diff changeset
15 uint argc, sz, sp, ustack[3+MAXARG+1];
ed10291ff195 first commit
mir3636
parents:
diff changeset
16 struct elfhdr elf;
ed10291ff195 first commit
mir3636
parents:
diff changeset
17 struct inode *ip;
ed10291ff195 first commit
mir3636
parents:
diff changeset
18 struct proghdr ph;
ed10291ff195 first commit
mir3636
parents:
diff changeset
19 pde_t *pgdir, *oldpgdir;
ed10291ff195 first commit
mir3636
parents:
diff changeset
20
ed10291ff195 first commit
mir3636
parents:
diff changeset
21 if((ip = namei(path)) == 0)
ed10291ff195 first commit
mir3636
parents:
diff changeset
22 return -1;
ed10291ff195 first commit
mir3636
parents:
diff changeset
23 ilock(ip);
ed10291ff195 first commit
mir3636
parents:
diff changeset
24 pgdir = 0;
ed10291ff195 first commit
mir3636
parents:
diff changeset
25
ed10291ff195 first commit
mir3636
parents:
diff changeset
26 // Check ELF header
ed10291ff195 first commit
mir3636
parents:
diff changeset
27 if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
ed10291ff195 first commit
mir3636
parents:
diff changeset
28 goto bad;
ed10291ff195 first commit
mir3636
parents:
diff changeset
29 if(elf.magic != ELF_MAGIC)
ed10291ff195 first commit
mir3636
parents:
diff changeset
30 goto bad;
ed10291ff195 first commit
mir3636
parents:
diff changeset
31
ed10291ff195 first commit
mir3636
parents:
diff changeset
32 if((pgdir = setupkvm()) == 0)
ed10291ff195 first commit
mir3636
parents:
diff changeset
33 goto bad;
ed10291ff195 first commit
mir3636
parents:
diff changeset
34 // Load program into memory.
ed10291ff195 first commit
mir3636
parents:
diff changeset
35 sz = 0;
ed10291ff195 first commit
mir3636
parents:
diff changeset
36 for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
ed10291ff195 first commit
mir3636
parents:
diff changeset
37 if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
ed10291ff195 first commit
mir3636
parents:
diff changeset
38 goto bad;
ed10291ff195 first commit
mir3636
parents:
diff changeset
39 if(ph.type != ELF_PROG_LOAD)
ed10291ff195 first commit
mir3636
parents:
diff changeset
40 continue;
ed10291ff195 first commit
mir3636
parents:
diff changeset
41 if(ph.memsz < ph.filesz)
ed10291ff195 first commit
mir3636
parents:
diff changeset
42 goto bad;
ed10291ff195 first commit
mir3636
parents:
diff changeset
43 if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0)
ed10291ff195 first commit
mir3636
parents:
diff changeset
44 goto bad;
ed10291ff195 first commit
mir3636
parents:
diff changeset
45 if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0)
ed10291ff195 first commit
mir3636
parents:
diff changeset
46 goto bad;
ed10291ff195 first commit
mir3636
parents:
diff changeset
47 }
ed10291ff195 first commit
mir3636
parents:
diff changeset
48 iunlockput(ip);
ed10291ff195 first commit
mir3636
parents:
diff changeset
49 ip = 0;
ed10291ff195 first commit
mir3636
parents:
diff changeset
50
ed10291ff195 first commit
mir3636
parents:
diff changeset
51 // Allocate two pages at the next page boundary.
ed10291ff195 first commit
mir3636
parents:
diff changeset
52 // Make the first inaccessible. Use the second as the user stack.
ed10291ff195 first commit
mir3636
parents:
diff changeset
53 sz = PGROUNDUP(sz);
ed10291ff195 first commit
mir3636
parents:
diff changeset
54 if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0)
ed10291ff195 first commit
mir3636
parents:
diff changeset
55 goto bad;
ed10291ff195 first commit
mir3636
parents:
diff changeset
56 clearpteu(pgdir, (char*)(sz - 2*PGSIZE));
ed10291ff195 first commit
mir3636
parents:
diff changeset
57 sp = sz;
ed10291ff195 first commit
mir3636
parents:
diff changeset
58 // Push argument strings, prepare rest of stack in ustack.
ed10291ff195 first commit
mir3636
parents:
diff changeset
59 for(argc = 0; argv[argc]; argc++) {
ed10291ff195 first commit
mir3636
parents:
diff changeset
60 if(argc >= MAXARG)
ed10291ff195 first commit
mir3636
parents:
diff changeset
61 goto bad;
ed10291ff195 first commit
mir3636
parents:
diff changeset
62 sp = (sp - (strlen(argv[argc]) + 1)) & ~3;
ed10291ff195 first commit
mir3636
parents:
diff changeset
63 if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
ed10291ff195 first commit
mir3636
parents:
diff changeset
64 goto bad;
ed10291ff195 first commit
mir3636
parents:
diff changeset
65 ustack[3+argc] = sp;
ed10291ff195 first commit
mir3636
parents:
diff changeset
66 }
ed10291ff195 first commit
mir3636
parents:
diff changeset
67 ustack[3+argc] = 0;
ed10291ff195 first commit
mir3636
parents:
diff changeset
68
ed10291ff195 first commit
mir3636
parents:
diff changeset
69 //cprintf("Exec is called argc=%d sz=%x\n", argc, sz);
ed10291ff195 first commit
mir3636
parents:
diff changeset
70
ed10291ff195 first commit
mir3636
parents:
diff changeset
71 ustack[0] = 0xffffffff; // fake return PC
ed10291ff195 first commit
mir3636
parents:
diff changeset
72 ustack[1] = argc;
ed10291ff195 first commit
mir3636
parents:
diff changeset
73 ustack[2] = sp - (argc+1)*4; // argv pointer
ed10291ff195 first commit
mir3636
parents:
diff changeset
74
ed10291ff195 first commit
mir3636
parents:
diff changeset
75 sp -= (3+argc+1) * 4;
ed10291ff195 first commit
mir3636
parents:
diff changeset
76 if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0)
ed10291ff195 first commit
mir3636
parents:
diff changeset
77 goto bad;
ed10291ff195 first commit
mir3636
parents:
diff changeset
78
ed10291ff195 first commit
mir3636
parents:
diff changeset
79 // Save program name for debugging.
ed10291ff195 first commit
mir3636
parents:
diff changeset
80 /* for(last=s=path; *s; s++)
ed10291ff195 first commit
mir3636
parents:
diff changeset
81 if(*s == '/')
ed10291ff195 first commit
mir3636
parents:
diff changeset
82 last = s+1;*/
ed10291ff195 first commit
mir3636
parents:
diff changeset
83 last = argv[0];
ed10291ff195 first commit
mir3636
parents:
diff changeset
84 safestrcpy(curr_proc->name, last, sizeof(curr_proc->name));
ed10291ff195 first commit
mir3636
parents:
diff changeset
85
ed10291ff195 first commit
mir3636
parents:
diff changeset
86 // Commit to the user image.
ed10291ff195 first commit
mir3636
parents:
diff changeset
87 oldpgdir = curr_proc->pgdir;
ed10291ff195 first commit
mir3636
parents:
diff changeset
88 curr_proc->pgdir = pgdir;
ed10291ff195 first commit
mir3636
parents:
diff changeset
89 curr_proc->sz = sz;
ed10291ff195 first commit
mir3636
parents:
diff changeset
90 curr_proc->tf->pc = elf.entry; // main
ed10291ff195 first commit
mir3636
parents:
diff changeset
91 curr_proc->tf->sp = sp;
ed10291ff195 first commit
mir3636
parents:
diff changeset
92 curr_proc->tf->r0 = ustack[1];
ed10291ff195 first commit
mir3636
parents:
diff changeset
93 curr_proc->tf->r1 = ustack[2];
ed10291ff195 first commit
mir3636
parents:
diff changeset
94 switchuvm(curr_proc);
ed10291ff195 first commit
mir3636
parents:
diff changeset
95 freevm(oldpgdir);
ed10291ff195 first commit
mir3636
parents:
diff changeset
96 return 0;
ed10291ff195 first commit
mir3636
parents:
diff changeset
97
ed10291ff195 first commit
mir3636
parents:
diff changeset
98 bad:
ed10291ff195 first commit
mir3636
parents:
diff changeset
99 if(pgdir)
ed10291ff195 first commit
mir3636
parents:
diff changeset
100 freevm(pgdir);
ed10291ff195 first commit
mir3636
parents:
diff changeset
101 if(ip)
ed10291ff195 first commit
mir3636
parents:
diff changeset
102 iunlockput(ip);
ed10291ff195 first commit
mir3636
parents:
diff changeset
103 return -1;
ed10291ff195 first commit
mir3636
parents:
diff changeset
104 }