Permalink
Browse files

Initial version of single-cpu xv6 with page tables

  • Loading branch information...
1 parent b7a517f commit 40889627ba50db29a64bc6a1553c2b21e6a99b78 Frans Kaashoek committed Jul 2, 2010
Showing with 307 additions and 152 deletions.
  1. +3 −2 Makefile
  2. +1 −1 bootasm.S
  3. +19 −3 defs.h
  4. +40 −50 exec.c
  5. +0 −1 file.c
  6. +5 −3 forktest.c
  7. +2 −1 ide.c
  8. +25 −11 kalloc.c
  9. +1 −0 lapic.c
  10. +20 −6 main.c
  11. +88 −0 mmu.h
  12. +1 −0 mp.c
  13. +1 −1 param.h
  14. +15 −57 proc.c
  15. +1 −1 proc.h
  16. +3 −2 sh.c
  17. +1 −1 spinlock.c
  18. +8 −0 swtch.S
  19. +11 −5 syscall.c
  20. +2 −3 sysfile.c
  21. +5 −4 trap.c
  22. +55 −0 x86.h
View
@@ -25,12 +25,13 @@ OBJS = \
trap.o\
uart.o\
vectors.o\
+ vm.o\
# Cross-compiling (e.g., on Mac OS X)
-#TOOLPREFIX = i386-jos-elf-
+TOOLPREFIX = i386-jos-elf-
# Using native tools (e.g., on X86 Linux)
-TOOLPREFIX =
+#TOOLPREFIX =
CC = $(TOOLPREFIX)gcc
AS = $(TOOLPREFIX)gas
View
@@ -88,5 +88,5 @@ gdt:
SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg
gdtdesc:
- .word (gdtdesc - gdt - 1) # sizeof(gdt) - 1
+ .word (gdtdesc - gdt - 1) # sizeof(gdt) - 1
.long gdt # address gdt
View
22 defs.h
@@ -60,9 +60,10 @@ extern uchar ioapicid;
void ioapicinit(void);
// kalloc.c
+extern int nfreemem;
char* kalloc(int);
void kfree(char*, int);
-void kinit(void);
+void kinit(char*,uint);
// kbd.c
void kbdintr(void);
@@ -101,8 +102,6 @@ int kill(int);
void pinit(void);
void procdump(void);
void scheduler(void) __attribute__((noreturn));
-void ksegment(void);
-void usegment(void);
void sleep(void*, struct spinlock*);
void userinit(void);
int wait(void);
@@ -111,6 +110,7 @@ void yield(void);
// swtch.S
void swtch(struct context**, struct context*);
+void jstack(uint);
// spinlock.c
void acquire(struct spinlock*);
@@ -152,6 +152,22 @@ void uartinit(void);
void uartintr(void);
void uartputc(int);
+// vm.c
+#define PGROUNDUP(sz) ((sz+PGSIZE-1) & ~(PGSIZE-1))
+void pminit(void);
+void swkstack(void);
+void vminit(void);
+void printpgdir(uint*);
+uint* setupkvm(void); // XXX need pde_t*
+char* uva2ka(uint*, char*);
+int allocuvm(uint*, char*, uint); // XXX need pde_t*
+void freevm(uint*);
+void inituvm(uint*, char*, char*, uint);
+int loaduvm(uint*, char*, struct inode *ip, uint, uint);
+uint* copyuvm(uint*,uint);
+void ksegment(void);
+void loadvm(struct proc*);
+
// number of elements in fixed-size array
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
View
90 exec.c
@@ -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,94 +30,83 @@ 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)){
if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
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++)
if(*s == '/')
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;
}
View
1 file.c
@@ -116,7 +116,6 @@ filewrite(struct file *f, char *addr, int n)
return pipewrite(f->pipe, addr, n);
if(f->type == FD_INODE){
ilock(f->ip);
- cprintf("filewrite: %d\n", n);
if((r = writei(f->ip, addr, f->off, n)) > 0)
f->off += r;
iunlock(f->ip);
View
@@ -5,6 +5,8 @@
#include "stat.h"
#include "user.h"
+#define N 1000
+
void
printf(int fd, char *s, ...)
{
@@ -18,16 +20,16 @@ forktest(void)
printf(1, "fork test\n");
- for(n=0; n<1000; n++){
+ for(n=0; n<N; n++){
pid = fork();
if(pid < 0)
break;
if(pid == 0)
exit();
}
- if(n == 1000){
- printf(1, "fork claimed to work 1000 times!\n");
+ if(n == N){
+ printf(1, "fork claimed to work N times!\n", N);
exit();
}
View
3 ide.c
@@ -147,8 +147,9 @@ iderw(struct buf *b)
// Wait for request to finish.
// Assuming will not sleep too long: ignore proc->killed.
- while((b->flags & (B_VALID|B_DIRTY)) != B_VALID)
+ while((b->flags & (B_VALID|B_DIRTY)) != B_VALID) {
sleep(b, &idelock);
+ }
release(&idelock);
}
View
@@ -8,6 +8,7 @@
#include "types.h"
#include "defs.h"
#include "param.h"
+#include "mmu.h"
#include "spinlock.h"
struct run {
@@ -20,21 +21,28 @@ struct {
struct run *freelist;
} kmem;
+int nfreemem;
+
+static void
+printfreelist(void)
+{
+ struct run *r, **rp;
+ cprintf("freelist:\n");
+ for(rp=&kmem.freelist; (r=*rp) != 0; rp=&r->next){
+ cprintf("0x%x %d=0x%x\n", r, r->len, r->len);
+ }
+}
+
// Initialize free list of physical pages.
// This code cheats by just considering one megabyte of
// pages after end. Real systems would determine the
// amount of memory available in the system and use it all.
void
-kinit(void)
+kinit(char *p, uint len)
{
- extern char end[];
- uint len;
- char *p;
-
initlock(&kmem.lock, "kmem");
- p = (char*)(((uint)end + PAGE) & ~(PAGE-1));
- len = 256*PAGE; // assume computer has 256 pages of RAM, 1 MB
- cprintf("mem = %d\n", len);
+ cprintf("end 0x%x free = %d(0x%x)\n", p, len);
+ nfreemem = 0;
kfree(p, len);
}
@@ -47,19 +55,23 @@ kfree(char *v, int len)
{
struct run *r, *rend, **rp, *p, *pend;
- if(len <= 0 || len % PAGE)
+ if(len <= 0 || len % PGSIZE)
panic("kfree");
// Fill with junk to catch dangling refs.
memset(v, 1, len);
acquire(&kmem.lock);
+ nfreemem += len;
p = (struct run*)v;
pend = (struct run*)(v + len);
for(rp=&kmem.freelist; (r=*rp) != 0 && r <= pend; rp=&r->next){
rend = (struct run*)((char*)r + r->len);
- if(r <= p && p < rend)
+ if(r <= p && p < rend) {
+ cprintf("freeing a free page: r = 0x%x p = 0x%x rend = 0x%x\n",
+ r, p, rend);
panic("freeing free page");
+ }
if(rend == p){ // r before p: expand r to include p
r->len += len;
if(r->next && r->next == pend){ // r now next to r->next?
@@ -93,7 +105,7 @@ kalloc(int n)
char *p;
struct run *r, **rp;
- if(n % PAGE || n <= 0)
+ if(n % PGSIZE || n <= 0)
panic("kalloc");
acquire(&kmem.lock);
@@ -103,6 +115,7 @@ kalloc(int n)
p = (char*)r + r->len;
if(r->len == 0)
*rp = r->next;
+ nfreemem -= n;
release(&kmem.lock);
return p;
}
@@ -112,3 +125,4 @@ kalloc(int n)
cprintf("kalloc: out of memory\n");
return 0;
}
+
View
@@ -48,6 +48,7 @@ lapicw(int index, int value)
void
lapicinit(int c)
{
+ cprintf("lapicinit: %d 0x%x\n", c, lapic);
if(!lapic)
return;
Oops, something went wrong.

0 comments on commit 4088962

Please sign in to comment.