summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrans Kaashoek <[email protected]>2018-10-09 14:28:54 -0400
committerFrans Kaashoek <[email protected]>2018-10-09 14:28:54 -0400
commit54e6f829e4019e10734588b9ba63c2c186c94f8e (patch)
treec4fae7ef568183e9566d69fb6f563c218c12819b
parentf241e67d911d790376de26698f8bf8ba02550212 (diff)
downloadxv6-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.h3
-rw-r--r--exec.c9
-rw-r--r--proc.c26
-rw-r--r--proc.h2
-rw-r--r--syscall.c35
-rw-r--r--trap.c10
-rw-r--r--trapasm.S78
-rw-r--r--x86.h27
8 files changed, 104 insertions, 86 deletions
diff --git a/defs.h b/defs.h
index fd9ecb4..763eb75 100644
--- a/defs.h
+++ b/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);
diff --git a/exec.c b/exec.c
index b1a9229..743437a 100644
--- a/exec.c
+++ b/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;
diff --git a/proc.c b/proc.c
index 14c3da8..55e435c 100644
--- a/proc.c
+++ b/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])
diff --git a/proc.h b/proc.h
index e421e44..9261766 100644
--- a/proc.h
+++ b/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
diff --git a/syscall.c b/syscall.c
index 481bde8..b815f28 100644
--- a/syscall.c
+++ b/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;
+}
+
diff --git a/trap.c b/trap.c
index afa0e18..4c58cb2 100644
--- a/trap.c
+++ b/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){
diff --git a/trapasm.S b/trapasm.S
index fc71336..6b6b567 100644
--- a/trapasm.S
+++ b/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 %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
diff --git a/x86.h b/x86.h
index 17bec0d..1ae64ac 100644
--- a/x86.h
+++ b/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