From 668341a56a2da8cac1a821cd2ffae5134a7f15c2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Eduard=20Vintil=C4=83?= Date: Sun, 12 Nov 2023 14:39:57 +0200 Subject: [PATCH] Add goroutine context switch functions for ARM64 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Eduard Vintilă Reviewed-by: Stefan Jumarea Approved-by: Razvan Deaconescu GitHub-Closes: #9 --- libgo/arm64/go-context.S | 119 ++++++++++++++++++ ...d-context-switch-functions-for-ARM64.patch | 41 ++++++ 2 files changed, 160 insertions(+) create mode 100644 libgo/arm64/go-context.S create mode 100644 patches/0003-Add-context-switch-functions-for-ARM64.patch diff --git a/libgo/arm64/go-context.S b/libgo/arm64/go-context.S new file mode 100644 index 0000000..348d24e --- /dev/null +++ b/libgo/arm64/go-context.S @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Goroutine context switch for AArch64 + * + * Authors: Eduard Vintilă + * + * Copyright (c) 2023, University of Bucharest. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + + +#if defined(__ARM_64__) + +/* + * We save the following registers for each Goroutine context switch: + * + * x18 -> platform register + * x19-x28 -> callee saved registers + * x29 -> frame pointer + * x30 -> link register (i.e. return PC) + * sp -> stack pointer + * + * Total: 14 regs + */ + +#define PC_OFF (12*8) +#define SP_OFF (13*8) + +// int __go_getcontext(__go_context_t* context); +// x0 +.globl __go_getcontext +.text +__go_getcontext: + + /* Save GP-regs */ + stp x19, x20, [x0], #0x10 + stp x21, x22, [x0], #0x10 + stp x23, x24, [x0], #0x10 + stp x25, x26, [x0], #0x10 + stp x27, x28, [x0], #0x10 + + /* Save PR and FP */ + stp x18, x29, [x0], #0x10 + + /* Save Return PC and SP */ + mov x1, sp + stp x30, x1, [x0], #0x10 + + ret + +// int __go_setcontext(__go_context_t* context); +// x0 +.globl __go_setcontext +.text +__go_setcontext: + /* Set GP-regs */ + ldp x19, x20, [x0], #0x10 + ldp x21, x22, [x0], #0x10 + ldp x23, x24, [x0], #0x10 + ldp x25, x26, [x0], #0x10 + ldp x27, x28, [x0], #0x10 + + /* Set PR and FP */ + ldp x18, x29, [x0], #0x10 + + /* Set Return PC and SP */ + ldp x30, x1, [x0], #0x10 + mov sp, x1 + + ret + +//void __go_makecontext(__go_context_t* context, void (*)() fn, void* sp, size_t size); +// x0, x1, x2, x3 +.globl __go_makecontext +.text +__go_makecontext: + /* Allocate space for the stack */ + add x4, x2, x3 + + /* Align the stack pointer */ + and x4, x4, #0xfffffffffffffff0 + + /* Store SP and PC in the context structure */ + str x4, [x0, #SP_OFF] + str x1, [x0, #PC_OFF] + + ret + + .section .note.GNU-split-stack,"",@progbits + .section .note.GNU-no-split-stack,"",@progbits + +#endif + + .section .note.GNU-stack,"",@progbits diff --git a/patches/0003-Add-context-switch-functions-for-ARM64.patch b/patches/0003-Add-context-switch-functions-for-ARM64.patch new file mode 100644 index 0000000..c0e3a91 --- /dev/null +++ b/patches/0003-Add-context-switch-functions-for-ARM64.patch @@ -0,0 +1,41 @@ +From 1c50741ef721664dc646b9ef989838f992c59f37 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Eduard=20Vintil=C4=83?= +Date: Wed, 8 Nov 2023 12:39:21 +0200 +Subject: [PATCH] Add context switch functions for ARM64 + +Signed-off-by: Eduard Vintilă + +--- + libgo/runtime/runtime.h | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h +index b3dc4fd24..2598fddf0 100644 +--- a/libgo/runtime/runtime.h ++++ b/libgo/runtime/runtime.h +@@ -491,7 +491,7 @@ bool probestackmaps(void) + extern uint32 __go_runtime_in_callers; + + // Cheaper context switch functions. Currently only defined on +-// Linux/AMD64. ++// Linux/AMD64 and ARM64. + #if defined(__x86_64__) && defined(__linux__) && !defined(__CET__) + typedef struct { + uint64 regs[8]; +@@ -499,6 +499,13 @@ typedef struct { + int __go_getcontext(__go_context_t*); + int __go_setcontext(__go_context_t*); + void __go_makecontext(__go_context_t*, void (*)(), void*, size_t); ++#elif defined(__ARM_64__) ++typedef struct { ++ uint64 regs[14]; ++} __go_context_t; ++int __go_getcontext(__go_context_t*); ++int __go_setcontext(__go_context_t*); ++void __go_makecontext(__go_context_t*, void (*)(), void*, size_t); + #else + #define __go_context_t ucontext_t + #define __go_getcontext(c) getcontext(c) +-- +2.42.0 + -- 2.39.5