]> Devi Nivas Git - cs3210-lab1.git/commitdiff
compile "user programs"
authorrtm <rtm>
Thu, 22 Jun 2006 20:47:23 +0000 (20:47 +0000)
committerrtm <rtm>
Thu, 22 Jun 2006 20:47:23 +0000 (20:47 +0000)
curproc array

Makefile
defs.h
main.c
mp.c
proc.c
proc.h
spinlock.c
syscall.c
trap.c
trapasm.S
user1.c [new file with mode: 0644]

index c3495c0d195931ac487f33e37fb5f902de9271a3..870ea70133f04c657a83ba779fc1f6a8a52371fc 100644 (file)
--- 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 70394bb669931ec4e25c0967aaee7aaff7a30b06..85f3578610ae279ec9aa060dad51d78fb2df2723 100644 (file)
--- 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 5b172976b99cd682812992e3f5ecc65e47929213..206daf39a6347111fbc860cb8ce95d31d2041d11 100644 (file)
--- 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 d3db6979a275c3424b2f875cfd5737308bd4fa02..e797f812ddedba1e06f1d10515ac24b29aa27ec8 100644 (file)
--- 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 82910399b3f156be177467e69daa189c382a1c26..e771c4d0d00f095142f66aa0de13ad8aab13481d 100644 (file)
--- 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 6eba56623b71698dc0f4b10283af1272778ae49a..36e608e95b5efd8646d9ea355f08f0b7360be4ad 100644 (file)
--- 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];
index fa04a27657bf6ac9db0eee096897f1669fdf4a2e..2666842ae3cbd8d6a62c02d250994ed8baaec3f6 100644 (file)
@@ -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");
index 1968c8afaeedb3de1833c90d457d6b07ef716538..48adba887963f4819bad0058fe7a4ccece0d9b64 100644 (file)
--- 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 89c6bf5ddfe1b6e4fd373f279f5278caeab43741..33d7be1b815edd39ee9f1cffe433762f63958cc5 100644 (file)
--- 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;
   }
index 2608328ea6f07fe9c5333cdfd6402c3d76d613db..c0cfd8e0eb6ca125f036eeb2b1f5a45fe8e82566 100644 (file)
--- 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 (file)
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)
+    ;
+}