diff --git a/src/init.s b/src/init.s index b1e3382..9404817 100644 --- a/src/init.s +++ b/src/init.s @@ -1,17 +1,36 @@ +/// initialise a new context +/// arguments: rdi: stack pointer, +/// rsi: function pointer, +/// rdx, data pointer +/// rcx, stack limit + +// switch to the fresh stack xchg %rsp, %rdi +// save the function pointer, data pointer, and stack limit, respectively pushq %rsi pushq %rdx pushq %rcx -call 1f +// save the return address, control flow continues at label 1 +call 1f +// we arrive here once this context is reactivated (see swap.s) + +// restore the stack limit, data pointer, and function pointer, respectively popq %fs:0x70 popq %rdi popq %rax +// initialise the frame pointer movq $$0, %rbp + +// call the function pointer with the data pointer (rdi is the first argument) call *%rax + +// crash if it ever returns ud2 1: + // save our neatly-setup new stack xchg %rsp, %rdi + // back into Rust-land we go diff --git a/src/swap.s b/src/swap.s index 1866b85..01b2e70 100644 --- a/src/swap.s +++ b/src/swap.s @@ -1,17 +1,37 @@ +/// switch to a new context +/// arguments: rdi: stack pointer pointer + +// make sure we leave the red zone alone sub $$128, %rsp + +// save the Rust stack limit and the frame pointer, respectively pushq %fs:0x70 pushq %rbp -call 1f +// save the return address to the stack, control flow continues at label 1 +call 1f +// we arrive here once this context is reactivated + +// restore the frame pointer and the Rust stack limit, respectively popq %rbp popq %fs:0x70 + +// give back the red zone add $$128, %rsp + +// and we merrily go on our way, back into Rust-land jmp 2f 1: + // retrieve the new stack pointer movq (%rdi), %rax + // save the old stack pointer movq %rsp, (%rdi) + // switch to the new stack pointer movq %rax, %rsp + + // jump into the new context (return to the call point) popq %rax jmpq *%rax + 2: