summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--bootasm.S2
-rw-r--r--defs.h22
-rw-r--r--exec.c90
-rw-r--r--file.c1
-rw-r--r--forktest.c8
-rw-r--r--ide.c3
-rw-r--r--kalloc.c36
-rw-r--r--lapic.c1
-rw-r--r--main.c26
-rw-r--r--mmu.h88
-rw-r--r--mp.c1
-rw-r--r--param.h2
-rw-r--r--proc.c72
-rw-r--r--proc.h2
-rw-r--r--sh.c5
-rw-r--r--spinlock.c2
-rw-r--r--swtch.S8
-rw-r--r--syscall.c16
-rw-r--r--sysfile.c5
-rw-r--r--trap.c9
-rw-r--r--x86.h55
22 files changed, 307 insertions, 152 deletions
diff --git a/Makefile b/Makefile
index 91909d8..a0c901d 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/bootasm.S b/bootasm.S
index 059cc1b..f6af255 100644
--- a/bootasm.S
+++ b/bootasm.S
@@ -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
diff --git a/defs.h b/defs.h
index bcfab55..71dbb14 100644
--- a/defs.h
+++ b/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]))
diff --git a/exec.c b/exec.c
index 17fab01..65de312 100644
--- a/exec.c
+++ b/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,37 +30,8 @@ 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)){
@@ -67,37 +39,48 @@ exec(char *path, char **argv)
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++)
@@ -105,18 +88,25 @@ exec(char *path, char **argv)
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;
}
diff --git a/file.c b/file.c
index 9b29d08..e10b824 100644
--- a/file.c
+++ b/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);
diff --git a/forktest.c b/forktest.c
index 90cc38c..bb286e6 100644
--- a/forktest.c
+++ b/forktest.c
@@ -5,6 +5,8 @@
#include "stat.h"
#include "user.h"
+#define N 1000
+
void
printf(int fd, char *s, ...)
{
@@ -18,7 +20,7 @@ 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;
@@ -26,8 +28,8 @@ forktest(void)
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();
}
diff --git a/ide.c b/ide.c
index c0eb80a..7b12aa0 100644
--- a/ide.c
+++ b/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);
}
diff --git a/kalloc.c b/kalloc.c
index 2730d57..200ea8d 100644
--- a/kalloc.c
+++ b/kalloc.c
@@ -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;
}
+
diff --git a/lapic.c b/lapic.c
index d2407b1..4fe4ace 100644
--- a/lapic.c
+++ b/lapic.c
@@ -48,6 +48,7 @@ lapicw(int index, int value)
void
lapicinit(int c)
{
+ cprintf("lapicinit: %d 0x%x\n", c, lapic);
if(!lapic)
return;
diff --git a/main.c b/main.c
index 60cd1b3..319aad9 100644
--- a/main.c
+++ b/main.c
@@ -19,20 +19,27 @@ main(void)
ioapicinit(); // another interrupt controller
consoleinit(); // I/O devices & their interrupts
uartinit(); // serial port
-cprintf("cpus %p cpu %p\n", cpus, cpu);
- cprintf("\ncpu%d: starting xv6\n\n", cpu->id);
+ pminit(); // physical memory for kernel
+ jkstack(); // Jump to mainc on a proper-allocated kernel stack
+}
- kinit(); // physical memory allocator
+void
+mainc(void)
+{
+ cprintf("cpus %p cpu %p\n", cpus, cpu);
+ cprintf("\ncpu%d: starting xv6\n\n", cpu->id);
+ vminit(); // virtual memory
pinit(); // process table
tvinit(); // trap vectors
binit(); // buffer cache
fileinit(); // file table
iinit(); // inode cache
ideinit(); // disk
+ cprintf("ismp: %d\n", ismp);
if(!ismp)
timerinit(); // uniprocessor timer
userinit(); // first user process
- bootothers(); // start other processors
+ // bootothers(); // start other processors XXX fix where to boot from
// Finish setting up this processor in mpmain.
mpmain();
@@ -43,9 +50,12 @@ cprintf("cpus %p cpu %p\n", cpus, cpu);
static void
mpmain(void)
{
- if(cpunum() != mpbcpu())
+ if(cpunum() != mpbcpu()) {
+ ksegment();
+ cprintf("other cpu\n");
+ vminit();
lapicinit(cpunum());
- ksegment();
+ }
cprintf("cpu%d: mpmain\n", cpu->id);
idtinit();
xchg(&cpu->booted, 1);
@@ -74,11 +84,15 @@ bootothers(void)
stack = kalloc(KSTACKSIZE);
*(void**)(code-4) = stack + KSTACKSIZE;
*(void**)(code-8) = mpmain;
+ cprintf("lapicstartap\n");
lapicstartap(c->id, (uint)code);
+ cprintf("lapicstartap done\n");
// Wait for cpu to get through bootstrap.
while(c->booted == 0)
;
+
+ cprintf("lapicstartap booted\n");
}
}
diff --git a/mmu.h b/mmu.h
index 364d05b..76d5ce7 100644
--- a/mmu.h
+++ b/mmu.h
@@ -62,6 +62,8 @@ struct segdesc {
#define STA_R 0x2 // Readable (executable segments)
#define STA_A 0x1 // Accessed
+//
+
// System segment type bits
#define STS_T16A 0x1 // Available 16-bit TSS
#define STS_LDT 0x2 // Local Descriptor Table
@@ -76,6 +78,92 @@ struct segdesc {
#define STS_IG32 0xE // 32-bit Interrupt Gate
#define STS_TG32 0xF // 32-bit Trap Gate
+
+// A linear address 'la' has a three-part structure as follows:
+//
+// +--------10------+-------10-------+---------12----------+
+// | Page Directory | Page Table | Offset within Page |
+// | Index | Index | |
+// +----------------+----------------+---------------------+
+// \--- PDX(la) --/ \--- PTX(la) --/ \---- PGOFF(la) ----/
+// \----------- PPN(la) -----------/
+//
+// The PDX, PTX, PGOFF, and PPN macros decompose linear addresses as shown.
+// To construct a linear address la from PDX(la), PTX(la), and PGOFF(la),
+// use PGADDR(PDX(la), PTX(la), PGOFF(la)).
+
+// page number field of address
+#define PPN(la) (((uint) (la)) >> PTXSHIFT)
+#define VPN(la) PPN(la) // used to index into vpt[]
+
+// page directory index
+#define PDX(la) ((((uint) (la)) >> PDXSHIFT) & 0x3FF)
+#define VPD(la) PDX(la) // used to index into vpd[]
+
+// page table index
+#define PTX(la) ((((uint) (la)) >> PTXSHIFT) & 0x3FF)
+
+// offset in page
+#define PGOFF(la) (((uint) (la)) & 0xFFF)
+
+// construct linear address from indexes and offset
+#define PGADDR(d, t, o) ((uint) ((d) << PDXSHIFT | (t) << PTXSHIFT | (o)))
+
+// mapping from physical addresses to virtual addresses is the identity one
+// (really linear addresses, but we map linear to physical also directly)
+#define PADDR(a) ((uint) a)
+
+// Page directory and page table constants.
+#define NPDENTRIES 1024 // page directory entries per page directory
+#define NPTENTRIES 1024 // page table entries per page table
+
+#define PGSIZE 4096 // bytes mapped by a page
+#define PGSHIFT 12 // log2(PGSIZE)
+
+#define PTSIZE (PGSIZE*NPTENTRIES) // bytes mapped by a page directory entry
+#define PTSHIFT 22 // log2(PTSIZE)
+
+#define PTXSHIFT 12 // offset of PTX in a linear address
+#define PDXSHIFT 22 // offset of PDX in a linear address
+
+// Page table/directory entry flags.
+#define PTE_P 0x001 // Present
+#define PTE_W 0x002 // Writeable
+#define PTE_U 0x004 // User
+#define PTE_PWT 0x008 // Write-Through
+#define PTE_PCD 0x010 // Cache-Disable
+#define PTE_A 0x020 // Accessed
+#define PTE_D 0x040 // Dirty
+#define PTE_PS 0x080 // Page Size
+#define PTE_MBZ 0x180 // Bits must be zero
+
+// The PTE_AVAIL bits aren't used by the kernel or interpreted by the
+// hardware, so user processes are allowed to set them arbitrarily.
+#define PTE_AVAIL 0xE00 // Available for software use
+
+// Only flags in PTE_USER may be used in system calls.
+#define PTE_USER (PTE_AVAIL | PTE_P | PTE_W | PTE_U)
+
+// Address in page table or page directory entry
+#define PTE_ADDR(pte) ((uint) (pte) & ~0xFFF)
+
+typedef uint pte_t;
+typedef uint pde_t;
+
+// Control Register flags
+#define CR0_PE 0x00000001 // Protection Enable
+#define CR0_MP 0x00000002 // Monitor coProcessor
+#define CR0_EM 0x00000004 // Emulation
+#define CR0_TS 0x00000008 // Task Switched
+#define CR0_ET 0x00000010 // Extension Type
+#define CR0_NE 0x00000020 // Numeric Errror
+#define CR0_WP 0x00010000 // Write Protect
+#define CR0_AM 0x00040000 // Alignment Mask
+#define CR0_NW 0x20000000 // Not Writethrough
+#define CR0_CD 0x40000000 // Cache Disable
+#define CR0_PG 0x80000000 // Paging
+
+
// PAGEBREAK: 40
// Task state segment format
struct taskstate {
diff --git a/mp.c b/mp.c
index e1edf24..d2f828a 100644
--- a/mp.c
+++ b/mp.c
@@ -39,6 +39,7 @@ mpsearch1(uchar *addr, int len)
{
uchar *e, *p;
+ cprintf("mpsearch1 0x%x %d\n", addr, len);
e = addr+len;
for(p = addr; p < e; p += sizeof(struct mp))
if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0)
diff --git a/param.h b/param.h
index 34edf95..c1959d1 100644
--- a/param.h
+++ b/param.h
@@ -1,5 +1,5 @@
#define NPROC 64 // maximum number of processes
-#define PAGE 4096 // granularity of user-space memory allocation
+#define PAGE 4096 // conveniently chosen to be equal to PGSIZE
#define KSTACKSIZE PAGE // size of per-process kernel stack
#define NCPU 8 // maximum number of CPUs
#define NOFILE 16 // open files per process
diff --git a/proc.c b/proc.c
index 669331e..a38a9e6 100644
--- a/proc.c
+++ b/proc.c
@@ -60,39 +60,6 @@ procdump(void)
}
}
-// Set up CPU's kernel segment descriptors.
-// Run once at boot time on each CPU.
-void
-ksegment(void)
-{
- struct cpu *c;
-
- c = &cpus[cpunum()];
- c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0x100000 + 64*1024-1, 0);
- c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
- c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 8, 0);
- lgdt(c->gdt, sizeof(c->gdt));
- loadgs(SEG_KCPU << 3);
-
- // Initialize cpu-local storage.
- cpu = c;
- proc = 0;
-}
-
-// Set up CPU's segment descriptors and current process task state.
-void
-usegment(void)
-{
- pushcli();
- cpu->gdt[SEG_UCODE] = SEG(STA_X|STA_R, proc->mem, proc->sz-1, DPL_USER);
- cpu->gdt[SEG_UDATA] = SEG(STA_W, proc->mem, proc->sz-1, DPL_USER);
- cpu->gdt[SEG_TSS] = SEG16(STS_T32A, &cpu->ts, sizeof(cpu->ts)-1, 0);
- cpu->gdt[SEG_TSS].s = 0;
- cpu->ts.ss0 = SEG_KDATA << 3;
- cpu->ts.esp0 = (uint)proc->kstack + KSTACKSIZE;
- ltr(SEG_TSS << 3);
- popcli();
-}
//PAGEBREAK: 32
// Look in the process table for an UNUSED proc.
@@ -149,20 +116,19 @@ userinit(void)
p = allocproc();
initproc = p;
-
- // Initialize memory from initcode.S
- p->sz = PAGE;
- p->mem = kalloc(p->sz);
- memset(p->mem, 0, p->sz);
- memmove(p->mem, _binary_initcode_start, (int)_binary_initcode_size);
-
+ if (!(p->pgdir = setupkvm()))
+ panic("userinit: out of memory?");
+ if (!allocuvm(p->pgdir, 0x0, (int)_binary_initcode_size))
+ panic("userinit: out of memory?");
+ inituvm(p->pgdir, 0x0, _binary_initcode_start, (int)_binary_initcode_size);
+ p->sz = PGROUNDUP((int)_binary_initcode_size);
memset(p->tf, 0, sizeof(*p->tf));
p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
p->tf->ds = (SEG_UDATA << 3) | DPL_USER;
p->tf->es = p->tf->ds;
p->tf->ss = p->tf->ds;
p->tf->eflags = FL_IF;
- p->tf->esp = p->sz;
+ p->tf->esp = PGSIZE;
p->tf->eip = 0; // beginning of initcode.S
safestrcpy(p->name, "initcode", sizeof(p->name));
@@ -176,17 +142,10 @@ userinit(void)
int
growproc(int n)
{
- char *newmem;
-
- newmem = kalloc(proc->sz + n);
- if(newmem == 0)
+ if (!allocuvm(proc->pgdir, (char *)proc->sz, n))
return -1;
- memmove(newmem, proc->mem, proc->sz);
- memset(newmem + proc->sz, 0, n);
- kfree(proc->mem, proc->sz);
- proc->mem = newmem;
proc->sz += n;
- usegment();
+ loadvm(proc);
return 0;
}
@@ -204,14 +163,13 @@ fork(void)
return -1;
// Copy process state from p.
- np->sz = proc->sz;
- if((np->mem = kalloc(np->sz)) == 0){
+ if (!(np->pgdir = copyuvm(proc->pgdir, proc->sz))) {
kfree(np->kstack, KSTACKSIZE);
np->kstack = 0;
np->state = UNUSED;
return -1;
}
- memmove(np->mem, proc->mem, np->sz);
+ np->sz = proc->sz;
np->parent = proc;
*np->tf = *proc->tf;
@@ -225,7 +183,7 @@ fork(void)
pid = np->pid;
np->state = RUNNABLE;
-
+ safestrcpy(np->name, proc->name, sizeof(proc->name));
return pid;
}
@@ -256,7 +214,7 @@ scheduler(void)
// to release ptable.lock and then reacquire it
// before jumping back to us.
proc = p;
- usegment();
+ loadvm(p);
p->state = RUNNING;
swtch(&cpu->scheduler, proc->context);
@@ -284,7 +242,6 @@ sched(void)
panic("sched running");
if(readeflags()&FL_IF)
panic("sched interruptible");
-
intena = cpu->intena;
swtch(&proc->context, cpu->scheduler);
cpu->intena = intena;
@@ -455,9 +412,10 @@ wait(void)
if(p->state == ZOMBIE){
// Found one.
pid = p->pid;
- kfree(p->mem, p->sz);
kfree(p->kstack, KSTACKSIZE);
+ freevm(p->pgdir);
p->state = UNUSED;
+ p->kstack = 0;
p->pid = 0;
p->parent = 0;
p->name[0] = 0;
diff --git a/proc.h b/proc.h
index ebf4f2d..ebc42f1 100644
--- a/proc.h
+++ b/proc.h
@@ -30,8 +30,8 @@ enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
// Per-process state
struct proc {
- char *mem; // Start of process memory (kernel address)
uint sz; // Size of process memory (bytes)
+ pde_t* pgdir; // linear address of proc's pgdir
char *kstack; // Bottom of kernel stack for this process
enum procstate state; // Process state
volatile int pid; // Process ID
diff --git a/sh.c b/sh.c
index 100bbdc..e8d65f0 100644
--- a/sh.c
+++ b/sh.c
@@ -330,7 +330,7 @@ parsecmd(char *s)
{
char *es;
struct cmd *cmd;
-
+
es = s + strlen(s);
cmd = parseline(&s, es);
peek(&s, es, "");
@@ -363,7 +363,7 @@ struct cmd*
parsepipe(char **ps, char *es)
{
struct cmd *cmd;
-
+
cmd = parseexec(ps, es);
if(peek(ps, es, "|")){
gettoken(ps, es, 0, 0);
@@ -420,6 +420,7 @@ parseexec(char **ps, char *es)
int tok, argc;
struct execcmd *cmd;
struct cmd *ret;
+ int *x = (int *) peek;
if(peek(ps, es, "("))
return parseblock(ps, es);
diff --git a/spinlock.c b/spinlock.c
index c3ea730..54e4eb5 100644
--- a/spinlock.c
+++ b/spinlock.c
@@ -71,7 +71,7 @@ getcallerpcs(void *v, uint pcs[])
ebp = (uint*)v - 2;
for(i = 0; i < 10; i++){
- if(ebp == 0 || ebp == (uint*)0xffffffff)
+ if(ebp == 0 || ebp < 0x100000 || ebp == (uint*)0xffffffff)
break;
pcs[i] = ebp[1]; // saved %eip
ebp = (uint*)ebp[0]; // saved %ebp
diff --git a/swtch.S b/swtch.S
index 8751317..49efdf9 100644
--- a/swtch.S
+++ b/swtch.S
@@ -26,3 +26,11 @@ swtch:
popl %ebx
popl %ebp
ret
+
+# Jump on a new stack, fake C calling conventions
+.globl jstack
+jstack:
+ movl 4(%esp), %esp
+ subl $16, %esp # space for arguments
+ movl $0, %ebp # terminate functions that follow ebp's
+ call mainc # continue at mainc
diff --git a/syscall.c b/syscall.c
index 110a872..2785c0a 100644
--- a/syscall.c
+++ b/syscall.c
@@ -18,10 +18,12 @@ fetchint(struct proc *p, uint addr, int *ip)
{
if(addr >= p->sz || addr+4 > p->sz)
return -1;
- *ip = *(int*)(p->mem + addr);
+ *ip = *(int*)(addr);
return 0;
}
+// XXX should we copy the string?
+
// Fetch the nul-terminated string at addr from process p.
// Doesn't actually copy the string - just sets *pp to point at it.
// Returns length of string, not including nul.
@@ -32,8 +34,10 @@ fetchstr(struct proc *p, uint addr, char **pp)
if(addr >= p->sz)
return -1;
- *pp = p->mem + addr;
- ep = p->mem + p->sz;
+ // *pp = p->mem + addr;
+ // ep = p->mem + p->sz;
+ *pp = (char **) addr;
+ ep = p->sz;
for(s = *pp; s < ep; s++)
if(*s == 0)
return s - *pp;
@@ -44,7 +48,8 @@ fetchstr(struct proc *p, uint addr, char **pp)
int
argint(int n, int *ip)
{
- return fetchint(proc, proc->tf->esp + 4 + 4*n, ip);
+ int x = fetchint(proc, proc->tf->esp + 4 + 4*n, ip);
+ return x;
}
// Fetch the nth word-sized system call argument as a pointer
@@ -59,7 +64,8 @@ argptr(int n, char **pp, int size)
return -1;
if((uint)i >= proc->sz || (uint)i+size >= proc->sz)
return -1;
- *pp = proc->mem + i;
+ // *pp = proc->mem + i; // XXXXX
+ *pp = (char *) i; // XXXXX
return 0;
}
diff --git a/sysfile.c b/sysfile.c
index 3eec766..6b8eef4 100644
--- a/sysfile.c
+++ b/sysfile.c
@@ -264,7 +264,6 @@ sys_open(void)
if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
return -1;
-
if(omode & O_CREATE){
if((ip = create(path, T_FILE, 0, 0)) == 0)
return -1;
@@ -291,7 +290,6 @@ sys_open(void)
f->off = 0;
f->readable = !(omode & O_WRONLY);
f->writable = (omode & O_WRONLY) || (omode & O_RDWR);
-
return fd;
}
@@ -350,8 +348,9 @@ sys_exec(void)
int i;
uint uargv, uarg;
- if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0)
+ if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0) {
return -1;
+ }
memset(argv, 0, sizeof(argv));
for(i=0;; i++){
if(i >= NELEM(argv))
diff --git a/trap.c b/trap.c
index 86ce052..1f35708 100644
--- a/trap.c
+++ b/trap.c
@@ -78,13 +78,14 @@ trap(struct trapframe *tf)
default:
if(proc == 0 || (tf->cs&3) == 0){
// In kernel, it must be our mistake.
- cprintf("unexpected trap %d from cpu %d eip %x\n",
- tf->trapno, cpu->id, tf->eip);
+ cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
+ tf->trapno, cpu->id, tf->eip, rcr2());
panic("trap");
}
// In user space, assume process misbehaved.
- cprintf("pid %d %s: trap %d err %d on cpu %d eip %x -- kill proc\n",
- proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip);
+ cprintf("pid %d %s: trap %d err %d on cpu %d eip 0x%x addr 0x%x--kill proc\n",
+ proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip,
+ rcr2());
proc->killed = 1;
}
diff --git a/x86.h b/x86.h
index fcd3062..986e1b0 100644
--- a/x86.h
+++ b/x86.h
@@ -121,6 +121,61 @@ sti(void)
asm volatile("sti");
}
+static inline void lcr0(uint val)
+{
+ asm volatile("movl %0,%%cr0" : : "r" (val));
+}
+
+static inline uint rcr0(void)
+{
+ uint val;
+ asm volatile("movl %%cr0,%0" : "=r" (val));
+ return val;
+}
+
+static inline uint rcr2(void)
+{
+ uint val;
+ asm volatile("movl %%cr2,%0" : "=r" (val));
+ return val;
+}
+
+static inline void lcr3(uint val)
+{
+ asm volatile("movl %0,%%cr3" : : "r" (val));
+}
+
+static inline uint rcr3(void)
+{
+ uint val;
+ asm volatile("movl %%cr3,%0" : "=r" (val));
+ return val;
+}
+
+static inline void lebp(uint val)
+{
+ asm volatile("movl %0,%%ebp" : : "r" (val));
+}
+
+static inline uint rebp(void)
+{
+ uint val;
+ asm volatile("movl %%ebp,%0" : "=r" (val));
+ return val;
+}
+
+static inline void lesp(uint val)
+{
+ asm volatile("movl %0,%%esp" : : "r" (val));
+}
+
+static inline uint resp(void)
+{
+ uint val;
+ asm volatile("movl %%esp,%0" : "=r" (val));
+ return val;
+}
+
//PAGEBREAK: 36
// Layout of the trap frame built on the stack by the
// hardware and by trapasm.S, and passed to trap().