From: Claudio Jeker Subject: Re: boost sparc64 support for context To: ports@openbsd.org Cc: Rafael Sadowski , Brad Smith Date: Tue, 13 Feb 2024 09:03:49 +0100 On Thu, Feb 08, 2024 at 06:50:55PM +0100, Claudio Jeker wrote: > 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 :) I realized that I can save an instruction by using the builtin ADD instruction in 'restore' to set up %o0. So a context switch on sparc64 is now 10 instructions :) I ran test for context, fiber, coroutine and coroutine2 in boost and all test pass. The powerdns_recoursor package built but I'm not sure how to test this properly. IMO this is ready for commit. I will start pushing these changes upstream as well. -- :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 12 Feb 2024 19:12:11 -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 12 Feb 2024 19:12:11 -0000 @@ -0,0 +1,51 @@ +/* + 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 CC64FSZ 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, -CC64FSZ, %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 + + ret + restore %o0, %g0, %o0 + # restore old %sp (pointing to old context-data) in %o0 + # *data stored in %o1 was not modified +.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 12 Feb 2024 19:12:11 -0000 @@ -0,0 +1,68 @@ +/* + 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 CC64FSZ 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, -CC64FSZ, %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 * CC64FSZ, %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 + CC64FSZ + I7] + stx %g0, [%i0 + CC64FSZ + 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, CC64FSZ - BIAS, %l0 + stx %l0, [%i0 + SP] + + # Return context-data which is also includes the BIAS + ret + restore %i0, -BIAS, %o0 + +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 12 Feb 2024 19:12:11 -0000 @@ -0,0 +1,50 @@ +/* + 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 CC64FSZ 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, -CC64FSZ, %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 + + # 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 %o0, %g0, %o0 + # restore old %sp (pointing to old context-data) in %o0 + # *data stored in %o1 was not modified + + 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 12 Feb 2024 19:12:11 -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 + 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 ++ : sysv ++ 64 ++ sparc ++ elf ++ 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 ++ : sysv ++ 64 ++ sparc ++ elf ++ gcc ++ ; ++ + # S390X + # S390X/SYSV/ELF + alias asm_sources