diff options
Diffstat (limited to 'coroutine')
| -rw-r--r-- | coroutine/amd64/Context.S | 42 | ||||
| -rw-r--r-- | coroutine/amd64/Context.h | 2 | ||||
| -rw-r--r-- | coroutine/arm32/Context.S | 7 | ||||
| -rw-r--r-- | coroutine/arm32/Context.h | 2 | ||||
| -rw-r--r-- | coroutine/arm64/Context.S | 98 | ||||
| -rw-r--r-- | coroutine/arm64/Context.asm | 81 | ||||
| -rw-r--r-- | coroutine/arm64/Context.h | 39 | ||||
| -rw-r--r-- | coroutine/asyncify/Context.h | 8 | ||||
| -rw-r--r-- | coroutine/loongarch64/Context.S | 5 | ||||
| -rw-r--r-- | coroutine/loongarch64/Context.h | 2 | ||||
| -rw-r--r-- | coroutine/ppc/Context.S | 5 | ||||
| -rw-r--r-- | coroutine/ppc64/Context.S | 5 | ||||
| -rw-r--r-- | coroutine/ppc64le/Context.S | 28 | ||||
| -rw-r--r-- | coroutine/ppc64le/Context.h | 2 | ||||
| -rw-r--r-- | coroutine/riscv64/Context.S | 5 | ||||
| -rw-r--r-- | coroutine/riscv64/Context.h | 2 | ||||
| -rw-r--r-- | coroutine/win32/Context.h | 3 | ||||
| -rw-r--r-- | coroutine/win64/Context.h | 5 | ||||
| -rw-r--r-- | coroutine/x86/Context.S | 5 | ||||
| -rw-r--r-- | coroutine/x86/Context.h | 2 |
20 files changed, 269 insertions, 79 deletions
diff --git a/coroutine/amd64/Context.S b/coroutine/amd64/Context.S index 056c276a31..4b94d31f30 100644 --- a/coroutine/amd64/Context.S +++ b/coroutine/amd64/Context.S @@ -5,13 +5,21 @@ ## Copyright, 2018, by Samuel Williams. ## +/* Important - do _not_ include <cet.h> in this file; doing so will + * cause an incorrect .note.gnu.property section to be emitted. We have + * one at the bottom of this file */ + #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .text -.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +.globl PREFIXED_SYMBOL(coroutine_transfer) +PREFIXED_SYMBOL(coroutine_transfer): + +#if defined(__CET__) && (__CET__ & 0x01) != 0 + /* IBT landing pad */ + endbr64 +#endif # Make space on the stack for 6 registers: subq $48, %rsp @@ -50,3 +58,31 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): #if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__) .section .note.GNU-stack,"",%progbits #endif + +#if defined(__ELF__) + +#if defined(__CET__) && (__CET__ & 0x01) != 0 +# define IBT_FLAG 0x01 +#else +# define IBT_FLAG 0x00 +#endif + +/* We do _NOT_ support CET shadow-stack. Do _not_ add the property for + * this to the Context.o object. If you require CET shadow-stack support, + * for now, consider building with --with-coroutine=ucontext */ +#define SHSTK_FLAG 0x00 + +.pushsection .note.gnu.property, "a" +.p2align 3 +.long 0x4 /* Name size ("GNU\0") */ +.long 0x10 /* Descriptor size */ +.long 0x5 /* Type: NT_GNU_PROPERTY_TYPE_0 */ +.asciz "GNU" /* Name */ +# Begin descriptor +.long 0xc0000002 /* Property type: GNU_PROPERTY_X86_FEATURE_1_AND */ +.long 0x4 /* Property size */ +.long (IBT_FLAG | SHSTK_FLAG) +.long 0x0 /* 8-byte alignment padding */ +/* End descriptor */ +.popsection +#endif diff --git a/coroutine/amd64/Context.h b/coroutine/amd64/Context.h index 44daa4e01a..65aa638304 100644 --- a/coroutine/amd64/Context.h +++ b/coroutine/amd64/Context.h @@ -69,7 +69,7 @@ static inline void coroutine_initialize( context->stack_pointer = (void**)((uintptr_t)top & ~0xF); *--context->stack_pointer = NULL; - *--context->stack_pointer = (void*)start; + *--context->stack_pointer = (void*)(uintptr_t)start; context->stack_pointer -= COROUTINE_REGISTERS; memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); diff --git a/coroutine/arm32/Context.S b/coroutine/arm32/Context.S index 1850c4c408..945e4f82d5 100644 --- a/coroutine/arm32/Context.S +++ b/coroutine/arm32/Context.S @@ -6,16 +6,15 @@ ## #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .file "Context.S" .text -.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) +.globl PREFIXED_SYMBOL(coroutine_transfer) .align 2 -.type PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer),%function +.type PREFIXED_SYMBOL(coroutine_transfer),%function .syntax unified -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +PREFIXED_SYMBOL(coroutine_transfer): # Save caller state (8 registers + return address) push {r4-r11,lr} diff --git a/coroutine/arm32/Context.h b/coroutine/arm32/Context.h index 09410eb25d..7529dd2efc 100644 --- a/coroutine/arm32/Context.h +++ b/coroutine/arm32/Context.h @@ -44,7 +44,7 @@ static inline void coroutine_initialize( char * top = (char*)stack + size; context->stack_pointer = (void**)((uintptr_t)top & ~0xF); - *--context->stack_pointer = (void*)start; + *--context->stack_pointer = (void*)(uintptr_t)start; context->stack_pointer -= COROUTINE_REGISTERS; memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); diff --git a/coroutine/arm64/Context.S b/coroutine/arm64/Context.S index eeb0f774a3..ce219c0c4d 100644 --- a/coroutine/arm64/Context.S +++ b/coroutine/arm64/Context.S @@ -6,7 +6,6 @@ ## #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) #if defined(__APPLE__) #define x29 fp @@ -18,37 +17,63 @@ .align 2 #endif +#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT & 0x02) != 0 +# error "-mbranch-protection flag specified b-key but Context.S does not support this" +#endif + +#if defined(_WIN32) +## Add more space for certain TEB values on each stack +#define TEB_OFFSET 0x20 +#else +#define TEB_OFFSET 0x00 +#endif + ## NOTE(PAC): Use we HINT mnemonics instead of PAC mnemonics to ## keep compatibility with those assemblers that don't support PAC. ## ## See "Providing protection for complex software" for more details about PAC/BTI ## https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software -.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +.global PREFIXED_SYMBOL(coroutine_transfer) +PREFIXED_SYMBOL(coroutine_transfer): #if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0) # paciasp (it also acts as BTI landing pad, so no need to insert BTI also) hint #25 #elif defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT != 0) - # For the the case PAC is not enabled but BTI is. + # For the case PAC is not enabled but BTI is. # bti c hint #34 #endif # Make space on the stack for caller registers - sub sp, sp, 0xa0 + sub sp, sp, 0xa0 + TEB_OFFSET # Save caller registers - stp d8, d9, [sp, 0x00] - stp d10, d11, [sp, 0x10] - stp d12, d13, [sp, 0x20] - stp d14, d15, [sp, 0x30] - stp x19, x20, [sp, 0x40] - stp x21, x22, [sp, 0x50] - stp x23, x24, [sp, 0x60] - stp x25, x26, [sp, 0x70] - stp x27, x28, [sp, 0x80] - stp x29, x30, [sp, 0x90] + stp d8, d9, [sp, 0x00 + TEB_OFFSET] + stp d10, d11, [sp, 0x10 + TEB_OFFSET] + stp d12, d13, [sp, 0x20 + TEB_OFFSET] + stp d14, d15, [sp, 0x30 + TEB_OFFSET] + stp x19, x20, [sp, 0x40 + TEB_OFFSET] + stp x21, x22, [sp, 0x50 + TEB_OFFSET] + stp x23, x24, [sp, 0x60 + TEB_OFFSET] + stp x25, x26, [sp, 0x70 + TEB_OFFSET] + stp x27, x28, [sp, 0x80 + TEB_OFFSET] + stp x29, x30, [sp, 0x90 + TEB_OFFSET] + +#if defined(_WIN32) + # Save certain values from Thread Environment Block (TEB) + # x18 points to the TEB on Windows + # Read TeStackBase and TeStackLimit at ksarm64.h from TEB + ldp x5, x6, [x18, #0x08] + # Save them + stp x5, x6, [sp, #0x00] + # Read TeDeallocationStack at ksarm64.h from TEB + ldr x5, [x18, #0x1478] + # Read TeFiberData at ksarm64.h from TEB + ldr x6, [x18, #0x20] + # Save current fiber data and deallocation stack + stp x5, x6, [sp, #0x10] +#endif # Save stack pointer to x0 (first argument) mov x2, sp @@ -58,20 +83,33 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): ldr x3, [x1, 0] mov sp, x3 +#if defined(_WIN32) + # Restore stack base and limit + ldp x5, x6, [sp, #0x00] + # Write TeStackBase and TeStackLimit at ksarm64.h to TEB + stp x5, x6, [x18, #0x08] + # Restore fiber data and deallocation stack + ldp x5, x6, [sp, #0x10] + # Write TeDeallocationStack at ksarm64.h to TEB + str x5, [x18, #0x1478] + # Write TeFiberData at ksarm64.h to TEB + str x6, [x18, #0x20] +#endif + # Restore caller registers - ldp d8, d9, [sp, 0x00] - ldp d10, d11, [sp, 0x10] - ldp d12, d13, [sp, 0x20] - ldp d14, d15, [sp, 0x30] - ldp x19, x20, [sp, 0x40] - ldp x21, x22, [sp, 0x50] - ldp x23, x24, [sp, 0x60] - ldp x25, x26, [sp, 0x70] - ldp x27, x28, [sp, 0x80] - ldp x29, x30, [sp, 0x90] + ldp d8, d9, [sp, 0x00 + TEB_OFFSET] + ldp d10, d11, [sp, 0x10 + TEB_OFFSET] + ldp d12, d13, [sp, 0x20 + TEB_OFFSET] + ldp d14, d15, [sp, 0x30 + TEB_OFFSET] + ldp x19, x20, [sp, 0x40 + TEB_OFFSET] + ldp x21, x22, [sp, 0x50 + TEB_OFFSET] + ldp x23, x24, [sp, 0x60 + TEB_OFFSET] + ldp x25, x26, [sp, 0x70 + TEB_OFFSET] + ldp x27, x28, [sp, 0x80 + TEB_OFFSET] + ldp x29, x30, [sp, 0x90 + TEB_OFFSET] # Pop stack frame - add sp, sp, 0xa0 + add sp, sp, 0xa0 + TEB_OFFSET #if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0) # autiasp: Authenticate x30 (LR) with SP and key A @@ -85,18 +123,19 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): .section .note.GNU-stack,"",%progbits #endif -#if __ARM_FEATURE_BTI_DEFAULT != 0 || __ARM_FEATURE_PAC_DEFAULT != 0 +#if (defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT != 0) || (defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT != 0) +#if defined(__ELF__) /* See "ELF for the Arm 64-bit Architecture (AArch64)" https://github.com/ARM-software/abi-aa/blob/2023Q3/aaelf64/aaelf64.rst#program-property */ # define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1<<0) # define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1<<1) -# if __ARM_FEATURE_BTI_DEFAULT != 0 +# if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT != 0 # define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI # else # define BTI_FLAG 0 # endif -# if __ARM_FEATURE_PAC_DEFAULT != 0 +# if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT != 0 # define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC # else # define PAC_FLAG 0 @@ -118,3 +157,4 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): # End descriptor .popsection #endif +#endif diff --git a/coroutine/arm64/Context.asm b/coroutine/arm64/Context.asm new file mode 100644 index 0000000000..866fa628e7 --- /dev/null +++ b/coroutine/arm64/Context.asm @@ -0,0 +1,81 @@ + TTL coroutine/arm64/Context.asm + + AREA |.drectve|, DRECTVE + + EXPORT |coroutine_transfer| + + AREA |.text$mn|, CODE, ARM64 + +;; Add more space for certain TEB values on each stack +TEB_OFFSET EQU 0x20 + +;; Incomplete implementation +coroutine_transfer PROC + ; Make space on the stack for caller registers + sub sp, sp, 0xa0 + TEB_OFFSET + + ; Save caller registers + stp d8, d9, [sp, 0x00 + TEB_OFFSET] + stp d10, d11, [sp, 0x10 + TEB_OFFSET] + stp d12, d13, [sp, 0x20 + TEB_OFFSET] + stp d14, d15, [sp, 0x30 + TEB_OFFSET] + stp x19, x20, [sp, 0x40 + TEB_OFFSET] + stp x21, x22, [sp, 0x50 + TEB_OFFSET] + stp x23, x24, [sp, 0x60 + TEB_OFFSET] + stp x25, x26, [sp, 0x70 + TEB_OFFSET] + stp x27, x28, [sp, 0x80 + TEB_OFFSET] + stp x29, x30, [sp, 0x90 + TEB_OFFSET] + + ;; Save certain values from Thread Environment Block (TEB) x18 + ;; points to the TEB on Windows + ;; Read TeStackBase and TeStackLimit at ksarm64.h from TEB + ldp x5, x6, [x18, #0x08] + ;; Save them + stp x5, x6, [sp, #0x00] + ;; Read TeDeallocationStack at ksarm64.h from TEB + ldr x5, [x18, #0x1478] + ;; Read TeFiberData at ksarm64.h from TEB + ldr x6, [x18, #0x20] + ;; Save current fiber data and deallocation stack + stp x5, x6, [sp, #0x10] + + ; Save stack pointer to x0 (first argument) + mov x2, sp + str x2, [x0, 0] + + ; Load stack pointer from x1 (second argument) + ldr x3, [x1, 0] + mov sp, x3 + + ;; Restore stack base and limit + ldp x5, x6, [sp, #0x00] + ;; Write TeStackBase and TeStackLimit at ksarm64.h to TEB + stp x5, x6, [x18, #0x08] + ;; Restore fiber data and deallocation stack + ldp x5, x6, [sp, #0x10] + ;; Write TeDeallocationStack at ksarm64.h to TEB + str x5, [x18, #0x1478] + ;; Write TeFiberData at ksarm64.h to TEB + str x6, [x18, #0x20] + + ; Restore caller registers + ldp d8, d9, [sp, 0x00 + TEB_OFFSET] + ldp d10, d11, [sp, 0x10 + TEB_OFFSET] + ldp d12, d13, [sp, 0x20 + TEB_OFFSET] + ldp d14, d15, [sp, 0x30 + TEB_OFFSET] + ldp x19, x20, [sp, 0x40 + TEB_OFFSET] + ldp x21, x22, [sp, 0x50 + TEB_OFFSET] + ldp x23, x24, [sp, 0x60 + TEB_OFFSET] + ldp x25, x26, [sp, 0x70 + TEB_OFFSET] + ldp x27, x28, [sp, 0x80 + TEB_OFFSET] + ldp x29, x30, [sp, 0x90 + TEB_OFFSET] + + ; Pop stack frame + add sp, sp, 0xa0 + TEB_OFFSET + + ; Jump to return address (in x30) + ret + + endp + + end diff --git a/coroutine/arm64/Context.h b/coroutine/arm64/Context.h index 1819fa5be9..468e4155b2 100644 --- a/coroutine/arm64/Context.h +++ b/coroutine/arm64/Context.h @@ -15,9 +15,21 @@ #include <stdint.h> #include <string.h> +#if defined __GNUC__ #define COROUTINE __attribute__((noreturn)) void +#define COROUTINE_DECL COROUTINE +#elif defined _MSC_VER +#define COROUTINE __declspec(noreturn) void +#define COROUTINE_DECL void +#endif + +#if defined(_WIN32) +#define TEB_OFFSET 0x20 +#else +#define TEB_OFFSET 0x00 +#endif -enum {COROUTINE_REGISTERS = 0xa0 / 8}; +enum {COROUTINE_REGISTERS = (0xa0 + TEB_OFFSET) / 8}; #if defined(__SANITIZE_ADDRESS__) #define COROUTINE_SANITIZE_ADDRESS @@ -44,28 +56,25 @@ struct coroutine_context #endif }; -typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); +typedef COROUTINE_DECL(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); static inline void coroutine_initialize_main(struct coroutine_context * context) { context->stack_pointer = NULL; } -#if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT != 0 -// Sign the given instruction address with the given modifier and key A static inline void *ptrauth_sign_instruction_addr(void *addr, void *modifier) { +#if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT != 0 + // Sign the given instruction address with the given modifier and key A register void *r17 __asm("r17") = addr; register void *r16 __asm("r16") = modifier; // Use HINT mnemonic instead of PACIA1716 for compatibility with older assemblers. - asm ("hint #8;" : "+r"(r17) : "r"(r16)); + __asm ("hint #8;" : "+r"(r17) : "r"(r16)); addr = r17; - return addr; -} #else -// No-op if PAC is not enabled -static inline void *ptrauth_sign_instruction_addr(void *addr, void *modifier) { + // No-op if PAC is not enabled +#endif return addr; } -#endif static inline void coroutine_initialize( struct coroutine_context *context, @@ -89,7 +98,15 @@ static inline void coroutine_initialize( context->stack_pointer -= COROUTINE_REGISTERS; memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); - context->stack_pointer[0x98 / 8] = ptrauth_sign_instruction_addr((void*)start, (void*)top); + void *addr = (void*)(uintptr_t)start; + context->stack_pointer[(0x98 + TEB_OFFSET) / 8] = ptrauth_sign_instruction_addr(addr, (void*)top); +#if defined(_WIN32) + // save top address of stack as base in TEB + context->stack_pointer[0x00 / 8] = (char*)stack + size; + // save botton address of stack as limit and deallocation stack in TEB + context->stack_pointer[0x08 / 8] = stack; + context->stack_pointer[0x10 / 8] = stack; +#endif } struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target); diff --git a/coroutine/asyncify/Context.h b/coroutine/asyncify/Context.h index 7dba829a1d..71791a4004 100644 --- a/coroutine/asyncify/Context.h +++ b/coroutine/asyncify/Context.h @@ -13,6 +13,7 @@ #include <stddef.h> #include <stdio.h> +#include <stdint.h> #include "wasm/asyncify.h" #include "wasm/machine.h" #include "wasm/fiber.h" @@ -47,10 +48,13 @@ static inline void coroutine_initialize_main(struct coroutine_context * context) static inline void coroutine_initialize(struct coroutine_context *context, coroutine_start start, void *stack, size_t size) { - if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] entry (context = %p, stack = %p ... %p)\n", __func__, context, stack, (char *)stack + size); + // Linear stack pointer must be always aligned down to 16 bytes. + // https://github.com/WebAssembly/tool-conventions/blob/c74267a5897c1bdc9aa60adeaf41816387d3cd12/BasicCABI.md#the-linear-stack + uintptr_t sp = ((uintptr_t)stack + size) & ~0xF; + if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] entry (context = %p, stack = %p ... %p)\n", __func__, context, stack, (char *)sp); rb_wasm_init_context(&context->fc, coroutine_trampoline, start, context); // record the initial stack pointer position to restore it after resumption - context->current_sp = (char *)stack + size; + context->current_sp = (char *)sp; context->stack_base = stack; context->size = size; } diff --git a/coroutine/loongarch64/Context.S b/coroutine/loongarch64/Context.S index 662f5dfb6c..6e10cd032b 100644 --- a/coroutine/loongarch64/Context.S +++ b/coroutine/loongarch64/Context.S @@ -1,11 +1,10 @@ #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .text .align 2 -.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +.global PREFIXED_SYMBOL(coroutine_transfer) +PREFIXED_SYMBOL(coroutine_transfer): # Make space on the stack for caller registers addi.d $sp, $sp, -0xa0 diff --git a/coroutine/loongarch64/Context.h b/coroutine/loongarch64/Context.h index 668c9a965e..82b85b36e9 100644 --- a/coroutine/loongarch64/Context.h +++ b/coroutine/loongarch64/Context.h @@ -36,7 +36,7 @@ static inline void coroutine_initialize( context->stack_pointer -= COROUTINE_REGISTERS; memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); - context->stack_pointer[0x90 / 8] = (void*)start; + context->stack_pointer[0x90 / 8] = (void*)(uintptr_t)start; } struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target); diff --git a/coroutine/ppc/Context.S b/coroutine/ppc/Context.S index e2431a9250..f44b2419b4 100644 --- a/coroutine/ppc/Context.S +++ b/coroutine/ppc/Context.S @@ -9,15 +9,14 @@ ; To add support for AIX, *BSD or *Linux, please make separate implementations. #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .machine ppc7400 ; = G4, Rosetta .text -.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) +.globl PREFIXED_SYMBOL(coroutine_transfer) .align 2 -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +PREFIXED_SYMBOL(coroutine_transfer): ; Make space on the stack for caller registers ; (Should we rather use red zone? See libphobos example.) subi r1,r1,80 diff --git a/coroutine/ppc64/Context.S b/coroutine/ppc64/Context.S index f8561e0e7d..20a47c61c6 100644 --- a/coroutine/ppc64/Context.S +++ b/coroutine/ppc64/Context.S @@ -8,15 +8,14 @@ ; To add support for AIX, *BSD or *Linux, please make separate implementations. #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .machine ppc64 ; = G5 .text -.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) +.globl PREFIXED_SYMBOL(coroutine_transfer) .align 2 -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +PREFIXED_SYMBOL(coroutine_transfer): ; Make space on the stack for caller registers ; (Should we rather use red zone? See libphobos example.) subi r1,r1,160 diff --git a/coroutine/ppc64le/Context.S b/coroutine/ppc64le/Context.S index 61be9efcf0..819264c245 100644 --- a/coroutine/ppc64le/Context.S +++ b/coroutine/ppc64le/Context.S @@ -1,14 +1,20 @@ #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) +.abiversion 2 .text .align 2 -.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) -.type PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer), @function -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +.globl PREFIXED_SYMBOL(coroutine_transfer) +.type PREFIXED_SYMBOL(coroutine_transfer), @function +PREFIXED_SYMBOL(coroutine_transfer): + # Global entry: set up TOC pointer (r2) from r12. + # Required by ELFv2 ABI when this function is reached via the PLT. + addis 2, 12, .TOC. - PREFIXED_SYMBOL(coroutine_transfer)@ha + addi 2, 2, .TOC. - PREFIXED_SYMBOL(coroutine_transfer)@l + .localentry PREFIXED_SYMBOL(coroutine_transfer), .-PREFIXED_SYMBOL(coroutine_transfer) + # Make space on the stack for caller registers - addi 1,1,-152 + addi 1,1,-160 # Save caller registers std 14,0(1) @@ -34,6 +40,10 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): mflr 0 std 0,144(1) + # Save caller special register + mfcr 0 + std 0, 152(1) + # Save stack pointer to first argument std 1,0(3) @@ -64,8 +74,14 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): ld 0,144(1) mtlr 0 + # Load special registers + ld 0,152(1) + # Restore cr register cr2, cr3 and cr4 (field index 3,4,5) + # (field index is 1-based, field 1 = cr0) using a mask (32|16|8 = 56) + mtcrf 56,0 + # Pop stack frame - addi 1,1,152 + addi 1,1,160 # Jump to return address blr diff --git a/coroutine/ppc64le/Context.h b/coroutine/ppc64le/Context.h index fbfaa2ee63..63ea9f19ff 100644 --- a/coroutine/ppc64le/Context.h +++ b/coroutine/ppc64le/Context.h @@ -12,7 +12,7 @@ enum { COROUTINE_REGISTERS = - 19 /* 18 general purpose registers (r14-r31) and 1 return address */ + 20 /* 18 general purpose registers (r14-r31), 1 special register (cr) and 1 return address */ + 4 /* space for fiber_entry() to store the link register */ }; diff --git a/coroutine/riscv64/Context.S b/coroutine/riscv64/Context.S index cc4e872f84..8e7fc74ffc 100644 --- a/coroutine/riscv64/Context.S +++ b/coroutine/riscv64/Context.S @@ -1,11 +1,10 @@ #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .text .align 2 -.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +.global PREFIXED_SYMBOL(coroutine_transfer) +PREFIXED_SYMBOL(coroutine_transfer): # Make space on the stack for caller registers addi sp, sp, -0xd0 diff --git a/coroutine/riscv64/Context.h b/coroutine/riscv64/Context.h index 9ce1140e0b..3660fb5577 100644 --- a/coroutine/riscv64/Context.h +++ b/coroutine/riscv64/Context.h @@ -36,7 +36,7 @@ static inline void coroutine_initialize( context->stack_pointer -= COROUTINE_REGISTERS; memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); - context->stack_pointer[0xc0 / 8] = (void*)start; + context->stack_pointer[0xc0 / 8] = (void*)(uintptr_t)start; } struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target); diff --git a/coroutine/win32/Context.h b/coroutine/win32/Context.h index 902fd1246f..c1c8fbcd13 100644 --- a/coroutine/win32/Context.h +++ b/coroutine/win32/Context.h @@ -16,6 +16,7 @@ #include <string.h> #define COROUTINE __declspec(noreturn) void __fastcall +#define COROUTINE_DECL void __fastcall #define COROUTINE_LIMITED_ADDRESS_SPACE /* This doesn't include thread information block */ @@ -45,7 +46,7 @@ static inline void coroutine_initialize( char * top = (char*)stack + size; context->stack_pointer = (void**)((uintptr_t)top & ~0xF); - *--context->stack_pointer = (void*)start; + *--context->stack_pointer = (void*)(uintptr_t)start; /* Windows Thread Information Block */ *--context->stack_pointer = (void*)0xFFFFFFFF; /* fs:[0] */ diff --git a/coroutine/win64/Context.h b/coroutine/win64/Context.h index aaa4caeaf9..23b21b5c1c 100644 --- a/coroutine/win64/Context.h +++ b/coroutine/win64/Context.h @@ -16,6 +16,7 @@ #include <string.h> #define COROUTINE __declspec(noreturn) void +#define COROUTINE_DECL void enum { COROUTINE_REGISTERS = 8, @@ -30,7 +31,7 @@ struct coroutine_context typedef void(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); -void coroutine_trampoline(); +void coroutine_trampoline(void); static inline void coroutine_initialize_main(struct coroutine_context * context) { context->stack_pointer = NULL; @@ -53,7 +54,7 @@ static inline void coroutine_initialize( /* Return address */ *--context->stack_pointer = 0; - *--context->stack_pointer = (void*)start; + *--context->stack_pointer = (void*)(uintptr_t)start; *--context->stack_pointer = (void*)coroutine_trampoline; /* Windows Thread Information Block */ diff --git a/coroutine/x86/Context.S b/coroutine/x86/Context.S index f06a417084..b04e71aa1c 100644 --- a/coroutine/x86/Context.S +++ b/coroutine/x86/Context.S @@ -6,12 +6,11 @@ ## #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .text -.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +.globl PREFIXED_SYMBOL(coroutine_transfer) +PREFIXED_SYMBOL(coroutine_transfer): # Save caller registers pushl %ebp diff --git a/coroutine/x86/Context.h b/coroutine/x86/Context.h index d98eaf6486..f33b338eab 100644 --- a/coroutine/x86/Context.h +++ b/coroutine/x86/Context.h @@ -45,7 +45,7 @@ static inline void coroutine_initialize( context->stack_pointer = (void**)((uintptr_t)top & ~0xF); *--context->stack_pointer = NULL; - *--context->stack_pointer = (void*)start; + *--context->stack_pointer = (void*)(uintptr_t)start; context->stack_pointer -= COROUTINE_REGISTERS; memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); |
