]> Devi Nivas Git - cs3210-lab0.git/commitdiff
primitive fork and exit system calls
authorrtm <rtm>
Thu, 15 Jun 2006 16:02:20 +0000 (16:02 +0000)
committerrtm <rtm>
Thu, 15 Jun 2006 16:02:20 +0000 (16:02 +0000)
12 files changed:
Makefile
Notes
defs.h
main.c
proc.c
proc.h
string.c
syscall.c [new file with mode: 0644]
syscall.h [new file with mode: 0644]
trap.c
trapasm.S
traps.h [new file with mode: 0644]

index 22636ea13af12bbc926adfc1a6cecc14af11fb50..2a8c3ce93b8457ce46af9db2ef9f7eb0e50120e9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,11 @@
-OBJS = main.o console.o string.o kalloc.o proc.o trapasm.o trap.o vectors.o
+OBJS = main.o console.o string.o kalloc.o proc.o trapasm.o trap.o vectors.o \
+       syscall.o
 
 CC = i386-jos-elf-gcc
 LD = i386-jos-elf-ld
 OBJCOPY = i386-jos-elf-objcopy
 OBJDUMP = i386-jos-elf-objdump
-CFLAGS = -nostdinc -I. -O
+CFLAGS = -nostdinc -I. -O -Wall
 
 xv6.img : bootblock kernel
        dd if=/dev/zero of=xv6.img count=10000
diff --git a/Notes b/Notes
index 4c06e746963a7592396c3e67ccf9e00d67359b3d..06a969656109b6c5159f98637502fa04c2d09b35 100644 (file)
--- a/Notes
+++ b/Notes
@@ -40,6 +40,7 @@ one segment array per cpu, or per process?
 
 pass curproc explicitly, or implicit from cpu #?
   e.g. argument to newproc()?
+  hmm, you need a global curproc[cpu] for trap() &c
 
 test stack expansion
 test running out of memory, process slots
diff --git a/defs.h b/defs.h
index ec41bfea830456cd6946476e1926ae9426f7f187..ad51167444d20dd6ae2a4af84abd99b426c75a8d 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -1,6 +1,7 @@
 // kalloc.c
 char *kalloc(int n);
 void kfree(char *cp, int len);
+void kinit(void);
 
 // console.c
 void cprintf(char *fmt, ...);
@@ -8,5 +9,16 @@ void panic(char *s);
 
 // proc.c
 struct proc;
-void setupsegs(struct proc *p);
-struct proc * newproc(struct proc *op);
+void setupsegs(struct proc *);
+struct proc * newproc(void);
+void swtch(void);
+
+// trap.c
+void tinit(void);
+
+// string.c
+void * memcpy(void *dst, void *src, unsigned n);
+void * memset(void *dst, int c, unsigned n);
+
+// syscall.c
+void syscall(void);
diff --git a/main.c b/main.c
index 3c75389316f52717a35e9663d177900b549ee8c5..6b07d836fa2642cf77d4b8b849650f341418c3c7 100644 (file)
--- a/main.c
+++ b/main.c
@@ -4,12 +4,16 @@
 #include "proc.h"
 #include "defs.h"
 #include "x86.h"
+#include "traps.h"
+#include "syscall.h"
 
 extern char edata[], end[];
 
+int
 main()
 {
   struct proc *p;
+  int i;
   
   // clear BSS
   memset(edata, 0, end - edata);
@@ -27,6 +31,7 @@ main()
 
   // create fake process zero
   p = &proc[0];
+  curproc = p;
   p->state = WAITING;
   p->sz = PAGE;
   p->mem = kalloc(p->sz);
@@ -39,14 +44,28 @@ main()
   p->tf->tf_eflags = FL_IF;
   setupsegs(p);
 
-  p = newproc(&proc[0]);
-  // xxx copy instructions to p->mem
-  p->mem[0] = 0x90; // nop 
-  p->mem[1] = 0x90; // nop 
-  p->mem[2] = 0x42; // inc %edx
-  p->mem[3] = 0x42; // inc %edx
+  p = newproc();
+
+  i = 0;
+  p->mem[i++] = 0x90; // nop 
+  p->mem[i++] = 0xb8; // mov ..., %eax
+  p->mem[i++] = SYS_fork;
+  p->mem[i++] = 0;
+  p->mem[i++] = 0;
+  p->mem[i++] = 0;
+  p->mem[i++] = 0xcd; // int
+  p->mem[i++] = T_SYSCALL;
+  p->mem[i++] = 0xb8; // mov ..., %eax
+  p->mem[i++] = SYS_exit;
+  p->mem[i++] = 0;
+  p->mem[i++] = 0;
+  p->mem[i++] = 0;
+  p->mem[i++] = 0xcd; // int
+  p->mem[i++] = T_SYSCALL;
   p->tf->tf_eip = 0;
   p->tf->tf_esp = p->sz;
 
-  swtch(&proc[0]);
+  swtch();
+
+  return 0;
 }
