Skip to content

Commit 4088962

Browse files
author
Frans Kaashoek
committed
Initial version of single-cpu xv6 with page tables
1 parent b7a517f commit 4088962

22 files changed

+307
-152
lines changed

Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@ OBJS = \
2525
trap.o\
2626
uart.o\
2727
vectors.o\
28+
vm.o\
2829

2930
# Cross-compiling (e.g., on Mac OS X)
30-
#TOOLPREFIX = i386-jos-elf-
31+
TOOLPREFIX = i386-jos-elf-
3132

3233
# Using native tools (e.g., on X86 Linux)
33-
TOOLPREFIX =
34+
#TOOLPREFIX =
3435

3536
CC = $(TOOLPREFIX)gcc
3637
AS = $(TOOLPREFIX)gas

bootasm.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,5 @@ gdt:
8888
SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg
8989

9090
gdtdesc:
91-
.word (gdtdesc - gdt - 1) # sizeof(gdt) - 1
91+
.word (gdtdesc - gdt - 1) # sizeof(gdt) - 1
9292
.long gdt # address gdt

defs.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ extern uchar ioapicid;
6060
void ioapicinit(void);
6161

6262
// kalloc.c
63+
extern int nfreemem;
6364
char* kalloc(int);
6465
void kfree(char*, int);
65-
void kinit(void);
66+
void kinit(char*,uint);
6667

6768
// kbd.c
6869
void kbdintr(void);
@@ -101,8 +102,6 @@ int kill(int);
101102
void pinit(void);
102103
void procdump(void);
103104
void scheduler(void) __attribute__((noreturn));
104-
void ksegment(void);
105-
void usegment(void);
106105
void sleep(void*, struct spinlock*);
107106
void userinit(void);
108107
int wait(void);
@@ -111,6 +110,7 @@ void yield(void);
111110

112111
// swtch.S
113112
void swtch(struct context**, struct context*);
113+
void jstack(uint);
114114

115115
// spinlock.c
116116
void acquire(struct spinlock*);
@@ -152,6 +152,22 @@ void uartinit(void);
152152
void uartintr(void);
153153
void uartputc(int);
154154

155+
// vm.c
156+
#define PGROUNDUP(sz) ((sz+PGSIZE-1) & ~(PGSIZE-1))
157+
void pminit(void);
158+
void swkstack(void);
159+
void vminit(void);
160+
void printpgdir(uint*);
161+
uint* setupkvm(void); // XXX need pde_t*
162+
char* uva2ka(uint*, char*);
163+
int allocuvm(uint*, char*, uint); // XXX need pde_t*
164+
void freevm(uint*);
165+
void inituvm(uint*, char*, char*, uint);
166+
int loaduvm(uint*, char*, struct inode *ip, uint, uint);
167+
uint* copyuvm(uint*,uint);
168+
void ksegment(void);
169+
void loadvm(struct proc*);
170+
155171
// number of elements in fixed-size array
156172
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
157173

exec.c

Lines changed: 40 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ exec(char *path, char **argv)
1111
{
1212
char *mem, *s, *last;
1313
int i, argc, arglen, len, off;
14-
uint sz, sp, argp;
14+
uint sz, sp, spoffset, argp;
1515
struct elfhdr elf;
1616
struct inode *ip;
1717
struct proghdr ph;
18+
pde_t *pgdir, *oldpgdir;
1819

19-
mem = 0;
20+
pgdir = 0;
2021
sz = 0;
2122

2223
if((ip = namei(path)) == 0)
@@ -29,94 +30,83 @@ exec(char *path, char **argv)
2930
if(elf.magic != ELF_MAGIC)
3031
goto bad;
3132

32-
// Compute memory size of new process.
33-
// Program segments.
34-
for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
35-
if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
36-
goto bad;
37-
if(ph.type != ELF_PROG_LOAD)
38-
continue;
39-
if(ph.memsz < ph.filesz)
40-
goto bad;
41-
sz += ph.memsz;
42-
}
43-
44-
// Arguments.
45-
arglen = 0;
46-
for(argc=0; argv[argc]; argc++)
47-
arglen += strlen(argv[argc]) + 1;
48-
arglen = (arglen+3) & ~3;
49-
sz += arglen;
50-
sz += 4*(argc+1); // argv data
51-
sz += 4; // argv
52-
sz += 4; // argc
53-
54-
// Stack.
55-
sz += PAGE;
56-
57-
// Allocate program memory.
58-
sz = (sz+PAGE-1) & ~(PAGE-1);
59-
mem = kalloc(sz);
60-
if(mem == 0)
33+
if (!(pgdir = setupkvm()))
6134
goto bad;
62-
memset(mem, 0, sz);
6335

