From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1791) id 58943385802E; Tue, 26 Jul 2022 18:54:29 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 58943385802E Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Adhemerval Zanella To: glibc-cvs@sourceware.org Subject: [glibc] LoongArch: Linux ABI X-Act-Checkin: glibc X-Git-Author: caiyinyu X-Git-Refname: refs/heads/master X-Git-Oldrev: 45955fe61844d94f7faa660eda9e515a6571e8c3 X-Git-Newrev: f2037efbb33ffaf033b7a601a8a592d54879341c Message-Id: <20220726185429.58943385802E@sourceware.org> Date: Tue, 26 Jul 2022 18:54:29 +0000 (GMT) X-BeenThere: glibc-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Glibc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Jul 2022 18:54:29 -0000 https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=f2037efbb33ffaf033b7a601a8a592d54879341c commit f2037efbb33ffaf033b7a601a8a592d54879341c Author: caiyinyu Date: Tue Jul 19 09:20:51 2022 +0800 LoongArch: Linux ABI Diff: --- sysdeps/loongarch/dl-irel.h | 54 +++++++++++ sysdeps/loongarch/nptl/pthreaddef.h | 32 +++++++ sysdeps/loongarch/sys/ifunc.h | 30 +++++++ sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h | 61 +++++++++++++ sysdeps/unix/sysv/linux/loongarch/bits/procfs.h | 52 +++++++++++ .../sysv/linux/loongarch/bits/pthread_stack_min.h | 20 +++++ sysdeps/unix/sysv/linux/loongarch/bits/sigstack.h | 32 +++++++ sysdeps/unix/sysv/linux/loongarch/getcontext.S | 59 ++++++++++++ sysdeps/unix/sysv/linux/loongarch/localplt.data | 12 +++ sysdeps/unix/sysv/linux/loongarch/makecontext.c | 81 +++++++++++++++++ sysdeps/unix/sysv/linux/loongarch/setcontext.S | 100 +++++++++++++++++++++ sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h | 32 +++++++ sysdeps/unix/sysv/linux/loongarch/swapcontext.S | 95 ++++++++++++++++++++ sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h | 61 +++++++++++++ sysdeps/unix/sysv/linux/loongarch/sys/user.h | 42 +++++++++ .../unix/sysv/linux/loongarch/ucontext-macros.h | 32 +++++++ sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym | 31 +++++++ 17 files changed, 826 insertions(+) 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)