diff --git a/proc.c b/proc.c
index 2b43237ae8bac13bffafdbe6774b1e0b736775eb..1e90e37a46f612692e35564478a8675c173c4b50 100644 (file)
--- a/proc.c
+++ b/proc.c
@@ -6,6 +6,7 @@
 #include "defs.h"
 
 struct proc proc[NPROC];
+struct proc *curproc;
 
 /*
  * set up a process's task state and segment descriptors
@@ -25,7 +26,8 @@ setupsegs(struct proc *p)
   p->gdt[0] = SEG_NULL;
   p->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0);
   p->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
-  p->gdt[SEG_TSS] = SEG16(STS_T32A, (unsigned) &p->ts, sizeof(p->ts), 0);
+  p->gdt[SEG_TSS] = SEG16(STS_T32A, (unsigned) &p->ts,
+                                sizeof(p->ts), 0);
   p->gdt[SEG_TSS].sd_s = 0;
   p->gdt[SEG_UCODE] = SEG(STA_X|STA_R, (unsigned)p->mem, p->sz, 3);
   p->gdt[SEG_UDATA] = SEG(STA_W, (unsigned)p->mem, p->sz, 3);
@@ -41,7 +43,7 @@ extern void trapret();
  * sets up the stack to return as if from system call.
  */
 struct proc *
-newproc(struct proc *op)
+newproc()
 {
   struct proc *np;
   unsigned *sp;
@@ -52,29 +54,30 @@ newproc(struct proc *op)
   if(np >= &proc[NPROC])
     return 0;
 
-  np->sz = op->sz;
-  np->mem = kalloc(op->sz);
+  np->sz = curproc->sz;
+  np->mem = kalloc(curproc->sz);
   if(np->mem == 0)
     return 0;
-  memcpy(np->mem, op->mem, np->sz);
+  memcpy(np->mem, curproc->mem, np->sz);
   np->kstack = kalloc(KSTACKSIZE);
   if(np->kstack == 0){
-    kfree(np->mem, op->sz);
+    kfree(np->mem, curproc->sz);
     return 0;
   }
-  np->tf = (struct Trapframe *) (np->kstack + KSTACKSIZE - sizeof(struct Trapframe));
   setupsegs(np);
-  np->state = RUNNABLE;
   
   // set up kernel stack to return to user space
-  *(np->tf) = *(op->tf);
+  np->tf = (struct Trapframe *) (np->kstack + KSTACKSIZE - sizeof(struct Trapframe));
+  *(np->tf) = *(curproc->tf);
   sp = (unsigned *) np->tf;
   *(--sp) = (unsigned) &trapret;  // for return from swtch()
   *(--sp) = 0;  // previous bp for leave in swtch()
   np->esp = (unsigned) sp;
   np->ebp = (unsigned) sp;
 
-  cprintf("newproc esp %x ebp %x mem %x\n", np->esp, np->ebp, np->mem);
+  np->state = RUNNABLE;
+
+  cprintf("newproc %x\n", np);
 
   return np;
 }
@@ -83,12 +86,12 @@ newproc(struct proc *op)
  * find a runnable process and switch to it.
  */
 void
