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