From patchwork Fri Jun 17 03:32:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Filippov X-Patchwork-Id: 1644662 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=UbyUuqtl; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=uclibc-ng.org (client-ip=89.238.66.15; helo=helium.openadk.org; envelope-from=devel-bounces@uclibc-ng.org; receiver=) Received: from helium.openadk.org (helium.openadk.org [89.238.66.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4LPPlW48D7z9s75 for ; Fri, 17 Jun 2022 13:33:41 +1000 (AEST) Received: from helium.openadk.org (localhost [IPv6:::1]) by helium.openadk.org (Postfix) with ESMTP id EF97D31E0552; Fri, 17 Jun 2022 05:33:28 +0200 (CEST) Authentication-Results: helium.openadk.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=UbyUuqtl; dkim-atps=neutral Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) by helium.openadk.org (Postfix) with ESMTPS id EDEF831E0438 for ; Fri, 17 Jun 2022 05:32:37 +0200 (CEST) Received: by mail-pl1-f181.google.com with SMTP id t2so2828679pld.4 for ; Thu, 16 Jun 2022 20:32:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=MRteOKY4KIyhnJm5uMqXn20wXV9xYQdHbNPUiF20xzI=; b=UbyUuqtleCEogmr5Rz7rdYdEBwt5f11PeiwpKDa4jSsK2HC/GA5sCk/PcMi4fQKQMt n7p2L4Hy3+s6WSubWlaI/fIICk1DOFsZvBzrOd/md5wEn3Y+FkSt7hHhKGFhOzeVVJGA YSJ5OTJBIO12lRL9XLKZ3P1FCvH8Pl105DjiEQq46ipQQNAH0olfp3zSDNhsr19Ej5UO JJ4NeYjOp6g/DXk00mkSyRJ3cR5j+buzRwH4oCyVNN8zavdkq41OhKm25cGNvPgDEmzr FriN8H22hlx8ddPS4dIq1Lr95GFAK+gEx+GKpFDtv+ynzKeuodg3mHrywiA6XoJvjiUJ WD/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=MRteOKY4KIyhnJm5uMqXn20wXV9xYQdHbNPUiF20xzI=; b=rCT+RuB8MPEzGnHfIbtiF96ZHWkqGSPFiZyf5GcCYq+E8HcjK3JJ/1b/0YYbfsZDAI D8NY3+KPSoOl5SMEdPaHI6q7Qp0MaReH9B42X1eNw9pd4GMO/H6CGn0kQbGesH5ViCqD iKIs7YhttBKXShaSLaDCzRTed7wx07MXBXdH5lTQGXqY1YzGBvojQZq31iCoB5cWr95Z mp2FmF/pKP9ujPZAYeMhio0b5PHj3xgFap4bOKSczLw+VIc9Oi3193c0X6XTMbw6TMBd ctoLqEXQgdLLeRYJz0KpHvDKoWs00WMGZqeJ46GAZVEhvp8y4iy8aCOK2YtKeAR97Ij/ sqgg== X-Gm-Message-State: AJIora8K7iKlq9gZCjzFxBbtJFjlp2zesZQlJgurE2yQdQ7jldjBd/YX KvbCt7oyjQkVVvS0Qew/yTjTY+zBoMO49Q== X-Google-Smtp-Source: AGRyM1tDeRDirZ7GCoG7N4TMKaRS1wsWonsusgqS3S9C89QYNztdjBBi0Jd5WFhX7+aP1jkd+ba28g== X-Received: by 2002:a17:902:f549:b0:167:77aa:d3da with SMTP id h9-20020a170902f54900b0016777aad3damr7578360plf.97.1655436755230; Thu, 16 Jun 2022 20:32:35 -0700 (PDT) Received: from octofox.hsd1.ca.comcast.net ([2601:641:401:1d20:4acf:f21e:cb28:b701]) by smtp.gmail.com with ESMTPSA id o1-20020a62f901000000b0052285857864sm2567513pfh.97.2022.06.16.20.32.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Jun 2022 20:32:34 -0700 (PDT) From: Max Filippov To: devel@uclibc-ng.org Date: Thu, 16 Jun 2022 20:32:19 -0700 Message-Id: <20220617033219.792243-1-jcmvbkbc@gmail.com> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 Message-ID-Hash: Z5OR7FWQVJUFFRIXMMBIEXWJNUJ6L4TR X-Message-ID-Hash: Z5OR7FWQVJUFFRIXMMBIEXWJNUJ6L4TR X-MailFrom: jcmvbkbc@gmail.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: linux-xtensa@linux-xtensa.org X-Mailman-Version: 3.3.3 Precedence: list Subject: [uclibc-ng-devel] [PATCH] xtensa: implement user context manipulation functions List-Id: uClibc-ng Development Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Implement getcontext, makecontext, setcontext and swapcontext. Signed-off-by: Max Filippov --- extra/Configs/Config.xtensa | 3 +- libc/sysdeps/linux/xtensa/Makefile.arch | 3 + libc/sysdeps/linux/xtensa/__start_context.S | 103 +++++++++++ libc/sysdeps/linux/xtensa/getcontext.S | 99 +++++++++++ libc/sysdeps/linux/xtensa/makecontext.c | 179 ++++++++++++++++++++ libc/sysdeps/linux/xtensa/setcontext.S | 116 +++++++++++++ libc/sysdeps/linux/xtensa/swapcontext.S | 173 +++++++++++++++++++ libc/sysdeps/linux/xtensa/sysdep.h | 7 +- libc/sysdeps/linux/xtensa/ucontext_i.sym | 15 ++ 9 files changed, 695 insertions(+), 3 deletions(-) create mode 100644 libc/sysdeps/linux/xtensa/__start_context.S create mode 100644 libc/sysdeps/linux/xtensa/getcontext.S create mode 100644 libc/sysdeps/linux/xtensa/makecontext.c create mode 100644 libc/sysdeps/linux/xtensa/setcontext.S create mode 100644 libc/sysdeps/linux/xtensa/swapcontext.S create mode 100644 libc/sysdeps/linux/xtensa/ucontext_i.sym diff --git a/extra/Configs/Config.xtensa b/extra/Configs/Config.xtensa index 3ee8817ba1a2..7316c542d896 100644 --- a/extra/Configs/Config.xtensa +++ b/extra/Configs/Config.xtensa @@ -10,5 +10,6 @@ config TARGET_ARCH config FORCE_OPTIONS_FOR_ARCH bool default y - select ARCH_HAS_DEPRECATED_SYSCALLS select ARCH_ANY_ENDIAN + select ARCH_HAS_DEPRECATED_SYSCALLS + select ARCH_HAS_UCONTEXT diff --git a/libc/sysdeps/linux/xtensa/Makefile.arch b/libc/sysdeps/linux/xtensa/Makefile.arch index 23cd08ee5687..f3a93caaafb1 100644 --- a/libc/sysdeps/linux/xtensa/Makefile.arch +++ b/libc/sysdeps/linux/xtensa/Makefile.arch @@ -10,3 +10,6 @@ SSRC-y := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \ sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S CSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += fork.c + +CSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += makecontext.c +SSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += setcontext.S getcontext.S swapcontext.S __start_context.S diff --git a/libc/sysdeps/linux/xtensa/__start_context.S b/libc/sysdeps/linux/xtensa/__start_context.S new file mode 100644 index 000000000000..f92c01112fa7 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/__start_context.S @@ -0,0 +1,103 @@ +/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +#if defined(__XTENSA_CALL0_ABI__) +/* + * There's no entry instruction, makecontext sets up ucontext_t as if + * getcontext was called above and is about to return here. + * Registers on entry to this function: + * a12: func to call + * a13: ucp->uc_link, next context to activate if func returns + * a14: func argc + * a2..a4: func arguments 0..2 + * + */ + .literal_position + +ENTRY_PREFIX(__start_context) + + beqz a14, 1f + + /* load func arguments 0..1 from stack and free that space */ + l32i a2, a1, 8 + l32i a3, a1, 12 + addi a1, a1, 16 + bltui a14, 3, 1f + + /* load func arguments 2..5 from stack and free that space */ + l32i a4, a1, 0 + l32i a5, a1, 4 + l32i a6, a1, 8 + l32i a7, a1, 12 + addi a1, a1, 16 + /* func arguments 6..argc - 1 are now at the top of the stack */ +1: + callx0 a12 + beqz a13, 1f + mov a2, a13 + movi a4, JUMPTARGET (setcontext) + callx0 a4 +1: + movi a4, JUMPTARGET (_exit) + movi a2, 0 + callx0 a4 + ill +END(__start_context) +#elif defined(__XTENSA_WINDOWED_ABI__) +/* + * There's no entry instruction, makecontext sets up ucontext_t as if + * getcontext was called above and is about to return here. + * Registers on entry to this function: + * a2: func to call + * a3: ucp->uc_link, next context to activate if func returns + * a4: func argc + * a5..a7: func arguments 0..2 + * + */ + .literal_position + +ENTRY_PREFIX(__start_context) + + mov a10, a5 + mov a11, a6 + mov a12, a7 + bltui a4, 4, 1f + + /* load func arguments 3..5 from stack and free that space */ + l32i a13, a1, 4 + l32i a14, a1, 8 + l32i a15, a1, 12 + addi a5, a1, 16 + movsp a1, a5 + /* func arguments 6..argc - 1 are now at the top of the stack */ +1: + callx8 a2 + beqz a3, 1f + mov a6, a3 + movi a4, JUMPTARGET (setcontext) + callx4 a4 +1: + movi a4, JUMPTARGET (_exit) + movi a6, 0 + callx4 a4 + ill +END(__start_context) +#else +#error Unsupported Xtensa ABI +#endif diff --git a/libc/sysdeps/linux/xtensa/getcontext.S b/libc/sysdeps/linux/xtensa/getcontext.S new file mode 100644 index 000000000000..fbb70c3f8720 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/getcontext.S @@ -0,0 +1,99 @@ +/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include "ucontext_i.h" + +#if defined(__XTENSA_CALL0_ABI__) +ENTRY(__getcontext) + s32i a0, a2, MCONTEXT_SC_PC + s32i a1, a2, MCONTEXT_SC_A_0 + 4 + + /* save callee-saved registers in the context */ + s32i a12, a2, MCONTEXT_SC_A_0 + 48 + s32i a13, a2, MCONTEXT_SC_A_0 + 52 + s32i a14, a2, MCONTEXT_SC_A_0 + 56 + s32i a15, a2, MCONTEXT_SC_A_0 + 60 + + movi a3, 0 + addi a4, a2, UCONTEXT_SIGMASK + movi a2, 0 + movi a5, JUMPTARGET (sigprocmask) + jx a5 +END(__getcontext) +#elif defined(__XTENSA_WINDOWED_ABI__) +ENTRY(__getcontext) + movi a4, __window_spill + callx4 a4 + s32i a0, a2, MCONTEXT_SC_PC + + /* copy registers a0..a3 from spill area */ + addi a3, a1, -16 + l32i a4, a3, 0 + l32i a5, a3, 4 + l32i a6, a3, 8 + l32i a7, a3, 12 + s32i a4, a2, MCONTEXT_SC_A_0 + 0 + s32i a5, a2, MCONTEXT_SC_A_0 + 4 + s32i a6, a2, MCONTEXT_SC_A_0 + 8 + s32i a7, a2, MCONTEXT_SC_A_0 + 12 + + /* if it was call4 then register saving is done */ + extui a4, a0, 30, 2 + bltui a4, 2, 1f + + /* otherwise load spill overflow area address into a3 */ + addi a3, a5, -16 + l32i a3, a3, 4 + addi a3, a3, -32 + beqi a4, 2, 2f + + /* copy registers a8..a11 from spill overflow area */ + addi a3, a3, -16 + l32i a4, a3, 16 + l32i a5, a3, 20 + l32i a6, a3, 24 + l32i a7, a3, 28 + s32i a4, a2, MCONTEXT_SC_A_0 + 32 + s32i a5, a2, MCONTEXT_SC_A_0 + 36 + s32i a6, a2, MCONTEXT_SC_A_0 + 40 + s32i a7, a2, MCONTEXT_SC_A_0 + 44 + + /* copy registers a4..a7 from spill overflow area */ +2: + l32i a4, a3, 0 + l32i a5, a3, 4 + l32i a6, a3, 8 + l32i a7, a3, 12 + s32i a4, a2, MCONTEXT_SC_A_0 + 16 + s32i a5, a2, MCONTEXT_SC_A_0 + 20 + s32i a6, a2, MCONTEXT_SC_A_0 + 24 + s32i a7, a2, MCONTEXT_SC_A_0 + 28 +1: + movi a6, 0 + movi a7, 0 + addi a8, a2, UCONTEXT_SIGMASK + movi a4, JUMPTARGET (sigprocmask) + callx4 a4 + mov a2, a6 + retw +END(__getcontext) +#else +#error Unsupported Xtensa ABI +#endif + +weak_alias (__getcontext, getcontext) diff --git a/libc/sysdeps/linux/xtensa/makecontext.c b/libc/sysdeps/linux/xtensa/makecontext.c new file mode 100644 index 000000000000..da26a0130325 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/makecontext.c @@ -0,0 +1,179 @@ +/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include + +extern void __start_context (void); + +#if defined(__XTENSA_CALL0_ABI__) +/* + * makecontext sets up new stack like this: + * + * +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size) + * | optional alignment + * +------------------ CFA of __start_context, initial sp points here + * | optional padding + * +------------------ Optional arguments 6..argc - 1 + * | func arg argc - 1 + * | func arg argc - 2 + * | ... + * | func arg 6 + * +------------------ Optional arguments 2..5 + * | func arg 5 + * 16 | func arg 4 + * | func arg 3 + * | func arg 2 + * +------------------ Optional arguments 0..1 + * | func arg 1 + * 16 | func arg 0 + * | padding + * | padding + * +------------------ CFA of pseudo getcontext + * | + * +------------------ stack bottom (uc_stack.ss_sp) + * + * When argc is 0 arguments areas are not allocated, + * when 1 <= argc < 3 only area for arguments 0..1 is allocated, + * when 3 <= argc < 7 areas for arguments 0..1 and 2..5 is allocated, + * when argc >= 7 all three arguments areas are allocated. + * Arguments 0..5 area is deallocated by the __start_context after + * arguments are loaded into registers. + * uc_mcontext registers are set as if __start_context made call0 + * to getcontext, sp points to that pseudo getcontext CFA. + * setcontext/swapcontext will arrange for restoring regiters + * a1, a12..a15 of __start_context. + */ + +void +__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) +{ + unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp + + ucp->uc_stack.ss_size) & -16; + int i; + + if (argc > 0) + sp -= 4 * (argc + 2); + sp &= -16; + + ucp->uc_mcontext.sc_pc = (unsigned long) __start_context; + ucp->uc_mcontext.sc_a[1] = sp; + ucp->uc_mcontext.sc_a[12] = (unsigned long) func; + ucp->uc_mcontext.sc_a[13] = (unsigned long) ucp->uc_link; + ucp->uc_mcontext.sc_a[14] = argc; + + if (argc) + { + va_list ap; + + va_start (ap, argc); + for (i = 0; i < argc; ++i) + ((int *) sp)[i + 2] = va_arg (ap, int); + va_end (ap); + } +} +#elif defined(__XTENSA_WINDOWED_ABI__) +/* + * makecontext sets up new stack like this: + * + * +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size) + * | optional alignment + * +------------------ CFA of __start_context + * 16 | Outermost caller spill area + * +------------------ + * 16 | __start_context overflow area + * +------------------ initial sp points here + * | optional padding + * +------------------ Optional arguments 6..argc - 1 + * | func arg argc - 1 + * | func arg argc - 2 + * | ... + * | func arg 6 + * +------------------ Optional arguments 3..5 + * | func arg 5 + * 16 | func arg 4 + * | func arg 3 + * | padding + * +------------------ CFA of pseudo getcontext + * 16 | __start_context caller spill area + * +------------------ + * | + * +------------------ stack bottom (uc_stack.ss_sp) + * + * When argc < 4 both arguments areas are not allocated, + * when 4 <= argc < 7 only area for arguments 3..5 is allocated, + * when argc >= 7 both arguments areas are allocated. + * Arguments 3..5 area is deallocated by the __start_context after + * arguments are loaded into registers. + * uc_mcontext registers are set as if __start_context made call8 + * to getcontext, sp points to that pseudo getcontext CFA, spill + * area under that sp has a1 pointing to the __start_context CFA + * at the top of the stack. setcontext/swapcontext will arrange for + * restoring regiters a0..a7 of __start_context. + */ + +void +__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) +{ + unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp + + ucp->uc_stack.ss_size - 32) & -16; + unsigned long spill0[4] = + { + 0, sp + 32, 0, 0, + }; + int i; + + memset ((void *) sp, 0, 32); + + if (argc > 2) + sp -= 4 * (argc - 2); + sp &= -16; + + ucp->uc_mcontext.sc_pc = + ((unsigned long) __start_context & 0x3fffffff) + 0x80000000; + ucp->uc_mcontext.sc_a[0] = 0; + ucp->uc_mcontext.sc_a[1] = sp; + ucp->uc_mcontext.sc_a[2] = (unsigned long) func; + ucp->uc_mcontext.sc_a[3] = (unsigned long) ucp->uc_link; + ucp->uc_mcontext.sc_a[4] = argc; + + if (argc) + { + va_list ap; + + va_start (ap, argc); + for (i = 0; i < argc; ++i) + { + if (i < 3) + ucp->uc_mcontext.sc_a[5 + i] = va_arg (ap, int); + else + ((int *) sp)[i - 2] = va_arg (ap, int); + } + va_end (ap); + } + + sp -= 16; + memcpy ((void *) sp, spill0, sizeof (spill0)); +} +#else +#error Unsupported Xtensa ABI +#endif + +weak_alias (__makecontext, makecontext) diff --git a/libc/sysdeps/linux/xtensa/setcontext.S b/libc/sysdeps/linux/xtensa/setcontext.S new file mode 100644 index 000000000000..4df7cc049006 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/setcontext.S @@ -0,0 +1,116 @@ +/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include "ucontext_i.h" + +#if defined(__XTENSA_CALL0_ABI__) +ENTRY(__setcontext) + addi sp, sp, -16 + s32i a0, sp, 0 + s32i a2, sp, 4 + + addi a3, a2, UCONTEXT_SIGMASK + movi a4, 0 + movi a2, SIG_SETMASK + movi a5, JUMPTARGET (sigprocmask) + callx0 a5 + bnez a2, .Lerror + + l32i a2, sp, 4 + l32i a0, a2, MCONTEXT_SC_PC + l32i a1, a2, MCONTEXT_SC_A_0 + 4 + + /* load callee-saved registers from the context */ + l32i a12, a2, MCONTEXT_SC_A_0 + 48 + l32i a13, a2, MCONTEXT_SC_A_0 + 52 + l32i a14, a2, MCONTEXT_SC_A_0 + 56 + l32i a15, a2, MCONTEXT_SC_A_0 + 60 + movi a2, 0 + ret +.Lerror: + l32i a0, sp, 0 + addi sp, sp, 16 + ret +END(__setcontext) +#elif defined(__XTENSA_WINDOWED_ABI__) +ENTRY(__setcontext) + movi a6, SIG_SETMASK + addi a7, a2, UCONTEXT_SIGMASK + movi a8, 0 + movi a4, JUMPTARGET (sigprocmask) + callx4 a4 + bnez a6, .Lerror + movi a4, __window_spill + callx4 a4 + + l32i a0, a2, MCONTEXT_SC_PC + + /* copy registers a0..a3 to spill area */ + addi a3, a1, -16 + l32i a4, a2, MCONTEXT_SC_A_0 + 0 + l32i a5, a2, MCONTEXT_SC_A_0 + 4 + l32i a6, a2, MCONTEXT_SC_A_0 + 8 + l32i a7, a2, MCONTEXT_SC_A_0 + 12 + s32i a4, a3, 0 + s32i a5, a3, 4 + s32i a6, a3, 8 + s32i a7, a3, 12 + + /* if it was call4 then register setup is done */ + extui a4, a0, 30, 2 + bltui a4, 2, 1f + + /* otherwise load spill overflow area address into a3 */ + addi a3, a5, -16 + l32i a3, a3, 4 + addi a3, a3, -32 + beqi a4, 2, 2f + + /* copy registers a8..a11 to spill overflow area */ + addi a3, a3, -16 + l32i a4, a2, MCONTEXT_SC_A_0 + 32 + l32i a5, a2, MCONTEXT_SC_A_0 + 36 + l32i a6, a2, MCONTEXT_SC_A_0 + 40 + l32i a7, a2, MCONTEXT_SC_A_0 + 44 + s32i a4, a3, 16 + s32i a5, a3, 20 + s32i a6, a3, 24 + s32i a7, a3, 28 + + /* copy registers a4..a7 to spill overflow area */ +2: + l32i a4, a2, MCONTEXT_SC_A_0 + 16 + l32i a5, a2, MCONTEXT_SC_A_0 + 20 + l32i a6, a2, MCONTEXT_SC_A_0 + 24 + l32i a7, a2, MCONTEXT_SC_A_0 + 28 + s32i a4, a3, 0 + s32i a5, a3, 4 + s32i a6, a3, 8 + s32i a7, a3, 12 +1: + movi a2, 0 + retw +.Lerror: + mov a2, a6 + retw +END(__setcontext) +#else +#error Unsupported Xtensa ABI +#endif + +weak_alias (__setcontext, setcontext) diff --git a/libc/sysdeps/linux/xtensa/swapcontext.S b/libc/sysdeps/linux/xtensa/swapcontext.S new file mode 100644 index 000000000000..a215edc6d54a --- /dev/null +++ b/libc/sysdeps/linux/xtensa/swapcontext.S @@ -0,0 +1,173 @@ +/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include "ucontext_i.h" + +#if defined(__XTENSA_CALL0_ABI__) +ENTRY(__swapcontext) + s32i a0, a2, MCONTEXT_SC_PC + s32i a1, a2, MCONTEXT_SC_A_0 + 4 + + /* save callee-saved registers in the context */ + s32i a12, a2, MCONTEXT_SC_A_0 + 48 + s32i a13, a2, MCONTEXT_SC_A_0 + 52 + s32i a14, a2, MCONTEXT_SC_A_0 + 56 + s32i a15, a2, MCONTEXT_SC_A_0 + 60 + + mov a12, a3 + mov a13, a2 + + addi a3, a3, UCONTEXT_SIGMASK + addi a4, a2, UCONTEXT_SIGMASK + movi a2, SIG_SETMASK + movi a5, JUMPTARGET (sigprocmask) + callx0 a5 + bnez a2, .Lerror + + mov a2, a12 + l32i a0, a2, MCONTEXT_SC_PC + l32i a1, a2, MCONTEXT_SC_A_0 + 4 + + /* load callee-saved registers from the context */ + l32i a12, a2, MCONTEXT_SC_A_0 + 48 + l32i a13, a2, MCONTEXT_SC_A_0 + 52 + l32i a14, a2, MCONTEXT_SC_A_0 + 56 + l32i a15, a2, MCONTEXT_SC_A_0 + 60 + + movi a2, 0 + ret +.Lerror: + l32i a0, a13, MCONTEXT_SC_PC + l32i a12, a13, MCONTEXT_SC_A_0 + 48 + l32i a13, a13, MCONTEXT_SC_A_0 + 52 + ret +END(__swapcontext) +#elif defined(__XTENSA_WINDOWED_ABI__) +ENTRY(__swapcontext) + movi a4, __window_spill + callx4 a4 + mov a9, a3 + s32i a0, a2, MCONTEXT_SC_PC + + /* copy registers a0..a3 from spill area */ + addi a3, a1, -16 + l32i a4, a3, 0 + l32i a5, a3, 4 + l32i a6, a3, 8 + l32i a7, a3, 12 + s32i a4, a2, MCONTEXT_SC_A_0 + 0 + s32i a5, a2, MCONTEXT_SC_A_0 + 4 + s32i a6, a2, MCONTEXT_SC_A_0 + 8 + s32i a7, a2, MCONTEXT_SC_A_0 + 12 + + /* if it was call4 then register saving is done */ + extui a4, a0, 30, 2 + bltui a4, 2, 1f + + /* otherwise load spill overflow area address into a3 */ + addi a3, a5, -16 + l32i a3, a3, 4 + addi a3, a3, -32 + beqi a4, 2, 2f + + /* copy registers a8..a11 from spill overflow area */ + addi a3, a3, -16 + l32i a4, a3, 16 + l32i a5, a3, 20 + l32i a6, a3, 24 + l32i a7, a3, 28 + s32i a4, a2, MCONTEXT_SC_A_0 + 32 + s32i a5, a2, MCONTEXT_SC_A_0 + 36 + s32i a6, a2, MCONTEXT_SC_A_0 + 40 + s32i a7, a2, MCONTEXT_SC_A_0 + 44 + + /* copy registers a4..a7 from spill overflow area */ +2: + l32i a4, a3, 0 + l32i a5, a3, 4 + l32i a6, a3, 8 + l32i a7, a3, 12 + s32i a4, a2, MCONTEXT_SC_A_0 + 16 + s32i a5, a2, MCONTEXT_SC_A_0 + 20 + s32i a6, a2, MCONTEXT_SC_A_0 + 24 + s32i a7, a2, MCONTEXT_SC_A_0 + 28 +1: + movi a6, SIG_SETMASK + addi a7, a9, UCONTEXT_SIGMASK + addi a8, a2, UCONTEXT_SIGMASK + mov a2, a9 + movi a4, JUMPTARGET (sigprocmask) + callx4 a4 + bnez a6, .Lerror + + l32i a0, a2, MCONTEXT_SC_PC + + /* copy registers a0..a3 to spill area */ + addi a3, a1, -16 + l32i a4, a2, MCONTEXT_SC_A_0 + 0 + l32i a5, a2, MCONTEXT_SC_A_0 + 4 + l32i a6, a2, MCONTEXT_SC_A_0 + 8 + l32i a7, a2, MCONTEXT_SC_A_0 + 12 + s32i a4, a3, 0 + s32i a5, a3, 4 + s32i a6, a3, 8 + s32i a7, a3, 12 + + /* if it was call4 then register setup is done */ + extui a4, a0, 30, 2 + bltui a4, 2, 1f + + /* otherwise load spill overflow area address into a3 */ + addi a3, a5, -16 + l32i a3, a3, 4 + addi a3, a3, -32 + beqi a4, 2, 2f + + /* copy registers a8..a11 to spill overflow area */ + addi a3, a3, -16 + l32i a4, a2, MCONTEXT_SC_A_0 + 32 + l32i a5, a2, MCONTEXT_SC_A_0 + 36 + l32i a6, a2, MCONTEXT_SC_A_0 + 40 + l32i a7, a2, MCONTEXT_SC_A_0 + 44 + s32i a4, a3, 16 + s32i a5, a3, 20 + s32i a6, a3, 24 + s32i a7, a3, 28 + + /* copy registers a4..a7 to spill overflow area */ +2: + l32i a4, a2, MCONTEXT_SC_A_0 + 16 + l32i a5, a2, MCONTEXT_SC_A_0 + 20 + l32i a6, a2, MCONTEXT_SC_A_0 + 24 + l32i a7, a2, MCONTEXT_SC_A_0 + 28 + s32i a4, a3, 0 + s32i a5, a3, 4 + s32i a6, a3, 8 + s32i a7, a3, 12 +1: + movi a2, 0 + retw +.Lerror: + mov a2, a6 + retw +END(__swapcontext) +#else +#error Unsupported Xtensa ABI +#endif + +weak_alias (__swapcontext, swapcontext) diff --git a/libc/sysdeps/linux/xtensa/sysdep.h b/libc/sysdeps/linux/xtensa/sysdep.h index 0671f0783477..80b3f30fcc5d 100644 --- a/libc/sysdeps/linux/xtensa/sysdep.h +++ b/libc/sysdeps/linux/xtensa/sysdep.h @@ -39,12 +39,15 @@ #endif -#define ENTRY(name) \ +#define ENTRY_PREFIX(name) \ .globl C_SYMBOL_NAME(name); \ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name), @function); \ .align ALIGNARG(2); \ LITERAL_POSITION; \ - C_LABEL(name) \ + C_LABEL(name) + +#define ENTRY(name) \ + ENTRY_PREFIX(name) \ abi_entry(sp, FRAMESIZE); #define HIDDEN_ENTRY(name) \ diff --git a/libc/sysdeps/linux/xtensa/ucontext_i.sym b/libc/sysdeps/linux/xtensa/ucontext_i.sym new file mode 100644 index 000000000000..4770c36c9e1d --- /dev/null +++ b/libc/sysdeps/linux/xtensa/ucontext_i.sym @@ -0,0 +1,15 @@ +#include +#include +#include +#include + +SIG_BLOCK +SIG_SETMASK + +-- Offsets of the fields in the ucontext_t structure. +#define ucontext(member) offsetof (ucontext_t, member) +#define mcontext(member) ucontext (uc_mcontext.member) + +UCONTEXT_SIGMASK ucontext (uc_sigmask) +MCONTEXT_SC_A_0 mcontext (sc_a[0]) +MCONTEXT_SC_PC mcontext (sc_pc)