1/* 2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "runtime/fibers/arch/asm_macros.h" 17#include "runtime/fibers/arch/amd64/context_layout.h" 18 19.extern abort 20 21LOCAL_FUNCTION_START(FiberExitBridge) 22 // indicate abnormal exit by calling exit(-1) 23 // because fibers should not return from FiberProc 24 // movq $-1, %rax 25 // call exit 26 27 // let's make the exit more violent than exit(-1) for now 28 // TODO(konstanting, #I67QXC): revert to exit() when everything is tested and works 29 call abort@plt 30FUNCTION_END(FiberExitBridge) 31 32 33#define GPR_O(reg) FCTX_GPR_OFFSET_BYTES_ ## reg 34#define FP_O(reg) FCTX_FP_OFFSET_BYTES_ ## reg 35 36/** 37 * arguments: 38 * rdi: uint8_t* ctx_memory 39 * rsi: void (*func)(void*) 40 * rdx: void* argument 41 * rcx: uint8_t* stack 42 * r8: size_t stack_size_bytes 43 */ 44FUNCTION_START(UpdateContext) 45 // context->RIP = func 46 movq %rsi, GPR_O(RIP)(%rdi) 47 // context->RDI = argument 48 movq %rdx, GPR_O(RDI)(%rdi) 49 50 /** 51 * %rax will hold the new RSP value: 52 * NEW_RSP = align((stack + stack_size), 16B) - sizeof(trampoline_ptr) 53 */ 54 55 // %rax = stack + stack_size_bytes 56 movq %rcx, %rax 57 addq %r8, %rax 58 // %rax = align(%rax, 16B) - 8B 59 andq $-16, %rax 60 subq $8, %rax 61 // context->RSP = %rax 62 movq %rax, GPR_O(RSP)(%rdi) 63 // put FiberExitBridge as the return address for the FiberProc 64 leaq FiberExitBridge(%rip), %r10 65 movq %r10, (%rax) 66 67 // return success 68 xorq %rax, %rax 69 ret 70FUNCTION_END(UpdateContext) 71 72/** 73 * arguments: 74 * rdi: uint8_t* ctx_memory 75 * rsi: void (*func)(void*) 76 * rdx: void* argument 77 */ 78FUNCTION_START(UpdateContextKeepStack) 79 // (use %rax, %r10 as temporaries) 80 // %r10 = context->RIP 81 movq GPR_O(RIP)(%rdi), %r10 82 // context->RIP = func 83 movq %rsi, GPR_O(RIP)(%rdi) 84 // context->RDI = argument 85 movq %rdx, GPR_O(RDI)(%rdi) 86 87 // pretend that we called the func(), i.e. push context's RIP to context's stack: 88 // %rax = context->RSP 89 movq GPR_O(RSP)(%rdi), %rax 90 // %rax -= 8 91 subq $8, %rax 92 // M[%rax] = %r10 93 movq (%rax), %r10 94 // context->RSP = %rax 95 movq %rax, GPR_O(RSP)(%rdi) 96 97 // return success 98 xorq %rax, %rax 99 ret 100FUNCTION_END(UpdateContextKeepStack) 101 102#undef GPR_O 103#undef FP_O 104 105// we don't need executable stack. 106.section .note.GNU-stack,"",%progbits