提交 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 {
struct cpu *cpu;
struct proc *proc; // The currently-running process.
struct kmem *kmem; // The per-core memory table
u64 syscallno; // Temporary used by sysentry
} __mpalign__;
extern struct cpu cpus[NCPU];
......
......@@ -26,4 +26,4 @@ void threadhelper(void (*fn)(void *), void *arg);
struct trapframe;
void trap(struct trapframe *tf);
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*);
int fetchstr(char*, const char*, u64);
int fetchmem(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
extern "C" int memcmp(const void*, const void*, size_t);
......
......@@ -79,11 +79,11 @@ argcheckptr(const void *p, int size)
return 0;
}
extern u64 (*syscalls[])(u64, u64, u64, u64, u64);
extern u64 (*syscalls[])(u64, u64, u64, u64, u64, u64);
extern const int nsyscalls;
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 (;;) {
#if EXCEPTIONS
......@@ -92,7 +92,7 @@ syscall(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num)
if(num < nsyscalls && syscalls[num]) {
mtstart(syscalls[num], myproc());
mtrec();
u64 r = syscalls[num](a0, a1, a2, a3, a4);
u64 r = syscalls[num](a0, a1, a2, a3, a4, a5);
mtstop(myproc());
mtign();
return r;
......
......@@ -20,7 +20,7 @@ struct intdesc idt[256] __attribute__((aligned(16)));
extern u64 trapentry[];
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();
......@@ -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));
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) {
mtstart(trap, myproc());
......
......@@ -21,14 +21,13 @@
/* Calling convention:
*
* Syscall #: %rax
* Arguments: %rdi, %rsi, %rdx, %r10 (*), %r8
* Arguments: %rdi, %rsi, %rdx, %r10 (*), %r8, %r9
* Return RIP: %rcx (from syscall instruction)
* RFLAGS: %r11 (from syscall instruction)
* Clobbers: %r9, everything above
*
* None of the above registers are preserved across function calls in
* 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.
* Normally, the fourth argument is in %rcx, but this is clobbered by
......@@ -41,21 +40,21 @@ sysentry:
// can syscall/sysret be used safely in the presence of NMIs?
// we are executing with cpl=0 but without a valid stack.
// blow away %r9: syscalls can take at most 5 args
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
addq $(KSTACKSIZE-TRAPFRAME_SIZE), %r9
movq %ss:PROC_KSTACK_OFFSET(%rax), %rax
addq $(KSTACKSIZE-TRAPFRAME_SIZE), %rax
// save all registers we're not allowed to clobber
// skip padding3, ds
movq %r15, %ss:0x10(%r9)
movq %r14, %ss:0x18(%r9)
movq %r13, %ss:0x20(%r9)
movq %r12, %ss:0x28(%r9)
movq %rbp, %ss:0x30(%r9)
movq %rbx, %ss:0x38(%r9)
movq %r15, %ss:0x10(%rax)
movq %r14, %ss:0x18(%rax)
movq %r13, %ss:0x20(%rax)
movq %r12, %ss:0x28(%rax)
movq %rbp, %ss:0x30(%rax)
movq %rbx, %ss:0x38(%rax)
// skip r11 (0x40)
// skip r10 (0x48)
// skip r9 (0x50)
......@@ -67,20 +66,21 @@ sysentry:
// skip rdi (0x80)
// skip trapno (0x88)
// 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)
movq %r11, %ss:0xa8(%r9) // eflags saved by syscall
movq %rsp, %ss:0xb0(%r9)
movq %r11, %ss:0xa8(%rax) // eflags saved by syscall
movq %rsp, %ss:0xb0(%rax)
movw $KDSEG, %cx
movw %cx, %ds
movw %cx, %es
movq %r9, %rsp
movq %rax, %rsp
movq %r10, %rcx // saved by usys.S
movq %rax, %r9 // syscall# from usys.S
pushq %gs:24 // syscall# saved from %rax
call sysentry_c
popq %r11
// return using SYSRET
cli
......
......@@ -34,13 +34,13 @@ def main():
", ".join(syscall.kargs))
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)
for num in range(max(bynum.keys()) + 1):
if num not in bynum:
print " nullptr,"
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 "extern const int nsyscalls = %d;" % (max(bynum.keys()) + 1)
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论