6436
// Load program into memory.
6537
for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
6638
if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
6739
goto bad;
6840
if(ph.type != ELF_PROG_LOAD)
6941
continue;
70-
if(ph.va + ph.memsz < ph.va || ph.va + ph.memsz > sz)
71-
goto bad;
7242
if(ph.memsz < ph.filesz)
7343
goto bad;
74-
if(readi(ip, mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
44+
if (!allocuvm(pgdir, (char *)ph.va, ph.memsz))
45+
goto bad;
46+
sz += PGROUNDUP(ph.memsz);
47+
if (!loaduvm(pgdir, (char *)ph.va, ip, ph.offset, ph.filesz))
7548
goto bad;
76-
memset(mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz);
7749
}
7850
iunlockput(ip);
79-
80-
// Initialize stack.
51+
52+
// Allocate and initialize stack at sz
53+
if (!allocuvm(pgdir, (char *)sz, PGSIZE))
54+
goto bad;
55+
mem = uva2ka(pgdir, (char *)sz);
56+
spoffset = sz;
57+
sz += PGSIZE;
58+
59+
arglen = 0;
60+
for(argc=0; argv[argc]; argc++)
61+
arglen += strlen(argv[argc]) + 1;
62+
arglen = (arglen+3) & ~3;
63+
8164
sp = sz;
8265
argp = sz - arglen - 4*(argc+1);
8366

8467
// Copy argv strings and pointers to stack.
85-
*(uint*)(mem+argp + 4*argc) = 0; // argv[argc]
68+
*(uint*)(mem+argp-spoffset + 4*argc) = 0; // argv[argc]
8669
for(i=argc-1; i>=0; i--){
8770
len = strlen(argv[i]) + 1;
8871
sp -= len;
89-
memmove(mem+sp, argv[i], len);
90-
*(uint*)(mem+argp + 4*i) = sp; // argv[i]
72+
memmove(mem+sp-spoffset, argv[i], len);
73+
*(uint*)(mem+argp-spoffset + 4*i) = sp; // argv[i]
9174
}
9275

9376
// Stack frame for main(argc, argv), below arguments.
9477
sp = argp;
9578
sp -= 4;
96-
*(uint*)(mem+sp) = argp;
79+
*(uint*)(mem+sp-spoffset) = argp;
9780
sp -= 4;
98-
*(uint*)(mem+sp) = argc;
81+
*(uint*)(mem+sp-spoffset) = argc;
9982
sp -= 4;
100-
*(uint*)(mem+sp) = 0xffffffff; // fake return pc
83+
*(uint*)(mem+sp-spoffset) = 0xffffffff; // fake return pc
10184

10285
// Save program name for debugging.
10386
for(last=s=path; *s; s++)
10487
if(*s == '/')
10588
last = s+1;
10689
safestrcpy(proc->name, last, sizeof(proc->name));
10790

108-
// Commit to the new image.
109-
kfree(proc->mem, proc->sz);
110-
proc->mem = mem;
91+
// Commit to the user image.
92+
oldpgdir = proc->pgdir;
93+
proc->pgdir = pgdir;
11194
proc->sz = sz;
11295
proc->tf->eip = elf.entry; // main
11396
proc->tf->esp = sp;
114-
usegment();
97+
98+
// printstack();
99+
100+
loadvm(proc);
101+
102+
freevm(oldpgdir);
103+
104+
// printstack();
105+
115106
return 0;
116107

117108
bad:
118-
if(mem)
119-
kfree(mem, sz);
109+
freevm(pgdir);
120110
iunlockput(ip);
121111
return -1;
122112
}

