summaryrefslogtreecommitdiff
path: root/coroutine
diff options
context:
space:
mode:
Diffstat (limited to 'coroutine')
-rw-r--r--coroutine/amd64/Context.S42
-rw-r--r--coroutine/amd64/Context.h2
-rw-r--r--coroutine/arm32/Context.S7
-rw-r--r--coroutine/arm32/Context.h2
-rw-r--r--coroutine/arm64/Context.S98
-rw-r--r--coroutine/arm64/Context.asm81
-rw-r--r--coroutine/arm64/Context.h39
-rw-r--r--coroutine/asyncify/Context.h8
-rw-r--r--coroutine/loongarch64/Context.S5
-rw-r--r--coroutine/loongarch64/Context.h2
-rw-r--r--coroutine/ppc/Context.S5
-rw-r--r--coroutine/ppc64/Context.S5
-rw-r--r--coroutine/ppc64le/Context.S28
-rw-r--r--coroutine/ppc64le/Context.h2
-rw-r--r--coroutine/riscv64/Context.S5
-rw-r--r--coroutine/riscv64/Context.h2
-rw-r--r--coroutine/win32/Context.h3
-rw-r--r--coroutine/win64/Context.h5
-rw-r--r--coroutine/x86/Context.S5
-rw-r--r--coroutine/x86/Context.h2
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);