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 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; nkilled. - 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().