提交 7f3e124e 创建 作者: Austin Clements's avatar Austin Clements

Support six argument syscalls

This fixes the syscall path so it no longer clobbers %r9, which means we can use it as the 6th function argument, following the AMD64 ABI. We still need a scratch register, but we now get that by stashing away %rax (the syscall number) in a per-CPU variable, making it available for use.
上级 3f3247c5
...@@ -26,6 +26,7 @@ struct cpu { ...@@ -26,6 +26,7 @@ struct cpu {
struct cpu *cpu; struct cpu *cpu;
struct proc *proc; // The currently-running process. struct proc *proc; // The currently-running process.
struct kmem *kmem; // The per-core memory table struct kmem *kmem; // The per-core memory table
u64 syscallno; // Temporary used by sysentry
} __mpalign__; } __mpalign__;
extern struct cpu cpus[NCPU]; extern struct cpu cpus[NCPU];
......
...@@ -26,4 +26,4 @@ void threadhelper(void (*fn)(void *), void *arg); ...@@ -26,4 +26,4 @@ void threadhelper(void (*fn)(void *), void *arg);
struct trapframe; struct trapframe;
void trap(struct trapframe *tf); void trap(struct trapframe *tf);
void sysentry(void); void sysentry(void);
u64 sysentry_c(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num); u64 sysentry_c(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 num);
...@@ -217,7 +217,7 @@ int fetchint64(uptr, u64*); ...@@ -217,7 +217,7 @@ int fetchint64(uptr, u64*);
int fetchstr(char*, const char*, u64); int fetchstr(char*, const char*, u64);
int fetchmem(void*, const void*, u64); int fetchmem(void*, const void*, u64);
int putmem(void*, const void*, u64); int putmem(void*, const void*, u64);
u64 syscall(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num); u64 syscall(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 num);
// string.c // string.c
extern "C" int memcmp(const void*, const void*, size_t); extern "C" int memcmp(const void*, const void*, size_t);
......
...@@ -79,11 +79,11 @@ argcheckptr(const void *p, int size) ...@@ -79,11 +79,11 @@ argcheckptr(const void *p, int size)
return 0; return 0;
} }
extern u64 (*syscalls[])(u64, u64, u64, u64, u64); extern u64 (*syscalls[])(u64, u64, u64, u64, u64, u64);
extern const int nsyscalls; extern const int nsyscalls;
u64 u64
syscall(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num) syscall(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 num)
{ {
for (;;) { for (;;) {
#if EXCEPTIONS #if EXCEPTIONS
...@@ -92,7 +92,7 @@ syscall(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num) ...@@ -92,7 +92,7 @@ syscall(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num)
if(num < nsyscalls && syscalls[num]) { if(num < nsyscalls && syscalls[num]) {
mtstart(syscalls[num], myproc()); mtstart(syscalls[num], myproc());
mtrec(); mtrec();
u64 r = syscalls[num](a0, a1, a2, a3, a4); u64 r = syscalls[num](a0, a1, a2, a3, a4, a5);
mtstop(myproc()); mtstop(myproc());
mtign(); mtign();
return r; return r;
......
...@@ -20,7 +20,7 @@ struct intdesc idt[256] __attribute__((aligned(16))); ...@@ -20,7 +20,7 @@ struct intdesc idt[256] __attribute__((aligned(16)));
extern u64 trapentry[]; extern u64 trapentry[];
u64 u64
sysentry_c(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num) sysentry_c(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 num)
{ {
sti(); sti();
...@@ -31,7 +31,7 @@ sysentry_c(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num) ...@@ -31,7 +31,7 @@ sysentry_c(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num)
trapframe *tf = (trapframe*) (myproc()->kstack + KSTACKSIZE - sizeof(*tf)); trapframe *tf = (trapframe*) (myproc()->kstack + KSTACKSIZE - sizeof(*tf));
myproc()->tf = tf; myproc()->tf = tf;
u64 r = syscall(a0, a1, a2, a3, a4, num); u64 r = syscall(a0, a1, a2, a3, a4, a5, num);
if(myproc()->killed) { if(myproc()->killed) {
mtstart(trap, myproc()); mtstart(trap, myproc());
......
...@@ -21,14 +21,13 @@ ...@@ -21,14 +21,13 @@
/* Calling convention: /* Calling convention:
* *
* Syscall #: %rax * Syscall #: %rax
* Arguments: %rdi, %rsi, %rdx, %r10 (*), %r8 * Arguments: %rdi, %rsi, %rdx, %r10 (*), %r8, %r9
* Return RIP: %rcx (from syscall instruction) * Return RIP: %rcx (from syscall instruction)
* RFLAGS: %r11 (from syscall instruction) * RFLAGS: %r11 (from syscall instruction)
* Clobbers: %r9, everything above
* *
* None of the above registers are preserved across function calls in * None of the above registers are preserved across function calls in
* the AMD64 ABI. This means user space doesn't need to save any * the AMD64 ABI. This means user space doesn't need to save any
* registers across a syscall. * registers across a syscall and we're free to clobber them.
* *
* (*) This argument register differs from the regular AMD64 ABI. * (*) This argument register differs from the regular AMD64 ABI.
* Normally, the fourth argument is in %rcx, but this is clobbered by * Normally, the fourth argument is in %rcx, but this is clobbered by
...@@ -41,21 +40,21 @@ sysentry: ...@@ -41,21 +40,21 @@ sysentry:
// can syscall/sysret be used safely in the presence of NMIs? // can syscall/sysret be used safely in the presence of NMIs?
// we are executing with cpl=0 but without a valid stack. // we are executing with cpl=0 but without a valid stack.
// blow away %r9: syscalls can take at most 5 args
swapgs swapgs
movq %gs:8, %r9 // myproc() movq %rax, %gs:24 // save %rax so we can use it
movq %gs:8, %rax // myproc()
movq %ss:PROC_KSTACK_OFFSET(%r9), %r9 movq %ss:PROC_KSTACK_OFFSET(%rax), %rax
addq $(KSTACKSIZE-TRAPFRAME_SIZE), %r9 addq $(KSTACKSIZE-TRAPFRAME_SIZE), %rax
// save all registers we're not allowed to clobber // save all registers we're not allowed to clobber
// skip padding3, ds // skip padding3, ds
movq %r15, %ss:0x10(%r9) movq %r15, %ss:0x10(%rax)
movq %r14, %ss:0x18(%r9) movq %r14, %ss:0x18(%rax)
movq %r13, %ss:0x20(%r9) movq %r13, %ss:0x20(%rax)
movq %r12, %ss:0x28(%r9) movq %r12, %ss:0x28(%rax)
movq %rbp, %ss:0x30(%r9) movq %rbp, %ss:0x30(%rax)
movq %rbx, %ss:0x38(%r9) movq %rbx, %ss:0x38(%rax)
// skip r11 (0x40) // skip r11 (0x40)
// skip r10 (0x48) // skip r10 (0x48)
// skip r9 (0x50) // skip r9 (0x50)
...@@ -67,20 +66,21 @@ sysentry: ...@@ -67,20 +66,21 @@ sysentry:
// skip rdi (0x80) // skip rdi (0x80)
// skip trapno (0x88) // skip trapno (0x88)
// skip err, padding2 (0x90) // skip err, padding2 (0x90)
movq %rcx, %ss:0x98(%r9) // rip saved by syscall movq %rcx, %ss:0x98(%rax) // rip saved by syscall
// skip cs, padding (0xa0) // skip cs, padding (0xa0)
movq %r11, %ss:0xa8(%r9) // eflags saved by syscall movq %r11, %ss:0xa8(%rax) // eflags saved by syscall
movq %rsp, %ss:0xb0(%r9) movq %rsp, %ss:0xb0(%rax)
movw $KDSEG, %cx movw $KDSEG, %cx
movw %cx, %ds movw %cx, %ds
movw %cx, %es movw %cx, %es
movq %r9, %rsp movq %rax, %rsp
movq %r10, %rcx // saved by usys.S movq %r10, %rcx // saved by usys.S
movq %rax, %r9 // syscall# from usys.S pushq %gs:24 // syscall# saved from %rax
call sysentry_c call sysentry_c
popq %r11
// return using SYSRET // return using SYSRET
cli cli
......
...@@ -34,13 +34,13 @@ def main(): ...@@ -34,13 +34,13 @@ def main():
", ".join(syscall.kargs)) ", ".join(syscall.kargs))
print print
print "u64 (*syscalls[])(u64, u64, u64, u64, u64) = {" print "u64 (*syscalls[])(u64, u64, u64, u64, u64, u64) = {"
bynum = dict((s.num, s) for s in syscalls) bynum = dict((s.num, s) for s in syscalls)
for num in range(max(bynum.keys()) + 1): for num in range(max(bynum.keys()) + 1):
if num not in bynum: if num not in bynum:
print " nullptr," print " nullptr,"
else: else:
print " (u64(*)(u64,u64,u64,u64,u64))%s," % bynum[num].kname print " (u64(*)(u64,u64,u64,u64,u64,u64))%s," % bynum[num].kname
print "};" print "};"
print print
print "extern const int nsyscalls = %d;" % (max(bynum.keys()) + 1) print "extern const int nsyscalls = %d;" % (max(bynum.keys()) + 1)
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论