diff --git a/Makefile b/Makefile index c3495c0..870ea70 100644 --- a/Makefile +++ b/Makefile @@ -20,18 +20,22 @@ bootblock : bootasm.S bootmain.c $(OBJCOPY) -S -O binary bootblock.o bootblock ./sign.pl bootblock -kernel : $(OBJS) bootother.S +kernel : $(OBJS) bootother.S user1 $(CC) -nostdinc -I. -c bootother.S $(LD) -N -e start -Ttext 0x7000 -o bootother.out bootother.o $(OBJCOPY) -S -O binary bootother.out bootother $(OBJDUMP) -S bootother.o > bootother.asm - $(LD) -Ttext 0x100000 -e main -o kernel $(OBJS) -b binary bootother + $(LD) -Ttext 0x100000 -e main -o kernel $(OBJS) -b binary bootother user1 $(OBJDUMP) -S kernel > kernel.asm vectors.S : vectors.pl perl vectors.pl > vectors.S +user1 : user1.c + $(CC) -nostdinc -I. -c user1.c + $(LD) -N -e main -Ttext 0 -o user1 user1.o + -include *.d clean : - rm -f *.o bootblock kernel kernel.asm xv6.img *.d + rm -f *.o bootblock kernel kernel.asm xv6.img *.d user1 diff --git a/defs.h b/defs.h index 70394bb..85f3578 100644 --- a/defs.h +++ b/defs.h @@ -33,7 +33,7 @@ void pic_init(void); // mp.c void mp_init(void); -int lapic_cpu_number(void); +int cpu(void); int mp_isbcpu(void); // spinlock.c @@ -42,3 +42,5 @@ void acquire_spinlock(uint32_t* lock); void release_spinlock(uint32_t* lock); void release_grant_spinlock(uint32_t* lock, int cpu); +// main.c +void load_icode(struct proc *p, uint8_t *binary, unsigned size); diff --git a/main.c b/main.c index 5b17297..206daf3 100644 --- a/main.c +++ b/main.c @@ -6,9 +6,13 @@ #include "x86.h" #include "traps.h" #include "syscall.h" +#include "elf.h" +#include "param.h" extern char edata[], end[]; extern int acpu; +extern char _binary_user1_start[]; +extern char _binary_user1_size[]; char buf[512]; @@ -16,12 +20,14 @@ int main() { struct proc *p; - int i; if (acpu) { cprintf("an application processor\n"); release_spinlock(&kernel_lock); - while (1) ; + acquire_spinlock(&kernel_lock); + lapic_init(cpu()); + curproc[cpu()] = &proc[0]; // XXX + swtch(); } acpu = 1; // clear BSS @@ -34,11 +40,9 @@ main() tinit(); // traps and interrupts pic_init(); - while (1); - // create fake process zero p = &proc[0]; - curproc = p; + curproc[cpu()] = p; p->state = WAITING; p->sz = PAGE; p->mem = kalloc(p->sz); @@ -54,17 +58,20 @@ main() setupsegs(p); // turn on interrupts + irq_setmask_8259A(0xff); write_eflags(read_eflags() | FL_IF); - irq_setmask_8259A(0); #if 0 ide_read(0, buf, 1); cprintf("sec0.0 %x\n", buf[0] & 0xff); #endif -#if 0 +#if 1 p = newproc(); + load_icode(p, _binary_user1_start, (unsigned) _binary_user1_size); +#endif +#if 0 i = 0; p->mem[i++] = 0x90; // nop p->mem[i++] = 0xb8; // mov ..., %eax @@ -96,3 +103,36 @@ main() return 0; } + +void +load_icode(struct proc *p, uint8_t *binary, unsigned size) +{ + int i; + struct Elf *elf; + struct Proghdr *ph; + + // Check magic number on binary + elf = (struct Elf*) binary; + cprintf("elf %x magic %x\n", elf, elf->e_magic); + if (elf->e_magic != ELF_MAGIC) + panic("load_icode: not an ELF binary"); + + p->tf->tf_eip = elf->e_entry; + p->tf->tf_esp = p->sz; + + // Map and load segments as directed. + ph = (struct Proghdr*) (binary + elf->e_phoff); + for (i = 0; i < elf->e_phnum; i++, ph++) { + if (ph->p_type != ELF_PROG_LOAD) + continue; + cprintf("va %x memsz %d\n", ph->p_va, ph->p_memsz); + if (ph->p_va + ph->p_memsz < ph->p_va) + panic("load_icode: overflow in elf header segment"); + if (ph->p_va + ph->p_memsz >= p->sz) + panic("load_icode: icode wants to be above UTOP"); + + // Load/clear the segment + memcpy(p->mem + ph->p_va, binary + ph->p_offset, ph->p_filesz); + memset(p->mem + ph->p_va + ph->p_filesz, 0, ph->p_memsz - ph->p_filesz); + } +} diff --git a/mp.c b/mp.c index d3db697..e797f81 100644 --- a/mp.c +++ b/mp.c @@ -97,7 +97,7 @@ static uint32_t *lapicaddr; static struct cpu { uint8_t apicid; /* Local APIC ID */ int lintr[2]; /* Local APIC */ -} cpu[NCPU]; +} cpus[NCPU]; static int ncpu; static struct cpu *bcpu; @@ -113,7 +113,7 @@ lapic_write(int r, int data) *(lapicaddr+(r/sizeof(*lapicaddr))) = data; } -static void +void lapic_init(int c) { uint32_t r, lvt; @@ -131,8 +131,8 @@ lapic_init(int c) * LINT[01] are set to ExtINT. * Acknowledge any outstanding interrupts. */ - lapic_write(LAPIC_LINT0, cpu[c].lintr[0]); - lapic_write(LAPIC_LINT1, cpu[c].lintr[1]); + lapic_write(LAPIC_LINT0, cpus[c].lintr[0]); + lapic_write(LAPIC_LINT1, cpus[c].lintr[1]); lapic_write(LAPIC_EOI, 0); lvt = (lapic_read(LAPIC_VER)>>16) & 0xFF; @@ -168,7 +168,7 @@ lapic_online(void) } int -lapic_cpu_number(void) +cpu(void) { return (lapic_read(LAPIC_ID)>>24) & 0xFF; } @@ -312,12 +312,12 @@ mp_init() switch(*p){ case MPPROCESSOR: proc = (struct MPPE *) p; - cpu[ncpu].apicid = proc->apicid; - cpu[ncpu].lintr[0] = APIC_IMASK; - cpu[ncpu].lintr[1] = APIC_IMASK; - cprintf("a processor %x\n", cpu[ncpu].apicid); + cpus[ncpu].apicid = proc->apicid; + cpus[ncpu].lintr[0] = APIC_IMASK; + cpus[ncpu].lintr[1] = APIC_IMASK; + cprintf("a processor %x\n", cpus[ncpu].apicid); if (proc->flags & MPBP) { - bcpu = &cpu[ncpu]; + bcpu = &cpus[ncpu]; } ncpu++; p += sizeof(struct MPPE); @@ -342,8 +342,8 @@ mp_init() } } - lapic_init(cpu-bcpu); - cprintf("ncpu: %d boot %d\n", ncpu, cpu-bcpu); + lapic_init(bcpu-cpus); + cprintf("ncpu: %d boot %d\n", ncpu, bcpu-cpus); lapic_online(); @@ -352,12 +352,12 @@ mp_init() (uint32_t) _binary_bootother_size); acquire_spinlock(&kernel_lock); - for (c = cpu; c < &cpu[ncpu]; c++) { + for (c = cpus; c < &cpus[ncpu]; c++) { if (c == bcpu) continue; - cprintf ("starting processor %d\n", c - cpu); - release_grant_spinlock(&kernel_lock, c - cpu); + cprintf ("starting processor %d\n", c - cpus); + release_grant_spinlock(&kernel_lock, c - cpus); lapic_startap(c, (uint32_t) KADDR(APBOOTCODE)); acquire_spinlock(&kernel_lock); - cprintf ("done starting processor %d\n", c - cpu); + cprintf ("done starting processor %d\n", c - cpus); } } diff --git a/proc.c b/proc.c index 8291039..e771c4d 100644 --- a/proc.c +++ b/proc.c @@ -1,12 +1,12 @@ #include "types.h" #include "mmu.h" #include "x86.h" -#include "proc.h" #include "param.h" +#include "proc.h" #include "defs.h" struct proc proc[NPROC]; -struct proc *curproc; +struct proc *curproc[NCPU]; int next_pid = 1; /* @@ -47,6 +47,7 @@ struct proc * newproc() { struct proc *np; + struct proc *op = curproc[cpu()]; unsigned *sp; for(np = &proc[1]; np < &proc[NPROC]; np++) @@ -56,22 +57,22 @@ newproc() return 0; np->pid = next_pid++; - np->ppid = curproc->pid; - np->sz = curproc->sz; - np->mem = kalloc(curproc->sz); + np->ppid = op->pid; + np->sz = op->sz; + np->mem = kalloc(op->sz); if(np->mem == 0) return 0; - memcpy(np->mem, curproc->mem, np->sz); + memcpy(np->mem, op->mem, np->sz); np->kstack = kalloc(KSTACKSIZE); if(np->kstack == 0){ - kfree(np->mem, curproc->sz); + kfree(np->mem, op->sz); return 0; } setupsegs(np); // set up kernel stack to return to user space np->tf = (struct Trapframe *) (np->kstack + KSTACKSIZE - sizeof(struct Trapframe)); - *(np->tf) = *(curproc->tf); + *(np->tf) = *(op->tf); sp = (unsigned *) np->tf; *(--sp) = (unsigned) &trapret; // for return from swtch() *(--sp) = 0; // previous bp for leave in swtch() @@ -92,31 +93,38 @@ void swtch() { struct proc *np; + struct proc *op = curproc[cpu()]; + cprintf("swtch cpu %d op %x proc0 %x\n", cpu(), op, proc); while(1){ - for(np = curproc + 1; np != curproc; np++){ - if(np == &proc[NPROC]) - np = &proc[0]; + np = op + 1; + while(np != op){ if(np->state == RUNNABLE) break; + np++; + if(np == &proc[NPROC]) + np = &proc[0]; } if(np->state == RUNNABLE) break; - // idle... + cprintf("swtch: nothing to run\n"); + release_spinlock(&kernel_lock); + acquire_spinlock(&kernel_lock); } - curproc->ebp = read_ebp(); - curproc->esp = read_esp(); + op->ebp = read_ebp(); + op->esp = read_esp(); - cprintf("swtch %x -> %x\n", curproc, np); + cprintf("cpu %d swtch %x -> %x\n", cpu(), op, np); - curproc = np; + curproc[cpu()] = np; + np->state = RUNNING; // XXX callee-saved registers? // h/w sets busy bit in TSS descriptor sometimes, and faults // if it's set in LTR. so clear tss descriptor busy bit. - curproc->gdt[SEG_TSS].sd_type = STS_T32A; + np->gdt[SEG_TSS].sd_type = STS_T32A; // XXX probably ought to lgdt on trap return too, in case // a system call has moved a program or changed its size. @@ -134,8 +142,8 @@ swtch() void sleep(void *chan) { - curproc->chan = chan; - curproc->state = WAITING; + curproc[cpu()]->chan = chan; + curproc[cpu()]->state = WAITING; swtch(); } diff --git a/proc.h b/proc.h index 6eba566..36e608e 100644 --- a/proc.h +++ b/proc.h @@ -20,7 +20,7 @@ struct proc{ char *mem; // start of process's physical memory unsigned sz; // total size of mem, including kernel stack char *kstack; // kernel stack, separate from mem so it doesn't move - enum { UNUSED, RUNNABLE, WAITING, ZOMBIE } state; + enum { UNUSED, RUNNABLE, WAITING, ZOMBIE, RUNNING } state; int pid; int ppid; void *chan; // sleep @@ -35,4 +35,4 @@ struct proc{ }; extern struct proc proc[]; -extern struct proc *curproc; +extern struct proc *curproc[NCPU]; diff --git a/spinlock.c b/spinlock.c index fa04a27..2666842 100644 --- a/spinlock.c +++ b/spinlock.c @@ -10,18 +10,18 @@ uint32_t kernel_lock = LOCK_FREE; void acquire_spinlock(uint32_t* lock) { - int cpu_id = lapic_cpu_number(); - cprintf ("acquire: %d\n", cpu_id); + int cpu_id = cpu(); if (*lock == cpu_id) return; while ( cmpxchg(LOCK_FREE, cpu_id, lock) != cpu_id ) { ; } + cprintf ("acquired: %d\n", cpu_id); } void release_spinlock(uint32_t* lock) { - int cpu_id = lapic_cpu_number(); + int cpu_id = cpu(); cprintf ("release: %d\n", cpu_id); if (*lock != cpu_id) panic("release_spinlock: releasing a lock that i don't own\n"); @@ -31,7 +31,7 @@ release_spinlock(uint32_t* lock) void release_grant_spinlock(uint32_t* lock, int c) { - int cpu_id = lapic_cpu_number(); + int cpu_id = cpu(); cprintf ("release_grant: %d -> %d\n", cpu_id, c); if (*lock != cpu_id) panic("release_spinlock: releasing a lock that i don't own\n"); diff --git a/syscall.c b/syscall.c index 1968c8a..48adba8 100644 --- a/syscall.c +++ b/syscall.c @@ -25,17 +25,18 @@ void sys_exit() { struct proc *p; + struct proc *cp = curproc[cpu()]; - curproc->state = ZOMBIE; + cp->state = ZOMBIE; // wake up parent for(p = proc; p < &proc[NPROC]; p++) - if(p->pid == curproc->ppid) + if(p->pid == cp->ppid) wakeup(p); // abandon children for(p = proc; p < &proc[NPROC]; p++) - if(p->ppid == curproc->pid) + if(p->ppid == cp->pid) p->pid = 1; swtch(); @@ -45,37 +46,39 @@ void sys_wait() { struct proc *p; + struct proc *cp = curproc[cpu()]; int any; - cprintf("waid pid %d ppid %d\n", curproc->pid, curproc->ppid); + cprintf("waid pid %d ppid %d\n", cp->pid, cp->ppid); while(1){ any = 0; for(p = proc; p < &proc[NPROC]; p++){ - if(p->state == ZOMBIE && p->ppid == curproc->pid){ + if(p->state == ZOMBIE && p->ppid == cp->pid){ kfree(p->mem, p->sz); kfree(p->kstack, KSTACKSIZE); p->state = UNUSED; - cprintf("%x collected %x\n", curproc, p); + cprintf("%x collected %x\n", cp, p); return; } - if(p->state != UNUSED && p->ppid == curproc->pid) + if(p->state != UNUSED && p->ppid == cp->pid) any = 1; } if(any == 0){ - cprintf("%x nothing to wait for\n", curproc); + cprintf("%x nothing to wait for\n", cp); return; } - sleep(curproc); + sleep(cp); } } void syscall() { - int num = curproc->tf->tf_regs.reg_eax; + struct proc *cp = curproc[cpu()]; + int num = cp->tf->tf_regs.reg_eax; - cprintf("%x sys %d\n", curproc, num); + cprintf("%x sys %d\n", cp, num); switch(num){ case SYS_fork: sys_fork(); diff --git a/trap.c b/trap.c index 89c6bf5..33d7be1 100644 --- a/trap.c +++ b/trap.c @@ -29,10 +29,13 @@ void trap(struct Trapframe *tf) { int v = tf->tf_trapno; + + acquire_spinlock(&kernel_lock); // released in trapret in trapasm.S + cprintf("trap %d eip %x:%x\n", tf->tf_trapno, tf->tf_cs, tf->tf_eip); if(v == T_SYSCALL){ - curproc->tf = tf; + curproc[cpu()]->tf = tf; syscall(); return; } diff --git a/trapasm.S b/trapasm.S index 2608328..c0cfd8e 100644 --- a/trapasm.S +++ b/trapasm.S @@ -22,6 +22,8 @@ alltraps: * expects ESP to point to a Trapframe */ trapret: + push $kernel_lock + call release_spinlock popal popl %es popl %ds diff --git a/user1.c b/user1.c new file mode 100644 index 0000000..4fe572e --- /dev/null +++ b/user1.c @@ -0,0 +1,13 @@ +void +fork() +{ + asm("mov $1, %eax"); + asm("int $48"); +} + +main() +{ + fork(); + while(1) + ; +}