-swtch(struct proc *op)
+swtch()
 {
   struct proc *np;
   
   while(1){
-    for(np = op + 1; np != op; np++){
+    for(np = curproc + 1; np != curproc; np++){
       if(np == &proc[NPROC])
         np = &proc[0];
       if(np->state == RUNNABLE)
@@ -99,10 +102,12 @@ swtch(struct proc *op)
     // idle...
   }
   
-  op->ebp = read_ebp();
-  op->esp = read_esp();
+  curproc->ebp = read_ebp();
+  curproc->esp = read_esp();
+
+  cprintf("swtch %x -> %x\n", curproc, np);
 
-  cprintf("switching\n");
+  curproc = np;
 
   // XXX callee-saved registers?
 
diff --git a/proc.h b/proc.h
index e5c230c02ffacf55f8b5f8c41f105ad5accfa4c7..39e1c494bdacb4043d0de236c9bdea9d9b4d0fb8 100644 (file)
--- a/proc.h
+++ b/proc.h
@@ -32,3 +32,4 @@ struct proc{
 };
 
 extern struct proc proc[];
+extern struct proc *curproc;
index aef42424abbbc471d07d8daea09afb661a8c38ce..f27b025fa8fb492605780becb659de9b639d7b1b 100644 (file)
--- a/string.c
+++ b/string.c
@@ -1,3 +1,6 @@
+#include "types.h"
+#include "defs.h"
+
 void *
 memcpy(void *dst, void *src, unsigned n)
 {
diff --git a/syscall.c b/syscall.c
new file mode 100644 (file)
index 0000000..9cb20dc
--- /dev/null
+++ b/syscall.c
@@ -0,0 +1,50 @@
+#include "types.h"
+#include "param.h"
+#include "mmu.h"
+#include "proc.h"
+#include "defs.h"
+#include "x86.h"
+#include "traps.h"
+#include "syscall.h"
+
+/*
+ * User code makes a system call with INT T_SYSCALL.
+ * System call number in %eax.
+ * Arguments on the stack.
+ *
+ * Return value? Error indication? Errno?
+ */
+
+void
+sys_fork()
+{
+  newproc();
+}
+
+void
+sys_exit()
+{
+  curproc->state = UNUSED;
+  // XXX free resources. notify parent. abandon children.
+  swtch();
+}
+
+void
+syscall()
+{
+  int num = curproc->tf->tf_regs.reg_eax;
+
+  cprintf("%x sys %d\n", curproc, num);
+  switch(num){
+  case SYS_fork:
+    sys_fork();
+    break;
+  case SYS_exit:
+    sys_exit();
+    break;
+  default:
+    cprintf("unknown sys call %d\n", num);
+    // XXX fault
+    break;
+  }
+}
diff --git a/syscall.h b/syscall.h
new file mode 100644 (file)
index 0000000..3155dbd
--- /dev/null
+++ b/syscall.h
@@ -0,0 +1,2 @@
+#define SYS_fork 1
+#define SYS_exit 2
diff --git a/trap.c b/trap.c
index ace4c95fe7d1bea9d224885cf3fa0aafd6f06e30..89c6bf5ddfe1b6e4fd373f279f5278caeab43741 100644 (file)
--- a/trap.c
+++ b/trap.c
@@ -4,6 +4,7 @@
 #include "proc.h"
 #include "defs.h"
 #include "x86.h"
+#include "traps.h"
 
 struct Gatedesc idt[256];
 struct Pseudodesc idt_pd = { 0, sizeof(idt) - 1, (unsigned) &idt };
@@ -12,29 +13,36 @@ extern unsigned vectors[]; /* vectors.S, array of 256 entry point addresses */
 extern void trapenter();
 extern void trapenter1();
 
-
-int xx;
-
 void
 tinit()
 {
   int i;
 
-  xx = 0;
   for(i = 0; i < 256; i++){
-    SETGATE(idt[i], 1, SEG_KCODE << 3, vectors[i], 3);
+    SETGATE(idt[i], 1, SEG_KCODE << 3, vectors[i], 0);
   }
+  SETGATE(idt[T_SYSCALL], T_SYSCALL, SEG_KCODE << 3, vectors[48], 3);
   asm volatile("lidt %0" : : "g" (idt_pd.pd_lim));
 }
 
 void
 trap(struct Trapframe *tf)
 {
-  /* which process are we running? */
-  if(xx < 10)
-    cprintf("%d\n", tf->tf_trapno);
-  xx++;
-  //while(1)
-  //;
+  int v = tf->tf_trapno;
+  cprintf("trap %d eip %x:%x\n", tf->tf_trapno, tf->tf_cs, tf->tf_eip);
+
+  if(v == T_SYSCALL){
+    curproc->tf = tf;
+    syscall();
+    return;
+  }
+
+  if(v == 32){
+    // probably clock
+    return;
+  }
+
+  while(1)
+    ;
   // XXX probably ought to lgdt on trap return
 }
index c75ab39d6568fe64693b19ea68c155550b186bba..c01cec029834c07d84b9923d768ba5b089fa8196 100644 (file)
--- a/trapasm.S
+++ b/trapasm.S
@@ -13,6 +13,7 @@ alltraps:
         movw %ax,%es        #  segments
         pushl %esp      # pass pointer to this trapframe
         call    trap        #  and call trap()
+        addl $4, %esp
         # return falls through to trapret...
         
         .globl trapret
diff --git a/traps.h b/traps.h
new file mode 100644 (file)
index 0000000..a81903c
--- /dev/null
+++ b/traps.h
@@ -0,0 +1,26 @@
+// system defined:
+#define T_DIVIDE     0         // divide error
+#define T_DEBUG      1         // debug exception
+#define T_NMI        2         // non-maskable interrupt
+#define T_BRKPT      3         // breakpoint
+#define T_OFLOW      4         // overflow
+#define T_BOUND      5         // bounds check
+#define T_ILLOP      6         // illegal opcode
+#define T_DEVICE     7         // device not available 
+#define T_DBLFLT     8         // double fault
+/* #define T_COPROC  9 */      // reserved (not generated by recent processors)
+#define T_TSS       10         // invalid task switch segment
+#define T_SEGNP     11         // segment not present
+#define T_STACK     12         // stack exception
+#define T_GPFLT     13         // genernal protection fault
+#define T_PGFLT     14         // page fault
+/* #define T_RES    15 */      // reserved
+#define T_FPERR     16         // floating point error
+#define T_ALIGN     17         // aligment check
+#define T_MCHK      18         // machine check
+#define T_SIMDERR   19         // SIMD floating point error
+
+// These are arbitrarily chosen, but with care not to overlap
+// processor defined exceptions or interrupt vectors.
+#define T_SYSCALL   48         // system call
+#define T_DEFAULT   500                // catchall