From patchwork Tue Jul 19 01:20:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: caiyinyu X-Patchwork-Id: 56143 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4950C3850867 for ; Tue, 19 Jul 2022 01:22:00 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by sourceware.org (Postfix) with ESMTP id C5F9E3858285 for ; Tue, 19 Jul 2022 01:21:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org C5F9E3858285 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=loongson.cn Received: from 5.5.5 (unknown [10.2.5.5]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9Dxf+P5BtZicpcnAA--.9695S10; Tue, 19 Jul 2022 09:21:07 +0800 (CST) From: caiyinyu To: adhemerval.zanella@linaro.org, libc-alpha@sourceware.org, joseph_myers@mentor.com, carlos@redhat.com, i.swmail@xen0n.name Subject: [PATCH v7 08/13] LoongArch: Linux ABI Date: Tue, 19 Jul 2022 09:20:51 +0800 Message-Id: <20220719012056.1461897-9-caiyinyu@loongson.cn> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220719012056.1461897-1-caiyinyu@loongson.cn> References: <20220719012056.1461897-1-caiyinyu@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf9Dxf+P5BtZicpcnAA--.9695S10 X-Coremail-Antispam: 1UD129KBjvAXoWfZryfuFykJF4fAFWDKrW5Awb_yoW5tr47Zo WfWFW7Jr48Gr47WF4Y9a9rJa47Wr429r1aqa1YvFZ7JF1rAr15CFZYya1Svw13Gry5uF4k Xa4xX3sxtF42krn3n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUY_7AC8VAFwI0_Wr0E3s1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r126s0DM28Irc Ia0xkI8VCY1x0267AKxVW5JVCq3wA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l 84ACjcxK6xIIjxv20xvE14v26F1j6w1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4UJV WxJr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x0267AKxVW8 Jr0_Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMc Ij6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_ Jr0_Gr1lF7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkIecxEwVCm-w CF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j 6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_JF0_Jw1lIxkGc2Ij64 vIr41lIxAIcVC0I7IYx2IY67AKxVWUCVW8JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Cr0_ Gr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42 IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjfUOBTYUUUUU X-CM-SenderInfo: 5fdl5xhq1xqz5rrqw2lrqou0/ X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_PASS, SPF_PASS, TXREP, URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: caiyinyu Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" --- sysdeps/loongarch/dl-irel.h | 54 ++++++++++ sysdeps/loongarch/nptl/pthreaddef.h | 32 ++++++ sysdeps/loongarch/sys/ifunc.h | 30 ++++++ .../unix/sysv/linux/loongarch/bits/fcntl.h | 61 +++++++++++ .../unix/sysv/linux/loongarch/bits/procfs.h | 52 +++++++++ .../linux/loongarch/bits/pthread_stack_min.h | 20 ++++ .../unix/sysv/linux/loongarch/bits/sigstack.h | 32 ++++++ .../unix/sysv/linux/loongarch/getcontext.S | 59 +++++++++++ .../unix/sysv/linux/loongarch/localplt.data | 12 +++ .../unix/sysv/linux/loongarch/makecontext.c | 81 ++++++++++++++ .../unix/sysv/linux/loongarch/setcontext.S | 100 ++++++++++++++++++ .../sysv/linux/loongarch/sigcontextinfo.h | 32 ++++++ .../unix/sysv/linux/loongarch/swapcontext.S | 95 +++++++++++++++++ .../unix/sysv/linux/loongarch/sys/ucontext.h | 61 +++++++++++ sysdeps/unix/sysv/linux/loongarch/sys/user.h | 42 ++++++++ .../sysv/linux/loongarch/ucontext-macros.h | 32 ++++++ .../unix/sysv/linux/loongarch/ucontext_i.sym | 31 ++++++ 17 files changed, 826 insertions(+) create mode 100644 sysdeps/loongarch/dl-irel.h create mode 100644 sysdeps/loongarch/nptl/pthreaddef.h create mode 100644 sysdeps/loongarch/sys/ifunc.h create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/procfs.h create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/pthread_stack_min.h create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/sigstack.h create mode 100644 sysdeps/unix/sysv/linux/loongarch/getcontext.S create mode 100644 sysdeps/unix/sysv/linux/loongarch/localplt.data create mode 100644 sysdeps/unix/sysv/linux/loongarch/makecontext.c create mode 100644 sysdeps/unix/sysv/linux/loongarch/setcontext.S create mode 100644 sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h create mode 100644 sysdeps/unix/sysv/linux/loongarch/swapcontext.S create mode 100644 sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h create mode 100644 sysdeps/unix/sysv/linux/loongarch/sys/user.h create mode 100644 sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h create mode 100644 sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym Reviewed-by: Adhemerval Zanella diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h new file mode 100644 index 0000000000..4440453f06 --- /dev/null +++ b/sysdeps/loongarch/dl-irel.h @@ -0,0 +1,54 @@ +/* Machine-dependent ELF indirect relocation inline functions. + Copyright (C) 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 + . */ + +#ifndef _DL_IREL_H +#define _DL_IREL_H + +#include +#include +#include + +#define ELF_MACHINE_IRELA 1 + +static inline ElfW (Addr) __attribute ((always_inline)) +elf_ifunc_invoke (ElfW (Addr) addr) +{ + __ifunc_arg_t arg = + { + ._size = sizeof (__ifunc_arg_t), + ._hwcap = GLRO(dl_hwcap), + }; + return ((ElfW(Addr) (*) (const __ifunc_arg_t *)) (addr)) (&arg); +} + +static inline void __attribute ((always_inline)) +elf_irela (const ElfW (Rela) *reloc) +{ + ElfW (Addr) *const reloc_addr = (void *) reloc->r_offset; + const unsigned long int r_type = ELFW (R_TYPE) (reloc->r_info); + + if (__glibc_likely (r_type == R_LARCH_IRELATIVE)) + { + ElfW (Addr) value = elf_ifunc_invoke (reloc->r_addend); + *reloc_addr = value; + } + else + __libc_fatal ("Unexpected reloc type in static binary.\n"); +} + +#endif /* dl-irel.h */ diff --git a/sysdeps/loongarch/nptl/pthreaddef.h b/sysdeps/loongarch/nptl/pthreaddef.h new file mode 100644 index 0000000000..955566cddc --- /dev/null +++ b/sysdeps/loongarch/nptl/pthreaddef.h @@ -0,0 +1,32 @@ +/* pthread machine parameter definitions. + Copyright (C) 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 + . */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Minimum guard size. */ +#define ARCH_MIN_GUARD_SIZE 0 + +/* Required stack pointer alignment at beginning. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) diff --git a/sysdeps/loongarch/sys/ifunc.h b/sysdeps/loongarch/sys/ifunc.h new file mode 100644 index 0000000000..461df20c96 --- /dev/null +++ b/sysdeps/loongarch/sys/ifunc.h @@ -0,0 +1,30 @@ +/* Definitions used by LoongArch indirect function resolvers. + Copyright (C) 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 + . */ + +#ifndef _SYS_IFUNC_H +#define _SYS_IFUNC_H + +struct __ifunc_arg_t +{ + unsigned long _size; /* Size of the struct, so it can grow. */ + unsigned long _hwcap; +}; + +typedef struct __ifunc_arg_t __ifunc_arg_t; + +#endif diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h b/sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h new file mode 100644 index 0000000000..bf1e254234 --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h @@ -0,0 +1,61 @@ +/* O_*, F_*, FD_* bit values for the generic Linux/LoongArch ABI. + Copyright (C) 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 + . */ + +#ifndef _FCNTL_H +#error "Never use directly; include instead." +#endif + +#include + +/* In 64-bit ISA files are always with 64bit off_t and F_*LK64 are the same as + non-64-bit versions. It will need to be revised for 128-bit. */ +#if __WORDSIZE == 64 +#define __O_LARGEFILE 0 + +#define F_GETLK64 5 /* Get record locking info. */ +#define F_SETLK64 6 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 7 /* Set record locking info (blocking). */ +#endif + +struct flock +{ + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ +}; + +#ifdef __USE_LARGEFILE64 +struct flock64 +{ + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ +}; +#endif + +/* Include generic Linux declarations. */ +#include diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/procfs.h b/sysdeps/unix/sysv/linux/loongarch/bits/procfs.h new file mode 100644 index 0000000000..2db777b38c --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/bits/procfs.h @@ -0,0 +1,52 @@ +/* Types for registers for sys/procfs.h. + Copyright (C) 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 + . */ + +#ifndef _SYS_PROCFS_H +# error "Never include directly; use instead." +#endif + +/* Type for a general-purpose register. */ +typedef __uint64_t elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + pt_regs' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof (elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +#define ELF_NFPREG 34 /* 32 FPRs + 8-byte byte-vec for fcc + 4-byte FCR */ +typedef union +{ + double d; + float f; +} elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +typedef union +{ + double d[2]; + float f[4]; +} __attribute__ ((__aligned__ (16))) elf_lsxregset_t[32]; + +typedef union +{ + double d[4]; + float f[8]; +} __attribute__ ((__aligned__ (32))) elf_lasxregset_t[32]; diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/pthread_stack_min.h b/sysdeps/unix/sysv/linux/loongarch/bits/pthread_stack_min.h new file mode 100644 index 0000000000..072c2ade42 --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/bits/pthread_stack_min.h @@ -0,0 +1,20 @@ +/* Definition of PTHREAD_STACK_MIN. LoongArch Linux version. + Copyright (C) 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 + . */ + +/* Minimum size for a thread. At least two pages with 64k pages. */ +#define PTHREAD_STACK_MIN 131072 diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/sigstack.h b/sysdeps/unix/sysv/linux/loongarch/bits/sigstack.h new file mode 100644 index 0000000000..238c1a98e6 --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/bits/sigstack.h @@ -0,0 +1,32 @@ +/* sigstack, sigaltstack definitions. + Copyright (C) 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 + . */ + +#ifndef _BITS_SIGSTACK_H +#define _BITS_SIGSTACK_H 1 + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never include this file directly. Use instead" +#endif + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ 4096 + +/* System default stack size. */ +#define SIGSTKSZ 16384 + +#endif /* bits/sigstack.h */ diff --git a/sysdeps/unix/sysv/linux/loongarch/getcontext.S b/sysdeps/unix/sysv/linux/loongarch/getcontext.S new file mode 100644 index 0000000000..43b95e9715 --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/getcontext.S @@ -0,0 +1,59 @@ +/* Save current context. + Copyright (C) 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 "ucontext-macros.h" + +/* int getcontext (ucontext_t *ucp) */ + + .text +LEAF (__getcontext) + SAVE_INT_REG (ra, 1, a0) + SAVE_INT_REG (sp, 3, a0) + SAVE_INT_REG (zero, 4, a0) /* return 0 by overwriting a0. */ + SAVE_INT_REG (x, 21, a0) + SAVE_INT_REG (fp, 22, a0) + SAVE_INT_REG (s0, 23, a0) + SAVE_INT_REG (s1, 24, a0) + SAVE_INT_REG (s2, 25, a0) + SAVE_INT_REG (s3, 26, a0) + SAVE_INT_REG (s4, 27, a0) + SAVE_INT_REG (s5, 28, a0) + SAVE_INT_REG (s6, 29, a0) + SAVE_INT_REG (s7, 30, a0) + SAVE_INT_REG (s8, 31, a0) + st.d ra, a0, MCONTEXT_PC + +/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */ + li.d a3, _NSIG8 + li.d a2, UCONTEXT_SIGMASK + add.d a2, a2, a0 + ori a1, zero,0 + li.d a0, SIG_BLOCK + + li.d a7, SYS_ify (rt_sigprocmask) + syscall 0 + blt a0, zero, 99f + + jirl $r0, $r1, 0 + +99: + b __syscall_error + +PSEUDO_END (__getcontext) + +weak_alias (__getcontext, getcontext) diff --git a/sysdeps/unix/sysv/linux/loongarch/localplt.data b/sysdeps/unix/sysv/linux/loongarch/localplt.data new file mode 100644 index 0000000000..817ab2659a --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/localplt.data @@ -0,0 +1,12 @@ +# See scripts/check-localplt.awk for how this file is processed. +# PLT use is required for the malloc family and for matherr because +# users can define their own functions and have library internals call them. +libc.so: calloc +libc.so: free +libc.so: malloc +libc.so: realloc +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error +ld.so: _dl_signal_exception +ld.so: _dl_catch_exception diff --git a/sysdeps/unix/sysv/linux/loongarch/makecontext.c b/sysdeps/unix/sysv/linux/loongarch/makecontext.c new file mode 100644 index 0000000000..94a45bf4ad --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/makecontext.c @@ -0,0 +1,81 @@ +/* Create new context. + Copyright (C) 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 + +void +__makecontext (ucontext_t *ucp, void (*func) (void), int argc, long int a0, + long int a1, long int a2, long int a3, long int a4, ...) +{ + extern void __start_context (void) attribute_hidden; + unsigned long int *sp; + + _Static_assert(LARCH_REG_NARGS == 8, + "__makecontext assumes 8 argument registers"); + + /* Set up the stack. */ + sp = (unsigned long int *) + (((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size) & ALMASK); + + /* Set up the register context. + ra = s0 = 0, terminating the stack for backtracing purposes. + s1 = the function we must call. + s2 = the subsequent context to run. */ + ucp->uc_mcontext.__gregs[LARCH_REG_RA] = (uintptr_t) 0; + ucp->uc_mcontext.__gregs[LARCH_REG_S0] = (uintptr_t) 0; + ucp->uc_mcontext.__gregs[LARCH_REG_S1] = (uintptr_t) func; + ucp->uc_mcontext.__gregs[LARCH_REG_S2] = (uintptr_t) ucp->uc_link; + ucp->uc_mcontext.__gregs[LARCH_REG_SP] = (uintptr_t) sp; + ucp->uc_mcontext.__pc = (uintptr_t) &__start_context; + + /* Put args in a0-a7, then put any remaining args on the stack. */ + ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 0] = (uintptr_t) a0; + ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 1] = (uintptr_t) a1; + ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 2] = (uintptr_t) a2; + ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 3] = (uintptr_t) a3; + ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 4] = (uintptr_t) a4; + + if (__glibc_unlikely (argc > 5)) + { + va_list vl; + va_start (vl, a4); + + long int reg_args = argc < LARCH_REG_NARGS ? argc : LARCH_REG_NARGS; + for (long int i = 5; i < reg_args; i++) + ucp->uc_mcontext.__gregs[LARCH_REG_A0 + i] = va_arg (vl, unsigned long int); + + long int stack_args = argc - reg_args; + if (stack_args > 0) + { + sp = (unsigned long int *) + (((uintptr_t) sp - stack_args * sizeof (long int)) & ALMASK); + ucp->uc_mcontext.__gregs[LARCH_REG_SP] = (uintptr_t) sp; + for (long int i = 0; i < stack_args; i++) + sp[i] = va_arg (vl, unsigned long int); + } + + va_end (vl); + } +} + +weak_alias (__makecontext, makecontext) diff --git a/sysdeps/unix/sysv/linux/loongarch/setcontext.S b/sysdeps/unix/sysv/linux/loongarch/setcontext.S new file mode 100644 index 0000000000..7295900149 --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/setcontext.S @@ -0,0 +1,100 @@ +/* Set current context. + Copyright (C) 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 "sys/regdef.h" +#include "ucontext-macros.h" + +/* int __setcontext (const ucontext_t *ucp) + + Restores the machine context in UCP and thereby resumes execution + in that context. + + This implementation is intended to be used for *synchronous* context + switches only. Therefore, it does not have to restore anything + other than the PRESERVED state. */ + + .text +LEAF (__setcontext) + + addi.d sp, sp, -16 + st.d a0, sp, 0 /* Save ucp to stack */ + +/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */ + li.d a3, _NSIG8 + li.d a2, 0 + li.d a1, UCONTEXT_SIGMASK + add.d a1, a1, a0 + li.d a0, SIG_SETMASK + + li.d a7, SYS_ify (rt_sigprocmask) + syscall 0 + + blt a0, $r0, 99f + + ld.d t0, sp, 0 /* Load ucp to t0 */ + cfi_def_cfa (12, 0) + +/* Note the contents of argument registers will be random + unless makecontext() has been called. */ + RESTORE_INT_REG(ra, 1, t0) + RESTORE_INT_REG(sp, 3, t0) + RESTORE_INT_REG(a0, 4, t0) + RESTORE_INT_REG(a1, 5, t0) + RESTORE_INT_REG(a2, 6, t0) + RESTORE_INT_REG(a3, 7, t0) + RESTORE_INT_REG(a4, 8, t0) + RESTORE_INT_REG(a5, 9, t0) + RESTORE_INT_REG(a6, 10, t0) + RESTORE_INT_REG(a7, 11, t0) + RESTORE_INT_REG(x, 21, t0) + RESTORE_INT_REG(fp, 22, t0) + RESTORE_INT_REG(s0, 23, t0) + RESTORE_INT_REG(s1, 24, t0) + RESTORE_INT_REG(s2, 25, t0) + RESTORE_INT_REG(s3, 26, t0) + RESTORE_INT_REG(s4, 27, t0) + RESTORE_INT_REG(s5, 28, t0) + RESTORE_INT_REG(s6, 29, t0) + RESTORE_INT_REG(s7, 30, t0) + RESTORE_INT_REG(s8, 31, t0) + + ld.d t1, t0, MCONTEXT_PC + jirl $r0,t1,0 + +99: + addi.d sp, sp, 16 + b __syscall_error + +PSEUDO_END (__setcontext) +weak_alias (__setcontext, setcontext) + +LEAF (__start_context) + + /* Terminate call stack by noting ra == 0. Happily, s0 == 0 here. */ + cfi_register (1, 23) + + /* Call the function passed to makecontext. */ + jirl $r1,s1,0 + + /* Invoke subsequent context if present, else exit(0). */ + ori a0, s2, 0 + beqz s2, 1f + bl __setcontext +1: + b HIDDEN_JUMPTARGET(exit) + +PSEUDO_END (__start_context) diff --git a/sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h b/sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h new file mode 100644 index 0000000000..5e202bc0b4 --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h @@ -0,0 +1,32 @@ +/* LoongArch definitions for signal handling calling conventions. + Copyright (C) 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 + . */ + +#ifndef _SIGCONTEXTINFO_H +#define _SIGCONTEXTINFO_H + +#include +#include + +static inline uintptr_t +sigcontext_get_pc (const ucontext_t *ctx) +{ + return ctx->uc_mcontext.__pc; +} + +#endif diff --git a/sysdeps/unix/sysv/linux/loongarch/swapcontext.S b/sysdeps/unix/sysv/linux/loongarch/swapcontext.S new file mode 100644 index 0000000000..bb22cd2f00 --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/swapcontext.S @@ -0,0 +1,95 @@ +/* Save and set current context. + Copyright (C) 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 "ucontext-macros.h" + +/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ + +LEAF (__swapcontext) + ori a2, sp, 0 /* Save sp to a2 */ + addi.d sp, sp, -16 + st.d a1, sp, 0 + ori t0, a1, 0 + + SAVE_INT_REG (ra, 1, a0) + SAVE_INT_REG (a2, 3, a0) /* Store sp */ + SAVE_INT_REG (zero, 4, a0) /* return 0 by overwriting a0 */ + SAVE_INT_REG (x, 21, a0) + SAVE_INT_REG (fp, 22, a0) + SAVE_INT_REG (s0, 23, a0) + SAVE_INT_REG (s1, 24, a0) + SAVE_INT_REG (s2, 25, a0) + SAVE_INT_REG (s3, 26, a0) + SAVE_INT_REG (s4, 27, a0) + SAVE_INT_REG (s5, 28, a0) + SAVE_INT_REG (s6, 29, a0) + SAVE_INT_REG (s7, 30, a0) + SAVE_INT_REG (s8, 31, a0) + + st.d ra, a0, MCONTEXT_PC + +/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, _NSIG8) */ + li.d a3, _NSIG8 + li.d a2, UCONTEXT_SIGMASK + add.d a2, a2, a0 + li.d a1, UCONTEXT_SIGMASK + add.d a1, a1, t0 + li.d a0, SIG_SETMASK + + li.d a7, SYS_ify (rt_sigprocmask) + syscall 0 + + blt a0, zero, 99f + + ld.d t0, sp, 0 /* Load a1 to t0 */ + +/* Note the contents of argument registers will be random + unless makecontext() has been called. */ + RESTORE_INT_REG (ra, 1, t0) + RESTORE_INT_REG (sp, 3, t0) + RESTORE_INT_REG (a0, 4, t0) + RESTORE_INT_REG (a1, 5, t0) + RESTORE_INT_REG (a2, 6, t0) + RESTORE_INT_REG (a3, 7, t0) + RESTORE_INT_REG (a4, 8, t0) + RESTORE_INT_REG (a5, 9, t0) + RESTORE_INT_REG (a6, 10, t0) + RESTORE_INT_REG (a7, 11, t0) + RESTORE_INT_REG (x, 21, t0) + RESTORE_INT_REG (fp, 22, t0) + RESTORE_INT_REG (s0, 23, t0) + RESTORE_INT_REG (s1, 24, t0) + RESTORE_INT_REG (s2, 25, t0) + RESTORE_INT_REG (s3, 26, t0) + RESTORE_INT_REG (s4, 27, t0) + RESTORE_INT_REG (s5, 28, t0) + RESTORE_INT_REG (s6, 29, t0) + RESTORE_INT_REG (s7, 30, t0) + RESTORE_INT_REG (s8, 31, t0) + + ld.d t1, t0, MCONTEXT_PC + jirl $r0, t1, 0 + + +99: + addi.d sp, sp, 16 + b __syscall_error + +PSEUDO_END (__swapcontext) + +weak_alias (__swapcontext, swapcontext) diff --git a/sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h b/sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h new file mode 100644 index 0000000000..e334a45a44 --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h @@ -0,0 +1,61 @@ +/* struct ucontext definition. + Copyright (C) 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 + . */ + +/* Don't rely on this, the interface is currently messed up and may need to + be broken to be fixed. */ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include + +#include +#include + +#ifdef __USE_MISC +#define LARCH_NGREG 32 + +#define LARCH_REG_RA 1 +#define LARCH_REG_SP 3 +#define LARCH_REG_S0 23 +#define LARCH_REG_S1 24 +#define LARCH_REG_A0 4 +#define LARCH_REG_S2 25 +#define LARCH_REG_NARGS 8 + +#endif + +typedef struct mcontext_t +{ + unsigned long long __pc; + unsigned long long __gregs[32]; + unsigned int __flags; + unsigned long long __extcontext[0] __attribute__((__aligned__(16))); +} mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext_t +{ + unsigned long int __uc_flags; + struct ucontext_t *uc_link; + stack_t uc_stack; + sigset_t uc_sigmask; + mcontext_t uc_mcontext; +} ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/sysdeps/unix/sysv/linux/loongarch/sys/user.h b/sysdeps/unix/sysv/linux/loongarch/sys/user.h new file mode 100644 index 0000000000..55181de816 --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/sys/user.h @@ -0,0 +1,42 @@ +/* struct user_regs_struct definition for LoongArch. + Copyright (C) 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 + . */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +#include + +struct user_regs_struct +{ + /* Saved main processor registers. */ + uint64_t regs[32]; + + /* Saved special registers. */ + uint64_t orig_a0; + uint64_t csr_era; + uint64_t csr_badv; + uint64_t reserved[10]; +}; + +struct user_fp_struct { + uint64_t fpr[32]; + uint64_t fcc; + uint32_t fcsr; +}; + +#endif /* _SYS_USER_H */ diff --git a/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h b/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h new file mode 100644 index 0000000000..859eba464b --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h @@ -0,0 +1,32 @@ +/* Macros for ucontext routines. + Copyright (C) 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 + . */ + +#ifndef _LINUX_LOONGARCH_UCONTEXT_MACROS_H +#define _LINUX_LOONGARCH_UCONTEXT_MACROS_H + +#include +#include +#include "ucontext_i.h" + +#define SAVE_INT_REG(name, num, base) \ + REG_S name, base, ((num) *SZREG + MCONTEXT_GREGS) + +#define RESTORE_INT_REG(name, num, base) \ + REG_L name, base, ((num) *SZREG + MCONTEXT_GREGS) + +#endif /* _LINUX_LOONGARCH_UCONTEXT_MACROS_H */ diff --git a/sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym b/sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym new file mode 100644 index 0000000000..f27afad56f --- /dev/null +++ b/sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +-- Constants used by the rt_sigprocmask call. + +SIG_BLOCK +SIG_SETMASK + +_NSIG8 (_NSIG / 8) + +-- Offsets of the fields in the ucontext_t structure. +#define ucontext(member) offsetof (ucontext_t, member) +#define stack(member) ucontext (uc_stack.member) +#define mcontext(member) ucontext (uc_mcontext.member) + +UCONTEXT_FLAGS ucontext (__uc_flags) +UCONTEXT_LINK ucontext (uc_link) +UCONTEXT_STACK ucontext (uc_stack) +UCONTEXT_MCONTEXT ucontext (uc_mcontext) +UCONTEXT_SIGMASK ucontext (uc_sigmask) + +STACK_SP stack (ss_sp) +STACK_SIZE stack (ss_size) +STACK_FLAGS stack (ss_flags) + +MCONTEXT_PC mcontext (__pc) +MCONTEXT_GREGS mcontext (__gregs) + +UCONTEXT_SIZE sizeof (ucontext_t)