diff --git a/Makefile b/Makefile index 1084c20..b7828dd 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ PRINT = \ string.c\ print: $(PRINT) -// ~/src/lgrind/source/lgrind -d ~/src/lgrind/lgrindef $(PRINT) > xv6.tex + //~/src/lgrind/source/lgrind -d ~/src/lgrind/lgrindef $(PRINT) > xv6.tex lgrind $(PRINT) > xv6.tex latex xv6.tex dvips -o xv61.ps xv6.dvi diff --git a/asm.h b/asm.h index 5986ec7..e02f050 100644 --- a/asm.h +++ b/asm.h @@ -1,3 +1,8 @@ +// +// macros to create x86 segments from assembler +// from JOS +// + #define SEG_NULL \ .word 0, 0; \ .byte 0, 0, 0, 0 diff --git a/bootasm.S b/bootasm.S index c2a3c3e..dda415d 100644 --- a/bootasm.S +++ b/bootasm.S @@ -1,3 +1,7 @@ +# +# from JOS +# + #include "asm.h" .set PROT_MODE_CSEG,0x8 # code segment selector diff --git a/elf.h b/elf.h index 8eb4074..e53051d 100644 --- a/elf.h +++ b/elf.h @@ -1,3 +1,8 @@ +// +// format of an ELF executable file +// from JOS +// + #define ELF_MAGIC 0x464C457FU /* "\x7FELF" in little endian */ struct elfhdr { diff --git a/init.c b/init.c index 5e387a8..359f1fb 100644 --- a/init.c +++ b/init.c @@ -13,20 +13,25 @@ main(void) { int pid; - if(open("console", 0) < 0){ + if(open("console", O_RDWR) < 0){ mknod("console", T_DEV, 1, 1); - open("console", 0); + open("console", O_RDWR); } - open("console", 1); - open("console", 1); + dup(0); + dup(0); while(1){ pid = fork(); - if(pid == 0){ - exec("sh", sh_args); + if(pid < 0){ + puts("init: fork failed\n"); exit(); } - if(pid > 0) + if(pid == 0){ + exec("sh", sh_args); + puts("init: exec sh failed\n"); + exit(); + } else { wait(); + } } } diff --git a/lapic.c b/lapic.c index 0d389f1..3b7c629 100644 --- a/lapic.c +++ b/lapic.c @@ -110,7 +110,6 @@ lapic_write(int r, int data) void lapic_timerinit(void) { - cprintf("cpu%d: init timer\n", cpu()); lapic_write(LAPIC_TDCR, LAPIC_X1); lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC | (IRQ_OFFSET + IRQ_TIMER)); lapic_write(LAPIC_TCCR, 10000000); @@ -129,8 +128,6 @@ lapic_init(int c) { uint r, lvt; - cprintf("cpu%d: lapic_init %d\n", c); - lapic_write(LAPIC_DFR, 0xFFFFFFFF); // set destination format register r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // read APIC ID lapic_write(LAPIC_LDR, (1<state = RUNNABLE; - p->sz = 4 * PAGE; - p->mem = kalloc(p->sz); - memset(p->mem, 0, p->sz); p->kstack = kalloc(KSTACKSIZE); - // cause proc[0] to start in kernel at main00 - memset(&p->jmpbuf, 0, sizeof p->jmpbuf); - p->jmpbuf.eip = (uint)main00; + // cause proc[0] to start in kernel at process0 + p->jmpbuf.eip = (uint) process0; p->jmpbuf.esp = (uint) (p->kstack + KSTACKSIZE - 4); // make sure there's a TSS @@ -78,6 +68,7 @@ main0(void) console_init(); ide_init(); + // start other CPUs mp_startthem(); // turn on timer and enable interrupts on the local APIC @@ -118,7 +109,7 @@ mpmain(void) // proc[0] starts here, called by scheduler() in the ordinary way. void -main00() +process0() { struct proc *p0 = &proc[0]; struct proc *p1; @@ -130,10 +121,13 @@ main00() p0->cwd = iget(rootdev, 1); iunlock(p0->cwd); + // dummy user memory to make copyproc() happy + p0->sz = 4 * PAGE; + p0->mem = kalloc(p0->sz); + // fake a trap frame as if a user process had made a system // call, so that copyproc will have a place for the new // process to return to. - p0 = &proc[0]; p0->tf = &tf; memset(p0->tf, 0, sizeof(struct trapframe)); p0->tf->es = p0->tf->ds = p0->tf->ss = (SEG_UDATA << 3) | 3; @@ -141,7 +135,7 @@ main00() p0->tf->eflags = FL_IF; p0->tf->esp = p0->sz; - p1 = copyproc(&proc[0]); + p1 = copyproc(p0); load_icode(p1, _binary_init_start, (uint) _binary_init_size); p1->state = RUNNABLE; @@ -157,7 +151,6 @@ load_icode(struct proc *p, uchar *binary, uint size) struct elfhdr *elf; struct proghdr *ph; - // Check magic number on binary elf = (struct elfhdr*) binary; if (elf->magic != ELF_MAGIC) panic("load_icode: not an ELF binary"); diff --git a/mmu.h b/mmu.h index 0cd7944..8b30534 100644 --- a/mmu.h +++ b/mmu.h @@ -1,15 +1,8 @@ /* - * This file contains definitions for the x86 memory management unit (MMU), - * including paging- and segmentation-related data structures and constants, - * the %cr0, %cr4, and %eflags registers, and traps. + * This file contains definitions for the x86 memory management unit (MMU). + * from JOS. */ -/* - * Register flags and fundamental constants. - */ - -#define PGSIZE 4096 // bytes mapped by a page - // Eflags register #define FL_CF 0x00000001 // Carry Flag #define FL_PF 0x00000004 // Parity Flag @@ -33,33 +26,7 @@ #define FL_VIP 0x00100000 // Virtual Interrupt Pending #define FL_ID 0x00200000 // ID flag -// Page fault error codes -#define FEC_PR 0x1 // Page fault caused by protection violation -#define FEC_WR 0x2 // Page fault caused by a write -#define FEC_U 0x4 // Page fault occured while in user mode - -/* - * - * Segmentation data structures and constants. - * - */ - -#ifdef __ASSEMBLER__ - -/* - * Macros to build GDT entries in assembly. - */ -#define SEG_NULL \ - .word 0, 0; \ - .byte 0, 0, 0, 0 -#define SEG(type,base,lim) \ - .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ - .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ - (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) - -#else // not __ASSEMBLER__ - -// Segment Descriptors +// Segment Descriptor struct segdesc { uint lim_15_0 : 16; // Low bits of segment limit uint base_15_0 : 16; // Low bits of segment base address @@ -75,22 +42,21 @@ struct segdesc { uint g : 1; // Granularity: limit scaled by 4K when set uint base_31_24 : 8; // High bits of segment base address }; + // Null segment #define SEG_NULL (struct segdesc){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } -// Segment that is loadable but faults when used -#define SEG_FAULT (struct segdesc){ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 } + // Normal segment #define SEG(type, base, lim, dpl) (struct segdesc) \ { ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \ type, 1, dpl, 1, (uint) (lim) >> 28, 0, 0, 1, 1, \ (uint) (base) >> 24 } + #define SEG16(type, base, lim, dpl) (struct segdesc) \ { (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \ type, 1, dpl, 1, (uint) (lim) >> 16, 0, 0, 1, 0, \ (uint) (base) >> 24 } -#endif /* !__ASSEMBLER__ */ - // Application segment type bits #define STA_X 0x8 // Executable segment #define STA_E 0x4 // Expand down (non-executable segments) @@ -113,16 +79,7 @@ struct segdesc { #define STS_IG32 0xE // 32-bit Interrupt Gate #define STS_TG32 0xF // 32-bit Trap Gate - -/* - * - * Traps. - * - */ - -#ifndef __ASSEMBLER__ - -// Task state segment format (as described by the Pentium architecture book) +// Task state segment format struct taskstate { uint link; // Old ts selector uint esp0; // Stack pointers and segment selectors @@ -197,19 +154,3 @@ struct gatedesc { (gate).off_31_16 = (uint) (off) >> 16; \ } -// Set up a call gate descriptor. -#define SETCALLGATE(gate, ss, off, d) \ -{ \ - (gate).off_15_0 = (uint) (off) & 0xffff; \ - (gate).ss = (ss); \ - (gate).args = 0; \ - (gate).rsv1 = 0; \ - (gate).type = STS_CG32; \ - (gate).s = 0; \ - (gate).dpl = (d); \ - (gate).p = 1; \ - (gate).off_31_16 = (uint) (off) >> 16; \ -} - -#endif /* !__ASSEMBLER__ */ - diff --git a/mp.c b/mp.c index 341b545..5029f12 100644 --- a/mp.c +++ b/mp.c @@ -42,7 +42,6 @@ mp_scan(uchar *addr, int len) uchar *e, *p, sum; int i; - cprintf("scanning: 0x%x\n", (uint)addr); e = addr+len; for(p = addr; p < e; p += sizeof(struct mp)){ if(memcmp(p, "_MP_", 4)) @@ -131,8 +130,6 @@ mp_init(void) ncpu = 0; if ((r = mp_detect()) != 0) return; - cprintf("Mp spec rev #: %x imcrp 0x%x\n", mp->specrev, mp->imcrp); - /* * Run through the table saving information needed for starting * application processors and initialising any I/O APICs. The table @@ -140,7 +137,6 @@ mp_init(void) */ mpctb = (struct mpctb *) mp->physaddr; lapicaddr = (uint *) mpctb->lapicaddr; - cprintf("apicaddr: %x\n", lapicaddr); p = ((uchar*)mpctb)+sizeof(struct mpctb); e = ((uchar*)mpctb)+mpctb->length; @@ -149,7 +145,6 @@ mp_init(void) case MPPROCESSOR: proc = (struct mppe *) p; cpus[ncpu].apicid = proc->apicid; - cprintf("a processor %x\n", cpus[ncpu].apicid); if (proc->flags & MPBP) { bcpu = &cpus[ncpu]; } @@ -162,18 +157,15 @@ mp_init(void) if(strncmp(buses[i], bus->string, sizeof(bus->string)) == 0) break; } - cprintf("a bus %d\n", i); p += sizeof(struct mpbe); continue; case MPIOAPIC: ioapic = (struct mpioapic *) p; - cprintf("an I/O APIC: id %d %x\n", ioapic->apicno, ioapic->flags); ioapic_id = ioapic->apicno; p += sizeof(struct mpioapic); continue; case MPIOINTR: intr = (struct mpie *) p; - // cprintf("an I/O intr: type %d flags 0x%x bus %d souce bus irq %d dest ioapic id %d dest ioapic intin %d\n", intr->intr, intr->flags, intr->busno, intr->irq, intr->apicno, intr->intin); p += sizeof(struct mpie); continue; default: @@ -192,8 +184,6 @@ mp_init(void) byte |= 0x01; /* mask external INTR */ outb(0x23, byte); /* disconnect 8259s/NMI */ } - - cprintf("ncpu: %d boot %d\n", ncpu, bcpu-cpus); } @@ -219,7 +209,6 @@ mp_startthem(void) for(c = 0; c < ncpu; c++){ if (c == cpu()) continue; - cprintf ("cpu%d: starting processor %d\n", cpu(), c); *(uint *)(APBOOTCODE-4) = (uint) (cpus[c].mpstack) + MPSTACK; // tell it what to use for %esp *(uint *)(APBOOTCODE-8) = (uint)mpmain; // tell it where to jump to lapic_startap(cpus[c].apicid, (uint) APBOOTCODE); diff --git a/proc.c b/proc.c index 1d0917f..01f6aa4 100644 --- a/proc.c +++ b/proc.c @@ -169,18 +169,11 @@ scheduler(void) struct proc *p; int i; - if(cpus[cpu()].nlock != 0){ - cprintf("la %x lr %x\n", cpus[cpu()].lastacquire, cpus[cpu()].lastrelease ); - panic("holding locks at first entry to scheduler"); - } - for(;;){ // Loop over process table looking for process to run. acquire(&proc_table_lock); + for(i = 0; i < NPROC; i++){ - if(cpus[cpu()].guard1 != 0xdeadbeef || - cpus[cpu()].guard2 != 0xdeadbeef) - panic("cpu guard"); p = &proc[i]; if(p->state != RUNNABLE) continue; @@ -198,31 +191,11 @@ scheduler(void) // Process is done running for now. // It should have changed its p->state before coming back. curproc[cpu()] = 0; - if(p->state == RUNNING) - panic("swtch to scheduler with state=RUNNING"); - if(!holding(&proc_table_lock)){ - cprintf("back to scheduler without proc_table_lock (pid=%d state=%d)", p->pid, p->state); - panic("scheduler lock"); - } - if(cpus[cpu()].nlock != 1){ - cprintf("holding %d locks in scheduler (pid=%d state=%d)\n", cpus[cpu()].nlock, p->pid, p->state); - panic("scheduler lock"); - } - setupsegs(0); } release(&proc_table_lock); - - if(cpus[cpu()].nlock != 0) - panic("holding locks in scheduler"); - - // With proc_table_lock released, there are no - // locks held on this cpu, so interrupts are enabled. - // Hardware interrupts can happen here. - // Also, releasing the lock here lets the other CPUs - // look for runnable processes too. } } diff --git a/proc.h b/proc.h index 64e979a..5689bbc 100644 --- a/proc.h +++ b/proc.h @@ -66,13 +66,9 @@ struct cpu { struct jmpbuf jmpbuf; struct taskstate ts; // only to give cpu address of kernel stack struct segdesc gdt[NSEGS]; - int guard1; char mpstack[MPSTACK]; // per-cpu start-up stack - int guard2; volatile int booted; int nlock; // # of locks currently held - struct spinlock *lastacquire; // xxx debug - struct spinlock *lastrelease; // xxx debug }; extern struct cpu cpus[NCPU]; diff --git a/spinlock.c b/spinlock.c index c77e444..7285748 100644 --- a/spinlock.c +++ b/spinlock.c @@ -43,7 +43,6 @@ acquire(struct spinlock * lock) cpuid(0, 0, 0, 0, 0); // memory barrier getcallerpcs(&lock, lock->pcs); lock->cpu = cpu() + 10; - cpus[cpu()].lastacquire = lock; } void @@ -53,7 +52,6 @@ release(struct spinlock * lock) if(!holding(lock)) panic("release"); - cpus[cpu()].lastrelease = lock; lock->pcs[0] = 0; lock->cpu = 0xffffffff; cpuid(0, 0, 0, 0, 0); // memory barrier diff --git a/syscall.c b/syscall.c index eaf13c5..5a7a60d 100644 --- a/syscall.c +++ b/syscall.c @@ -473,7 +473,7 @@ sys_getpid(void) int sys_sbrk(void) { - unsigned addr; + uint addr; int n; struct proc *cp = curproc[cpu()]; diff --git a/trapasm.S b/trapasm.S index 3e0f375..ca5b42a 100644 --- a/trapasm.S +++ b/trapasm.S @@ -1,5 +1,3 @@ -#include "mmu.h" - .text .globl trap .globl trapret1 diff --git a/usertests.c b/usertests.c index badaa1c..54cebbd 100644 --- a/usertests.c +++ b/usertests.c @@ -13,7 +13,10 @@ pipe1(void) int fds[2], pid; int seq = 0, i, n, cc, total; - pipe(fds); + if(pipe(fds) != 0){ + puts("pipe() failed\n"); + exit(); + } pid = fork(); if(pid == 0){ close(fds[0]); @@ -26,7 +29,7 @@ pipe1(void) } } exit(); - } else { + } else if(pid > 0){ close(fds[1]); total = 0; cc = 1; @@ -43,9 +46,12 @@ pipe1(void) cc = sizeof(buf); } if(total != 5 * 1033) - printf(1, "pipe1 oops 3\n"); + printf(1, "pipe1 oops 3 total %d\n", total); close(fds[0]); wait(); + } else { + puts("fork() failed\n"); + exit(); } puts("pipe1 ok\n"); } @@ -121,26 +127,30 @@ void mem(void) { void *m1, *m2; + int pid; - m1 = 0; - while ((m2 = malloc(1024)) != 0) { - printf(1, "malloc %x\n", m2); - *(char **) m2 = m1; - m1 = m2; - } - while (m1) { - m2 = *(char **)m1; + if((pid = fork()) == 0){ + m1 = 0; + while ((m2 = malloc(10001)) != 0) { + *(char **) m2 = m1; + m1 = m2; + } + while (m1) { + m2 = *(char **)m1; + free(m1); + m1 = m2; + } + m1 = malloc(1024*20); + if (m1 == 0) { + puts("couldn't allocate mem?!!\n"); + exit(); + } free(m1); - m1 = m2; - } - m1 = malloc(1024*20); - if (m1 == 0) { - puts("couldn't allocate mem?!!\n"); + printf(1, "mem ok\n"); exit(); + } else { + wait(); } - free(m1); - - printf(1, "mem ok\n"); } int