diff options
| -rw-r--r-- | Makefile | 5 | ||||
| -rw-r--r-- | Notes | 1 | ||||
| -rw-r--r-- | defs.h | 16 | ||||
| -rw-r--r-- | main.c | 33 | ||||
| -rw-r--r-- | proc.c | 35 | ||||
| -rw-r--r-- | proc.h | 1 | ||||
| -rw-r--r-- | string.c | 3 | ||||
| -rw-r--r-- | syscall.c | 50 | ||||
| -rw-r--r-- | syscall.h | 2 | ||||
| -rw-r--r-- | trap.c | 30 | ||||
| -rw-r--r-- | trapasm.S | 1 | ||||
| -rw-r--r-- | traps.h | 26 | 
12 files changed, 166 insertions, 37 deletions
| @@ -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 @@ -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 @@ -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); @@ -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;  } @@ -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? @@ -32,3 +32,4 @@ struct proc{  };  extern struct proc proc[]; +extern struct proc *curproc; @@ -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 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 index 0000000..3155dbd --- /dev/null +++ b/syscall.h @@ -0,0 +1,2 @@ +#define SYS_fork 1 +#define SYS_exit 2 @@ -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  } @@ -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 @@ -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 | 
