diff options
| author | Frans Kaashoek <kaashoek@mit.edu> | 2018-10-09 14:28:54 -0400 | 
|---|---|---|
| committer | Frans Kaashoek <kaashoek@mit.edu> | 2018-10-09 14:28:54 -0400 | 
| commit | 54e6f829e4019e10734588b9ba63c2c186c94f8e (patch) | |
| tree | c4fae7ef568183e9566d69fb6f563c218c12819b | |
| parent | f241e67d911d790376de26698f8bf8ba02550212 (diff) | |
| download | xv6-labs-54e6f829e4019e10734588b9ba63c2c186c94f8e.tar.gz xv6-labs-54e6f829e4019e10734588b9ba63c2c186c94f8e.tar.bz2 xv6-labs-54e6f829e4019e10734588b9ba63c2c186c94f8e.zip | |
Separate system call path from trap path.  Passes usertests on 1 and 2 cpus.
| -rw-r--r-- | defs.h | 3 | ||||
| -rw-r--r-- | exec.c | 9 | ||||
| -rw-r--r-- | proc.c | 26 | ||||
| -rw-r--r-- | proc.h | 2 | ||||
| -rw-r--r-- | syscall.c | 35 | ||||
| -rw-r--r-- | trap.c | 10 | ||||
| -rw-r--r-- | trapasm.S | 78 | ||||
| -rw-r--r-- | x86.h | 27 | 
8 files changed, 104 insertions, 86 deletions
| @@ -9,6 +9,7 @@ struct spinlock;  struct sleeplock;  struct stat;  struct superblock; +struct sysframe;  // bio.c  void            binit(void); @@ -156,7 +157,7 @@ int             argaddr(int, uint64 *);  int             fetchint(uint64, int*);  int             fetchstr(uint64, char**);  int             fetchaddr(uint64, uint64*); -void            syscall(void); +void            syscall(struct sysframe*);  // timer.c  void            timerinit(void); @@ -85,8 +85,8 @@ exec(char *path, char **argv)    ustack[1] = argc;    ustack[2] = sp - (argc+1)*sizeof(uint64);  // argv pointer -  curproc->tf->rdi = argc; -  curproc->tf->rsi = sp - (argc+1)*sizeof(uint64); +  curproc->sf->rdi = argc; +  curproc->sf->rsi = sp - (argc+1)*sizeof(uint64);    sp -= (3+argc+1) * sizeof(uint64);    if(copyout(pgdir, sp, ustack, (3+argc+1)*sizeof(uint64)) < 0) @@ -102,9 +102,8 @@ exec(char *path, char **argv)    oldpgdir = curproc->pgdir;    curproc->pgdir = pgdir;    curproc->sz = sz; -  curproc->tf->rip = elf.entry;  // main -  curproc->tf->rcx = elf.entry; -  curproc->tf->rsp = sp; +  curproc->sf->rcx = elf.entry;  // main +  curproc->sf->rsp = sp;    switchuvm(curproc);    freevm(oldpgdir, oldsz);    return 0; @@ -17,10 +17,8 @@ static struct proc *initproc;  int nextpid = 1;  extern void forkret(void); -// we can return two ways out of the kernel and -// for new processes we can choose either way +// for returning  out of the kernel  extern void sysexit(void); -extern void trapret(void);  static void wakeup1(void *chan); @@ -102,16 +100,16 @@ found:    }    sp = p->kstack + KSTACKSIZE; -  // Leave room for trap frame. -  sp -= sizeof *p->tf; +  // Leave room for syscall frame. +  sp -= sizeof *p->sf;    if ((uint64) sp % 16)      panic("misaligned sp"); -  p->tf = (struct trapframe*)sp; +  p->sf = (struct sysframe*)sp;    // Set up new context to start executing at forkret, -  // which returns to trapret. +  // which returns to sysexit.    sp -= sizeof(uint64);    *(uint64*)sp = (uint64)sysexit; @@ -138,12 +136,10 @@ userinit(void)      panic("userinit: out of memory?");    inituvm(p->pgdir, _binary_initcode_start, (uint64)_binary_initcode_size);    p->sz = PGSIZE; -  memset(p->tf, 0, sizeof(*p->tf)); -  p->tf->cs = SEG_UCODE | DPL_USER; -  p->tf->ss = SEG_UDATA | DPL_USER; -  p->tf->r11 = FL_IF; -  p->tf->rsp = PGSIZE; -  p->tf->rcx = 0;  // beginning of initcode.S +  memset(p->sf, 0, sizeof(*p->sf)); +  p->sf->r11 = FL_IF; +  p->sf->rsp = PGSIZE; +  p->sf->rcx = 0;  // beginning of initcode.S    safestrcpy(p->name, "initcode", sizeof(p->name));    p->cwd = namei("/"); @@ -204,10 +200,10 @@ fork(void)    }    np->sz = curproc->sz;    np->parent = curproc; -  *np->tf = *curproc->tf; +  *np->sf = *curproc->sf;    // Clear %eax so that fork returns 0 in the child. -  np->tf->rax = 0; +  np->sf->rax = 0;    for(i = 0; i < NOFILE; i++)      if(curproc->ofile[i]) @@ -47,7 +47,7 @@ struct proc {    enum procstate state;        // Process state    int pid;                     // Process ID    struct proc *parent;         // Parent process -  struct trapframe *tf;        // Trap frame for current syscall +  struct sysframe *sf;         // Syscall frame for current syscall    struct context *context;     // swtch() here to run process    void *chan;                  // If non-zero, sleeping on chan    int killed;                  // If non-zero, have been killed @@ -62,17 +62,17 @@ fetcharg(int n)    struct proc *curproc = myproc();    switch (n) {    case 0: -    return curproc->tf->rdi; +    return curproc->sf->rdi;    case 1: -    return curproc->tf->rsi; +    return curproc->sf->rsi;    case 2: -    return curproc->tf->rdx; +    return curproc->sf->rdx;    case 3: -    return curproc->tf->r10; +    return curproc->sf->r10;    case 4: -    return curproc->tf->r8; +    return curproc->sf->r8;    case 5: -    return curproc->tf->r9; +    return curproc->sf->r9;    }    panic("fetcharg");    return -1; @@ -169,18 +169,31 @@ static int (*syscalls[])(void) = {  [SYS_close]   sys_close,  }; -void -syscall(void) +static void +dosyscall(void)  {    int num;    struct proc *curproc = myproc(); -  num = curproc->tf->rax; +  num = curproc->sf->rax;    if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { -    curproc->tf->rax = syscalls[num](); +    curproc->sf->rax = syscalls[num]();    } else {      cprintf("%d %s: unknown sys call %d\n",              curproc->pid, curproc->name, num); -    curproc->tf->rax = -1; +    curproc->sf->rax = -1;    }  } + +void +syscall(struct sysframe *sf) +{ +    if(myproc()->killed) +      exit(); +    myproc()->sf = sf; +    dosyscall(); +    if(myproc()->killed) +      exit(); +    return; +} + @@ -41,16 +41,6 @@ idtinit(void)  void  trap(struct trapframe *tf)  { -  if(tf->trapno == T_SYSCALL){ -    if(myproc()->killed) -      exit(); -    myproc()->tf = tf; -    syscall(); -    if(myproc()->killed) -      exit(); -    return; -  } -    switch(tf->trapno){    case T_IRQ0 + IRQ_TIMER:      if(cpuid() == 0){ @@ -25,7 +25,7 @@ alltraps:    push %rbx    push %rax -  cmpw $KCSEG, CSOFF(%rsp)   # compare to saved cs +  cmpw $SEG_KCODE, CSOFF(%rsp)   # compare to saved cs    jz 1f     swapgs @@ -36,7 +36,7 @@ alltraps:  .globl trapret  trapret:    cli -  cmpw $KCSEG, CSOFF(%rsp)  # compare to saved cs +  cmpw $SEG_KCODE, CSOFF(%rsp)  # compare to saved cs    jz 1f    swapgs @@ -58,11 +58,12 @@ trapret:    add $16, %rsp  # discard trapnum and errorcode    iretq +  #PAGEBREAK! -# syscall_entry jumps here after syscall instruction +# syscall jumps here after syscall instruction  .globl sysentry -sysentry:  # Build trap frame. +sysentry:  # Build syscall frame.    // load kernel stack address    swapgs    movq  %rax, %gs:0  // save %rax in syscallno of cpu entry @@ -75,63 +76,54 @@ sysentry:  # Build trap frame.    movq  %rax, %rsp    movq  %gs:0, %rax  // restore rax -  // push usp to make a valid trapframe -  push $(UDSEG|0x3)    push %gs:8 -  // safe eflags and eip -  push %r11 -  push $(UCSEG|0x3)    push %rcx -  // push errno and trapno to make stack look like a trap -  push $0 -  push $64 +  push %r11	 +  push %rax	 -  // push values on kernel stack -  push %r15 -  push %r14 +  push %rbp +  push %rbx	 +  push %r12     push %r13 -  push %r12 -  push %r11 -  push %r10 +  push %r14 +  push %r15	 +    push %r9 -  push %r8 -  push %rdi -  push %rsi -  push %rbp +  push %r8	 +  push %r10    push %rdx -  push %rcx -  push %rbx -  push %rax - +  push %rsi	 +  push %rdi +	    mov  %rsp, %rdi  # frame in arg1 -  call trap -#PAGEBREAK! - -# Return falls through to trapret... +  call syscall +  # fall through to sysexit +	  .globl sysexit  sysexit:    # to make sure we don't get any interrupts on the user stack while in    # supervisor mode.  insufficient?  (see vunerability reports for sysret)    cli -   -  pop %rax -  pop %rbx -  pop %rcx -  pop %rdx -  pop %rbp -  pop %rsi +	    pop %rdi +  pop %rsi +  pop %rdx +  pop %r10    pop %r8    pop %r9 -  pop %r10 -  pop %r11 -  pop %r12 -  pop %r13 -  pop %r14 +    pop %r15 +  pop %r14 +  pop %r13 +  pop %r12 +  pop %rbx +  pop %rbp + +  pop %rax +  pop %r11 +  pop %rcx -  add $(5*8), %rsp  # discard trapnum, errorcode, rip, cs and rflags    mov (%rsp),%rsp  # switch to the user stack    # there are two more values on the stack, but we don't care about them	    swapgs	 @@ -166,6 +166,33 @@ struct trapframe {     uint64 ss;        }__attribute__((packed)); +struct sysframe { +  // arguments +  uint64 rdi; +  uint64 rsi; +  uint64 rdx; +  uint64 r10; +  uint64 r8; +  uint64 r9; +   +  // callee-saved registers +  uint64 r15; +  uint64 r14; +  uint64 r13; +  uint64 r12; +  uint64 rbx; +  uint64 rbp; + +  // return value +  uint64 rax; + +  // syscall registers +  uint64 r11;   // eflags +  uint64 rcx;   // rip +  uint64 rsp; +   +}__attribute__((packed)); +  #endif  #define TF_CS 144 // offset in trapframe for saved cs | 
