Separate system call path from trap path. Passes usertests on 1 and 2 cpus.
This commit is contained in:
		
							parent
							
								
									f241e67d91
								
							
						
					
					
						commit
						54e6f829e4
					
				
					 8 changed files with 106 additions and 88 deletions
				
			
		
							
								
								
									
										3
									
								
								defs.h
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								defs.h
									
										
									
									
									
								
							|  | @ -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); | ||||
|  |  | |||
							
								
								
									
										9
									
								
								exec.c
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								exec.c
									
										
									
									
									
								
							|  | @ -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; | ||||
|  |  | |||
							
								
								
									
										26
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										26
									
								
								proc.c
									
										
									
									
									
								
							|  | @ -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]) | ||||
|  |  | |||
							
								
								
									
										2
									
								
								proc.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								proc.h
									
										
									
									
									
								
							|  | @ -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
 | ||||
|  |  | |||
							
								
								
									
										35
									
								
								syscall.c
									
										
									
									
									
								
							
							
						
						
									
										35
									
								
								syscall.c
									
										
									
									
									
								
							|  | @ -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; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										10
									
								
								trap.c
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								trap.c
									
										
									
									
									
								
							|  | @ -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){ | ||||
|  |  | |||
							
								
								
									
										82
									
								
								trapasm.S
									
										
									
									
									
								
							
							
						
						
									
										82
									
								
								trapasm.S
									
										
									
									
									
								
							|  | @ -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 %r13 | ||||
|   push %r12 | ||||
|   push %r11 | ||||
|   push %r10 | ||||
|   push %r9 | ||||
|   push %r8 | ||||
|   push %rdi | ||||
|   push %rsi | ||||
|   push %rbp | ||||
|   push %rdx | ||||
|   push %rcx | ||||
|   push %rbx | ||||
|   push %rax | ||||
|   push %rbx	 | ||||
|   push %r12  | ||||
|   push %r13 | ||||
|   push %r14 | ||||
|   push %r15	 | ||||
| 
 | ||||
|   push %r9 | ||||
|   push %r8	 | ||||
|   push %r10 | ||||
|   push %rdx | ||||
|   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 | ||||
| 
 | ||||
|   add $(5*8), %rsp  # discard trapnum, errorcode, rip, cs and rflags | ||||
|   pop %r15 | ||||
|   pop %r14 | ||||
|   pop %r13 | ||||
|   pop %r12 | ||||
|   pop %rbx | ||||
|   pop %rbp | ||||
| 
 | ||||
|   pop %rax | ||||
|   pop %r11 | ||||
|   pop %rcx | ||||
| 
 | ||||
|   mov (%rsp),%rsp  # switch to the user stack | ||||
|   # there are two more values on the stack, but we don't care about them	 | ||||
|   swapgs	 | ||||
|  |  | |||
							
								
								
									
										27
									
								
								x86.h
									
										
									
									
									
								
							
							
						
						
									
										27
									
								
								x86.h
									
										
									
									
									
								
							|  | @ -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
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Frans Kaashoek
						Frans Kaashoek