file.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ filewrite(struct file *f, char *addr, int n)
116116
return pipewrite(f->pipe, addr, n);
117117
if(f->type == FD_INODE){
118118
ilock(f->ip);
119-
cprintf("filewrite: %d\n", n);
120119
if((r = writei(f->ip, addr, f->off, n)) > 0)
121120
f->off += r;
122121
iunlock(f->ip);

forktest.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include "stat.h"
66
#include "user.h"
77

8+
#define N 1000
9+
810
void
911
printf(int fd, char *s, ...)
1012
{
@@ -18,16 +20,16 @@ forktest(void)
1820

1921
printf(1, "fork test\n");
2022

21-
for(n=0; n<1000; n++){
23+
for(n=0; n<N; n++){
2224
pid = fork();
2325
if(pid < 0)
2426
break;
2527
if(pid == 0)
2628
exit();
2729
}
2830

29-
if(n == 1000){
30-
printf(1, "fork claimed to work 1000 times!\n");
31+
if(n == N){
32+
printf(1, "fork claimed to work N times!\n", N);
3133
exit();
3234
}
3335

ide.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,9 @@ iderw(struct buf *b)
147147

148148
// Wait for request to finish.
149149
// Assuming will not sleep too long: ignore proc->killed.
150-
while((b->flags & (B_VALID|B_DIRTY)) != B_VALID)
150+
while((b->flags & (B_VALID|B_DIRTY)) != B_VALID) {
151151
sleep(b, &idelock);
152+
}
152153

153154
release(&idelock);
154155
}

kalloc.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "types.h"
99
#include "defs.h"
1010
#include "param.h"
11+
#include "mmu.h"
1112
#include "spinlock.h"
1213

1314
struct run {
@@ -20,21 +21,28 @@ struct {
2021
struct run *freelist;
2122
} kmem;
2223

24+
int nfreemem;
25+
26+
static void
27+
printfreelist(void)
28+
{
29+
struct run *r, **rp;
30+
cprintf("freelist:\n");
31+
for(rp=&kmem.freelist; (r=*rp) != 0; rp=&r->next){
32+
cprintf("0x%x %d=0x%x\n", r, r->len, r->len);
33+
}
34+
}
35+
2336
// Initialize free list of physical pages.
2437
// This code cheats by just considering one megabyte of
2538
// pages after end. Real systems would determine the
2639
// amount of memory available in the system and use it all.
2740
void
28-
kinit(void)
41+
kinit(char *p, uint len)
2942
{
30-
extern char end[];
31-
uint len;
32-
char *p;
33-
3443
initlock(&kmem.lock, "kmem");
35-
p = (char*)(((uint)end + PAGE) & ~(PAGE-1));
36-
len = 256*PAGE; // assume computer has 256 pages of RAM, 1 MB
37-
cprintf("mem = %d\n", len);
44+
cprintf("end 0x%x free = %d(0x%x)\n", p, len);
45+
nfreemem = 0;
3846
kfree(p, len);
3947
}
4048

@@ -47,19 +55,23 @@ kfree(char *v, int len)
4755
{
4856
struct run *r, *rend, **rp, *p, *pend;
4957

50-
if(len <= 0 || len % PAGE)
58+
if(len <= 0 || len % PGSIZE)
5159
panic("kfree");
5260

5361
// Fill with junk to catch dangling refs.
5462
memset(v, 1, len);
5563

5664
acquire(&kmem.lock);
65+
nfreemem += len;
5766
p = (struct run*)v;
5867
pend = (struct run*)(v + len);
5968
for(rp=&kmem.freelist; (r=*rp) != 0 && r <= pend; rp=&r->next){
6069
rend = (struct run*)((char*)r + r->len);
61-
if(r <= p && p < rend)
70+
if(r <= p && p < rend) {
71+
cprintf("freeing a free page: r = 0x%x p = 0x%x rend = 0x%x\n",
72+
r, p, rend);
6273
panic("freeing free page");
74+
}
6375
if(rend == p){ // r before p: expand r to include p
6476
r->len += len;
6577
if(r->next && r->next == pend){ // r now next to r->next?
@@ -93,7 +105,7 @@ kalloc(int n)
93105
char *p;
94106
struct run *r, **rp;
95107

96-
if(n % PAGE || n <= 0)
108+
if(n % PGSIZE || n <= 0)
97109
panic("kalloc");
98110

99111
acquire(&kmem.lock);
@@ -103,6 +115,7 @@ kalloc(int n)
103115
p = (char*)r + r->len;
104116
if(r->len == 0)
105117
*rp = r->next;
118+
nfreemem -= n;
106119
release(&kmem.lock);
107120
return p;
108121
}
@@ -112,3 +125,4 @@ kalloc(int n)
112125
cprintf("kalloc: out of memory\n");
113126
return 0;
114127
}
128+

lapic.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ lapicw(int index, int value)
4848
void
4949
lapicinit(int c)
5050
{
51+
cprintf("lapicinit: %d 0x%x\n", c, lapic);
5152
if(!lapic)
5253
return;
5354

0 commit comments

Comments
 (0)