Update the syscall interface

This commit is contained in:
zongmin.gu 2020-08-10 17:56:59 +08:00 committed by tate.thl
parent 120d7334fd
commit c67bdd9a23
2 changed files with 32 additions and 34 deletions

@ -42,6 +42,12 @@ void do_exit_task(void);
/* Override the field for stack guard */ /* Override the field for stack guard */
#define TD_TASK_OFFSET TD_STACKGUARD_OFFSET #define TD_TASK_OFFSET TD_STACKGUARD_OFFSET
/* Big enough offset, which is not overlap with SDK */
/*In SGX SDK the GS register point to thread_data_t structure and a whole page is
assigned to the structure. So any offset larger than sizeof(thread_data_t) and
less than 4096 is unused by anyone. We can use it.*/
#define TD_SYSCALL_RET_ADDR_OFFSET 0x40
#define TASK_KERNEL_RSP (8 * 0) #define TASK_KERNEL_RSP (8 * 0)
#define TASK_KERNEL_STACK_BASE (8 * 1) #define TASK_KERNEL_STACK_BASE (8 * 1)
#define TASK_KERNEL_STACK_LIMIT (8 * 2) #define TASK_KERNEL_STACK_LIMIT (8 * 2)

@ -13,25 +13,29 @@ __occlum_syscall_linux_abi:
// arg3 - %r10 // arg3 - %r10
// arg4 - %r8 // arg4 - %r8
// arg5 - *r9 // arg5 - *r9
// return address - *(%rsp) // return address - %rcx
push %rbp // Save rsp in r11
movq %rsp, %rbp // r11 is used to store RFLAGS. Since the FLAGS is not changed before pushfq,
// The return address is now in 8(%rbp). // r11 is used to save original rsp.
// The original %rbp is now in (%rbp). movq %rsp, %r11
// The original %rsp is now in %rbp + 8.
// Get current task
movq %gs:(TD_TASK_OFFSET), %rsp
// Switch to the kernel stack
movq TASK_KERNEL_RSP(%rsp), %rsp
// Save the target CPU state when `call __occlum_syscall` is returned in // Save the target CPU state when `call __occlum_syscall` is returned in
// a CpuContext struct. The registers are saved in the reverse order of // a CpuContext struct. The registers are saved in the reverse order of
// the fields in CpuContext. // the fields in CpuContext.
pushfq pushfq
push 8(%rbp) // save %rip push %rcx // save %rip
push %rbp // save %rsp, but not the final value, to be adjusted later push %r11 // save %rsp
push %rcx push %rcx
push %rax push %rax
push %rdx push %rdx
push %rbx push %rbx
push (%rbp) // save %rbp push %rbp
push %rsi push %rsi
push %rdi push %rdi
push %r15 push %r15
@ -44,13 +48,10 @@ __occlum_syscall_linux_abi:
push %r8 push %r8
// Make %rdi points to CpuContext. // Make %rdi points to CpuContext.
mov %rsp, %rdi mov %rsp, %rdi
// The target %rsp is actuall the saved one plus 16
addq $16, (15*8)(%rdi)
// Get current task // Get current task
movq %gs:(TD_TASK_OFFSET), %r12 movq %gs:(TD_TASK_OFFSET), %r12
// Switch to the kernel stack
movq TASK_KERNEL_RSP(%r12), %rsp
// Switch to the kernel TLS by setting fsbase. Different implementation for HW and SIM modes. // Switch to the kernel TLS by setting fsbase. Different implementation for HW and SIM modes.
#if SGX_MODE_SIM #if SGX_MODE_SIM
pushq %rdi pushq %rdi
@ -67,6 +68,10 @@ __occlum_syscall_linux_abi:
wrfsbase %r11 wrfsbase %r11
#endif #endif
// Keep the stack 16 bytes alignment
and $-16, %rsp
// Do syscall
call occlum_syscall call occlum_syscall
// This should never happen! // This should never happen!
@ -79,23 +84,6 @@ __occlum_sysret:
// Arguments: // Arguments:
// %rdi - user_context: &mut CpuContext // %rdi - user_context: &mut CpuContext
// Jumping back to the user space itself is easy, but not so easy when
// we need to set all other registers to some specified values. To overcome
// this difficulty, the most obvious choice is using a ret instruction, which
// can set %rip and %rsp at the same time. So we must set -8(%rsp) to the
// value of the target %rip before ret, where %rsp has the value of target
// %rsp.
//
// But there is a catch: it is dangerous to modify the value at -8(%rsp),
// which may still be used by the user space (remember red zone and
// signal handler?). So we need to use a stack location outside the
// 128-byte red zone. So in this function, we store the target %rip value
// in $-136(%rsp) and do `ret 128` at the end of this function.
subq $136, (15*8)(%rdi)
movq (15*8)(%rdi), %r11
movq (16*8)(%rdi), %r12
movq %r12, (%r11)
// Get current task // Get current task
movq %gs:(TD_TASK_OFFSET), %r12 movq %gs:(TD_TASK_OFFSET), %r12
// Switch to the user TLS. Different implementation for HW and SIM modes. // Switch to the user TLS. Different implementation for HW and SIM modes.
@ -115,6 +103,10 @@ __occlum_sysret:
leaq (17*8)(%rdi), %rsp leaq (17*8)(%rdi), %rsp
popfq popfq
// Restore the return address
movq (16*8)(%rdi), %rcx //save the return address in %rcx
movq %rcx, %gs:(TD_SYSCALL_RET_ADDR_OFFSET)
// Make %rsp points to the CPU context // Make %rsp points to the CPU context
mov %rdi, %rsp mov %rdi, %rsp
// Restore the CPU context of the user space // Restore the CPU context of the user space
@ -134,9 +126,7 @@ __occlum_sysret:
pop %rax pop %rax
pop %rcx pop %rcx
pop %rsp pop %rsp
// Continue executing the user code jmp *%gs:(TD_SYSCALL_RET_ADDR_OFFSET)
ret $128
.global __occlum_syscall_c_abi .global __occlum_syscall_c_abi
.type __occlum_syscall_c_abi, @function .type __occlum_syscall_c_abi, @function
@ -148,5 +138,7 @@ __occlum_syscall_c_abi:
movq %r8,%r10 movq %r8,%r10
movq %r9,%r8 movq %r9,%r8
movq 8(%rsp),%r9 movq 8(%rsp),%r9
call __occlum_syscall_linux_abi lea syscall_return(%rip), %rcx
jmp __occlum_syscall_linux_abi
syscall_return:
ret ret