Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
boost sparc64 support for context
To:
ports@openbsd.org
Date:
Thu, 8 Feb 2024 18:50:55 +0100

Download raw body.

Thread
Since I did most of the work for php I decided to also implement the fiber
/ context ASM for sparc64 in boost.

The difference is that boost has a ontop_fcontext() function which is
not really documented but in the end I figured it out.

I did test this against the tests in boost-context. Will do more tests
tomorrow but maybe someone else wants to join the context party :)
-- 
:wq Claudio

Index: Makefile
===================================================================
RCS file: /cvs/ports/devel/boost/Makefile,v
diff -u -p -r1.142 Makefile
--- Makefile	4 Jan 2024 08:16:16 -0000	1.142
+++ Makefile	8 Feb 2024 16:51:47 -0000
@@ -1,4 +1,4 @@
-NOT_FOR_ARCHS-md = alpha hppa sparc64
+NOT_FOR_ARCHS-md = alpha hppa
 
 DPB_PROPERTIES=	parallel
 
@@ -132,7 +132,7 @@ SUBST_VARS+=	SO_VERSION
 
 # Revert back to Boost::Context 1.80.0 ASM code for i386
 post-extract:
-	cp -f ${FILESDIR}/*_i386_sysv_elf_gas.S ${WRKSRC}/libs/context/src/asm/
+	cp -f ${FILESDIR}/*_sysv_elf_gas.S ${WRKSRC}/libs/context/src/asm/
 
 do-configure:
 	echo "using ${TOOLSET} : : ${CXX} ;" >>${WRKSRC}/tools/build/src/user-config.jam
Index: files/jump_sparc64_sysv_elf_gas.S
===================================================================
RCS file: files/jump_sparc64_sysv_elf_gas.S
diff -N files/jump_sparc64_sysv_elf_gas.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ files/jump_sparc64_sysv_elf_gas.S	8 Feb 2024 16:51:47 -0000
@@ -0,0 +1,53 @@
+/*
+       Copyright Claudio Jeker 2024
+   Distributed under the Boost Software License, Version 1.0.
+      (See accompanying file LICENSE_1_0.txt or copy at
+          http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+/*
+ * typedef void*	fcontext_t;
+ *
+ * struct transfer_t {
+ *	fcontext_t	fctx;
+ *	void	*	data;
+ * };
+ *
+ * transfer_t jump_fcontext(fcontext_t const to, void *vp);
+ */
+#define FRAMESIZE 176
+#define BIAS 2047
+#define SP 128
+#define I7 136
+
+.file "jump_sparc64_sysv_elf_gas.S"
+.text
+.align  4
+.global jump_fcontext
+.type   jump_fcontext, %function
+jump_fcontext:
+	# prepare stack
+	save	%sp, -FRAMESIZE, %sp
+
+	# store framepointer and return address in slots reserved
+	# for arguments
+	stx %fp, [%sp + BIAS + SP]
+	stx %i7, [%sp + BIAS + I7]
+	mov %sp, %o0
+	# force flush register windows to stack and with that save context
+	flushw
+	# get SP (pointing to new context-data) from %i0 param
+	mov %i0, %sp
+	# load framepointer and return address from context
+	ldx [%sp + BIAS + SP], %fp
+	ldx [%sp + BIAS + I7], %i7
+
+	# store old %sp (pointing to old context-data) in %i0 as return
+	# *data stored in %i1 is unmodified
+	mov %o0, %i0
+
+	ret
+	 restore
+.size	jump_fcontext,.-jump_fcontext
+# Mark that we don't need executable stack.
+.section .note.GNU-stack,"",%progbits
Index: files/make_sparc64_sysv_elf_gas.S
===================================================================
RCS file: files/make_sparc64_sysv_elf_gas.S
diff -N files/make_sparc64_sysv_elf_gas.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ files/make_sparc64_sysv_elf_gas.S	8 Feb 2024 16:51:47 -0000
@@ -0,0 +1,69 @@
+/*
+       Copyright Claudio Jeker 2024
+   Distributed under the Boost Software License, Version 1.0.
+      (See accompanying file LICENSE_1_0.txt or copy at
+          http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+/*
+ * fcontext_t *make_fcontext(void *sp, size_t size, void (*fn)(transfer_t));
+ */
+#define FRAMESIZE 176
+#define BIAS 2047
+#define FP 112
+#define SP 128
+#define I7 136
+
+.file "make_sparc64_sysv_elf_gas.S"
+.text
+.align  4
+.global make_fcontext
+.type   make_fcontext, %function
+make_fcontext:
+	save	%sp, -FRAMESIZE, %sp
+
+	# shift address in %i0 (allocated stack) to lower 16 byte boundary
+	and	%i0, -0xf, %i0
+
+	# reserve space for two frames on the stack
+	# the first frame is for the call the second one holds the data
+	# for jump_fcontext
+	sub	%i0, 2 * FRAMESIZE, %i0
+	
+	# third argument of make_fcontext() is the context-function to call
+	# store it in the first stack frame, also clear %fp there to indicate
+	# the end of the stack.
+	stx	%i2, [%i0 + FRAMESIZE + I7]
+	stx	%g0, [%i0 + FRAMESIZE + FP]
+
+	# On OpenBSD stackghost prevents overriding the return address on
+	# a stack frame. So this code uses an extra trampoline to load
+	# to call the context-function and then do the _exit(0) dance.
+	# Extract the full address of the trampoline via pc relative addressing
+1:
+	rd	%pc, %l0
+	add	%l0, (trampoline - 1b - 8), %l0
+	stx	%l0, [%i0 + I7]
+
+	# Save framepointer to first stack frame but first substract the BIAS 
+	add	%i0, FRAMESIZE - BIAS, %l0
+	stx	%l0, [%i0 + SP]
+
+	# Return context-data which is also includes the BIAS
+	sub	%i0, BIAS, %i0
+	ret
+	 restore
+
+trampoline:
+	ldx	[%sp + BIAS + I7], %l0
+
+	# no need to setup transfer_t, already in %o0 and %o1
+	jmpl	%l0, %o7
+	 nop
+
+	call	_exit
+	 clr	%o0
+	unimp
+.size	make_fcontext,.-make_fcontext
+# Mark that we don't need executable stack.
+.section .note.GNU-stack,"",%progbits
Index: files/ontop_sparc64_sysv_elf_gas.S
===================================================================
RCS file: files/ontop_sparc64_sysv_elf_gas.S
diff -N files/ontop_sparc64_sysv_elf_gas.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ files/ontop_sparc64_sysv_elf_gas.S	8 Feb 2024 16:51:47 -0000
@@ -0,0 +1,52 @@
+/*
+       Copyright Claudio Jeker 2024
+   Distributed under the Boost Software License, Version 1.0.
+      (See accompanying file LICENSE_1_0.txt or copy at
+          http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+/*
+ * transfer_t ontop_fcontext(fcontext_t const to, void *vp, transfer_t (*fn)(transfer_t));
+ */
+#define FRAMESIZE 176
+#define BIAS 2047
+#define SP 128
+#define I7 136
+
+.file "ontop_sparc64_sysv_elf_gas.S"
+.text
+.align  4
+.global ontop_fcontext
+.type   ontop_fcontext, %function
+ontop_fcontext:
+	# prepare stack
+	save	%sp, -FRAMESIZE, %sp
+
+	# store framepointer and return address in slots reserved
+	# for arguments
+	stx %fp, [%sp + BIAS + SP]
+	stx %i7, [%sp + BIAS + I7]
+	mov %sp, %o0
+	# force flush register windows to stack and with that save context
+	flushw
+	# get SP (pointing to new context-data) from %i0 param
+	mov %i0, %sp
+	# load framepointer and return address from context
+	ldx [%sp + BIAS + SP], %fp
+	ldx [%sp + BIAS + I7], %i7
+
+	# store old %sp (pointing to old context-data) in %i0 as return
+	# *data stored in %i1 is unmodified
+	mov %o0, %i0
+
+	# ontop_fcontext requires to directly call a function on top of the
+	# current frame so restore register window before doing the jump
+	# to the context function which then is in %o2. Do not clobber
+	# %o7 in the jump so that (*fn)() returns to that address.
+	restore
+	jmpl %o2, %g0
+	 nop
+
+.size	jump_fcontext,.-jump_fcontext
+# Mark that we don't need executable stack.
+.section .note.GNU-stack,"",%progbits
Index: patches/patch-libs_context_build_Jamfile_v2
===================================================================
RCS file: patches/patch-libs_context_build_Jamfile_v2
diff -N patches/patch-libs_context_build_Jamfile_v2
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-libs_context_build_Jamfile_v2	8 Feb 2024 16:51:47 -0000
@@ -0,0 +1,34 @@
+Index: libs/context/build/Jamfile.v2
+--- libs/context/build/Jamfile.v2.orig
++++ libs/context/build/Jamfile.v2
+@@ -508,6 +508,30 @@ alias asm_sources
+      <toolset>gcc
+    ;
+ 
++# SPARC64
++# SPARC64/SYSV/ELF
++alias asm_sources
++   : asm/make_sparc64_sysv_elf_gas.S
++     asm/jump_sparc64_sysv_elf_gas.S
++     asm/ontop_sparc64_sysv_elf_gas.S
++   : <abi>sysv
++     <address-model>64
++     <architecture>sparc
++     <binary-format>elf
++     <toolset>clang
++   ;
++
++alias asm_sources
++   : asm/make_sparc64_sysv_elf_gas.S
++     asm/jump_sparc64_sysv_elf_gas.S
++     asm/ontop_sparc64_sysv_elf_gas.S
++   : <abi>sysv
++     <address-model>64
++     <architecture>sparc
++     <binary-format>elf
++     <toolset>gcc
++   ;
++
+ # S390X
+ # S390X/SYSV/ELF
+ alias asm_sources