diff mbox series

[v5,09/13] LoongArch: Linux ABI

Message ID 20220601021836.1082160-10-caiyinyu@loongson.cn
State New
Headers show
Series GLIBC LoongArch PATCHES | expand

Commit Message

caiyinyu June 1, 2022, 2:18 a.m. UTC
---
 sysdeps/loongarch/dl-irel.h                   |  48 +++++++++
 sysdeps/loongarch/nptl/pthreaddef.h           |  32 ++++++
 .../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   |  79 ++++++++++++++
 .../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 ++++++
 16 files changed, 788 insertions(+)
 create mode 100644 sysdeps/loongarch/dl-irel.h
 create mode 100644 sysdeps/loongarch/nptl/pthreaddef.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

Comments

Adhemerval Zanella June 6, 2022, 6:36 p.m. UTC | #1
On 31/05/2022 23:18, caiyinyu wrote:
> ---
>  sysdeps/loongarch/dl-irel.h                   |  48 +++++++++
>  sysdeps/loongarch/nptl/pthreaddef.h           |  32 ++++++
>  .../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   |  79 ++++++++++++++
>  .../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 ++++++
>  16 files changed, 788 insertions(+)
>  create mode 100644 sysdeps/loongarch/dl-irel.h
>  create mode 100644 sysdeps/loongarch/nptl/pthreaddef.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
> 
> diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h
> new file mode 100644
> index 0000000000..c94cba702a
> --- /dev/null
> +++ b/sysdeps/loongarch/dl-irel.h
> @@ -0,0 +1,48 @@
> +/* 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _DL_IREL_H
> +#define _DL_IREL_H
> +
> +#include <stdio.h>
> +#include <unistd.h>
> +
> +#define ELF_MACHINE_IRELA 1
> +
> +static inline ElfW (Addr) __attribute ((always_inline))
> +elf_ifunc_invoke (ElfW (Addr) addr)
> +{
> +  return ((ElfW (Addr) (*) (void)) (addr)) ();

At least for RISCV, sparc, aarch64, powerpc, arm; the ifunc resolver expects
a unsigned long int begin the hardware capability from kernelk (AT_HWCAP).

AArch64 also extends it by passing both uint64_t and a struct with both
AT_HWCAP and AT_HWCAP2.  I am not sure if loongarch will ever use more
than the AT_HWCAP.

> +}
> +
> +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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +/* 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/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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _FCNTL_H
> +#error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
> +#endif
> +
> +#include <bits/wordsize.h>
> +
> +/* 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 <bits/fcntl-linux.h>
> 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _SYS_PROCFS_H
> +# error "Never include <bits/procfs.h> directly; use <sys/procfs.h> 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +/* 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _BITS_SIGSTACK_H
> +#define _BITS_SIGSTACK_H 1
> +
> +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H
> +# error "Never include this file directly.  Use <signal.h> 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#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..d29c8056cb
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/makecontext.c
> @@ -0,0 +1,79 @@
> +/* 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <sysdep.h>
> +#include <sys/asm.h>
> +#include <sys/ucontext.h>
> +#include <stdarg.h>
> +#include <assert.h>
> +
> +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;
> +  long int i, sp;
> +
> +  _Static_assert(LARCH_REG_NARGS == 8,
> +		 "__makecontext assumes 8 argument registers");
> +
> +  /* Set up the stack.  */
> +  sp = ((long int) 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] = 0;
> +  ucp->uc_mcontext.__gregs[LARCH_REG_S0] = 0;
> +  ucp->uc_mcontext.__gregs[LARCH_REG_S1] = (long int) func;
> +  ucp->uc_mcontext.__gregs[LARCH_REG_S2] = (long int) ucp->uc_link;
> +  ucp->uc_mcontext.__gregs[LARCH_REG_SP] = sp;
> +  ucp->uc_mcontext.__pc = (long int) &__start_context;
> +
> +  /* Put args in a0-a7, then put any remaining args on the stack.  */
> +  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 0] = a0;
> +  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 1] = a1;
> +  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 2] = a2;
> +  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 3] = a3;
> +  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 4] = a4;
> +
> +  if (__glibc_unlikely (argc > 5))
> +    {
> +      va_list vl;
> +      va_start (vl, a4);
> +
> +      long reg_args = argc < LARCH_REG_NARGS ? argc : LARCH_REG_NARGS;
> +      for (i = 5; i < reg_args; i++)
> +	ucp->uc_mcontext.__gregs[LARCH_REG_A0 + i] = va_arg (vl, long);
> +
> +      long int stack_args = argc - reg_args;
> +      if (stack_args > 0)
> +	{
> +	  sp = (sp - stack_args * sizeof (long int)) & ALMASK;
> +	  ucp->uc_mcontext.__gregs[LARCH_REG_SP] = sp;
> +	  for (i = 0; i < stack_args; i++)
> +	    ((long int *) sp)[i] = va_arg (vl, 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..a1216dad69
> --- /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
> +   <https://www.gnu.org/licenses/>.  */
> +#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		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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _SIGCONTEXTINFO_H
> +#define _SIGCONTEXTINFO_H
> +
> +#include <stdint.h>
> +#include <sys/ucontext.h>
> +
> +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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +/* 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 <features.h>
> +
> +#include <bits/types/sigset_t.h>
> +#include <bits/types/stack_t.h>
> +
> +#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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _SYS_USER_H
> +#define _SYS_USER_H 1
> +
> +#include <stdint.h>
> +
> +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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _LINUX_LOONGARCH_UCONTEXT_MACROS_H
> +#define _LINUX_LOONGARCH_UCONTEXT_MACROS_H
> +
> +#include <sysdep.h>
> +#include <sys/asm.h>
> +#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 <inttypes.h>
> +#include <signal.h>
> +#include <stddef.h>
> +#include <sys/ucontext.h>
> +
> +-- 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)
caiyinyu June 7, 2022, 9:32 a.m. UTC | #2
+static inline ElfW (Addr) __attribute ((always_inline))
+elf_ifunc_invoke (ElfW (Addr) addr)
+{
+  return ((ElfW (Addr) (*) (void)) (addr)) ();

At least for RISCV, sparc, aarch64, powerpc, arm; the ifunc resolver expects
a unsigned long int begin the hardware capability from kernelk (AT_HWCAP).

AArch64 also extends it by passing both uint64_t and a struct with both
AT_HWCAP and AT_HWCAP2.  I am not sure if loongarch will ever use more
than the AT_HWCAP.
*Currently ifuncs (like __memchr_ifunc, __memcpy_ifunc ...) are not used 
in loongarch, and we will add these in future.*
*or we can add the following patch (now **AT_HWCAP only) though not woking: ****>>>>>>>>>>>*

diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h
index 0dfe78c217..ef248095b9 100644
--- a/sysdeps/loongarch/dl-irel.h
+++ b/sysdeps/loongarch/dl-irel.h
@@ -21,13 +21,18 @@
  
  #include <stdio.h>
  #include <unistd.h>
+#include <ldsodefs.h>
+#include <sysdep.h>
  
  #define ELF_MACHINE_IRELA 1
  
  static inline ElfW (Addr) __attribute ((always_inline))
  elf_ifunc_invoke (ElfW (Addr) addr)
  {
-  return ((ElfW (Addr) (*) (void)) (addr)) ();
+  /* The second argument is a void pointer to preserve the extension
+     fexibility.  */
+  return ((ElfW(Addr) (*) (uint64_t, void *)) (addr))
+        (GLRO(dl_hwcap), NULL);
  }
  
  static inline void __attribute ((always_inline))

*<<<<<<<<<<<<<<<<<<*





在 2022/6/7 上午2:36, Adhemerval Zanella 写道:
> On 31/05/2022 23:18, caiyinyu wrote:
>> ---
>>   sysdeps/loongarch/dl-irel.h                   |  48 +++++++++
>>   sysdeps/loongarch/nptl/pthreaddef.h           |  32 ++++++
>>   .../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   |  79 ++++++++++++++
>>   .../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 ++++++
>>   16 files changed, 788 insertions(+)
>>   create mode 100644 sysdeps/loongarch/dl-irel.h
>>   create mode 100644 sysdeps/loongarch/nptl/pthreaddef.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
>>
>> diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h
>> new file mode 100644
>> index 0000000000..c94cba702a
>> --- /dev/null
>> +++ b/sysdeps/loongarch/dl-irel.h
>> @@ -0,0 +1,48 @@
>> +/* 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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +#ifndef _DL_IREL_H
>> +#define _DL_IREL_H
>> +
>> +#include <stdio.h>
>> +#include <unistd.h>
>> +
>> +#define ELF_MACHINE_IRELA 1
>> +
>> +static inline ElfW (Addr) __attribute ((always_inline))
>> +elf_ifunc_invoke (ElfW (Addr) addr)
>> +{
>> +  return ((ElfW (Addr) (*) (void)) (addr)) ();
> At least for RISCV, sparc, aarch64, powerpc, arm; the ifunc resolver expects
> a unsigned long int begin the hardware capability from kernelk (AT_HWCAP).
>
> AArch64 also extends it by passing both uint64_t and a struct with both
> AT_HWCAP and AT_HWCAP2.  I am not sure if loongarch will ever use more
> than the AT_HWCAP.
>
>> +}
>> +
>> +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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +/* 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/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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +#ifndef _FCNTL_H
>> +#error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
>> +#endif
>> +
>> +#include <bits/wordsize.h>
>> +
>> +/* 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 <bits/fcntl-linux.h>
>> 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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +#ifndef _SYS_PROCFS_H
>> +# error "Never include <bits/procfs.h> directly; use <sys/procfs.h> 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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +/* 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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +#ifndef _BITS_SIGSTACK_H
>> +#define _BITS_SIGSTACK_H 1
>> +
>> +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H
>> +# error "Never include this file directly.  Use <signal.h> 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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +#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..d29c8056cb
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/loongarch/makecontext.c
>> @@ -0,0 +1,79 @@
>> +/* 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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +#include <sysdep.h>
>> +#include <sys/asm.h>
>> +#include <sys/ucontext.h>
>> +#include <stdarg.h>
>> +#include <assert.h>
>> +
>> +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;
>> +  long int i, sp;
>> +
>> +  _Static_assert(LARCH_REG_NARGS == 8,
>> +		 "__makecontext assumes 8 argument registers");
>> +
>> +  /* Set up the stack.  */
>> +  sp = ((long int) 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] = 0;
>> +  ucp->uc_mcontext.__gregs[LARCH_REG_S0] = 0;
>> +  ucp->uc_mcontext.__gregs[LARCH_REG_S1] = (long int) func;
>> +  ucp->uc_mcontext.__gregs[LARCH_REG_S2] = (long int) ucp->uc_link;
>> +  ucp->uc_mcontext.__gregs[LARCH_REG_SP] = sp;
>> +  ucp->uc_mcontext.__pc = (long int) &__start_context;
>> +
>> +  /* Put args in a0-a7, then put any remaining args on the stack.  */
>> +  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 0] = a0;
>> +  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 1] = a1;
>> +  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 2] = a2;
>> +  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 3] = a3;
>> +  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 4] = a4;
>> +
>> +  if (__glibc_unlikely (argc > 5))
>> +    {
>> +      va_list vl;
>> +      va_start (vl, a4);
>> +
>> +      long reg_args = argc < LARCH_REG_NARGS ? argc : LARCH_REG_NARGS;
>> +      for (i = 5; i < reg_args; i++)
>> +	ucp->uc_mcontext.__gregs[LARCH_REG_A0 + i] = va_arg (vl, long);
>> +
>> +      long int stack_args = argc - reg_args;
>> +      if (stack_args > 0)
>> +	{
>> +	  sp = (sp - stack_args * sizeof (long int)) & ALMASK;
>> +	  ucp->uc_mcontext.__gregs[LARCH_REG_SP] = sp;
>> +	  for (i = 0; i < stack_args; i++)
>> +	    ((long int *) sp)[i] = va_arg (vl, 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..a1216dad69
>> --- /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
>> +<https://www.gnu.org/licenses/>.  */
>> +#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		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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +#ifndef _SIGCONTEXTINFO_H
>> +#define _SIGCONTEXTINFO_H
>> +
>> +#include <stdint.h>
>> +#include <sys/ucontext.h>
>> +
>> +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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +#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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +/* 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 <features.h>
>> +
>> +#include <bits/types/sigset_t.h>
>> +#include <bits/types/stack_t.h>
>> +
>> +#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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +#ifndef _SYS_USER_H
>> +#define _SYS_USER_H 1
>> +
>> +#include <stdint.h>
>> +
>> +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
>> +<https://www.gnu.org/licenses/>.  */
>> +
>> +#ifndef _LINUX_LOONGARCH_UCONTEXT_MACROS_H
>> +#define _LINUX_LOONGARCH_UCONTEXT_MACROS_H
>> +
>> +#include <sysdep.h>
>> +#include <sys/asm.h>
>> +#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 <inttypes.h>
>> +#include <signal.h>
>> +#include <stddef.h>
>> +#include <sys/ucontext.h>
>> +
>> +-- 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)
Adhemerval Zanella June 7, 2022, 1:56 p.m. UTC | #3
On 07/06/2022 06:32, caiyinyu wrote:
> +static inline ElfW (Addr) __attribute ((always_inline))
> +elf_ifunc_invoke (ElfW (Addr) addr)
> +{
> +  return ((ElfW (Addr) (*) (void)) (addr)) ();
> 
> At least for RISCV, sparc, aarch64, powerpc, arm; the ifunc resolver expects
> a unsigned long int begin the hardware capability from kernelk (AT_HWCAP).
> 
> AArch64 also extends it by passing both uint64_t and a struct with both
> AT_HWCAP and AT_HWCAP2.  I am not sure if loongarch will ever use more
> than the AT_HWCAP.
> *Currently ifuncs (like __memchr_ifunc, __memcpy_ifunc ...) are not used in loongarch, and we will add these in future.*
> *or we can add the following patch (now **AT_HWCAP only) though not woking: ****>>>>>>>>>>>*
> 
> diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h
> index 0dfe78c217..ef248095b9 100644
> --- a/sysdeps/loongarch/dl-irel.h
> +++ b/sysdeps/loongarch/dl-irel.h
> @@ -21,13 +21,18 @@
>  
>  #include <stdio.h>
>  #include <unistd.h>
> +#include <ldsodefs.h>
> +#include <sysdep.h>
>  
>  #define ELF_MACHINE_IRELA 1
>  
>  static inline ElfW (Addr) __attribute ((always_inline))
>  elf_ifunc_invoke (ElfW (Addr) addr)
>  {
> -  return ((ElfW (Addr) (*) (void)) (addr)) ();
> +  /* The second argument is a void pointer to preserve the extension
> +     fexibility.  */
> +  return ((ElfW(Addr) (*) (uint64_t, void *)) (addr))
> +        (GLRO(dl_hwcap), NULL);
>  }
>  
>  static inline void __attribute ((always_inline))
> 
> *<<<<<<<<<<<<<<<<<<*

AArch64 added the extra argument to preserve backwards compatibility, which
is not the case here.  Since ifunc is also used outside glibc, maybe it would
be better to  use the extendable struct as default:


 struct __ifunc_arg_t
 {
   unsigned long int _size; /* Size of the struct, so it can grow.  */
   unsigned long int _hwcap;
 };

 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) (*) (uint64_t, void *)) (addr)) (&arg);
 }

And then export __ifunc_arg_t on the sys/ifunc.h header like aarch64.
caiyinyu June 8, 2022, 6:01 a.m. UTC | #4
I made some changes:

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 *, void *)*) (addr))
*(&arg, NULL)*;
}

otherwise:

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) (*) *(uint64_t, void *)*) (addr))
*((uint64_t) &arg, NULL)*;
}

THANKS.


 >>>>>>>>>>>>>>

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
+   <https://www.gnu.org/licenses/>.  */
+
+#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

<<<<<<<<<<<<<<


在 2022/6/7 下午9:56, Adhemerval Zanella 写道:
>
> On 07/06/2022 06:32, caiyinyu wrote:
>> +static inline ElfW (Addr) __attribute ((always_inline))
>> +elf_ifunc_invoke (ElfW (Addr) addr)
>> +{
>> +  return ((ElfW (Addr) (*) (void)) (addr)) ();
>>
>> At least for RISCV, sparc, aarch64, powerpc, arm; the ifunc resolver expects
>> a unsigned long int begin the hardware capability from kernelk (AT_HWCAP).
>>
>> AArch64 also extends it by passing both uint64_t and a struct with both
>> AT_HWCAP and AT_HWCAP2.  I am not sure if loongarch will ever use more
>> than the AT_HWCAP.
>> *Currently ifuncs (like __memchr_ifunc, __memcpy_ifunc ...) are not used in loongarch, and we will add these in future.*
>> *or we can add the following patch (now **AT_HWCAP only) though not woking: ****>>>>>>>>>>>*
>>
>> diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h
>> index 0dfe78c217..ef248095b9 100644
>> --- a/sysdeps/loongarch/dl-irel.h
>> +++ b/sysdeps/loongarch/dl-irel.h
>> @@ -21,13 +21,18 @@
>>   
>>   #include <stdio.h>
>>   #include <unistd.h>
>> +#include <ldsodefs.h>
>> +#include <sysdep.h>
>>   
>>   #define ELF_MACHINE_IRELA 1
>>   
>>   static inline ElfW (Addr) __attribute ((always_inline))
>>   elf_ifunc_invoke (ElfW (Addr) addr)
>>   {
>> -  return ((ElfW (Addr) (*) (void)) (addr)) ();
>> +  /* The second argument is a void pointer to preserve the extension
>> +     fexibility.  */
>> +  return ((ElfW(Addr) (*) (uint64_t, void *)) (addr))
>> +        (GLRO(dl_hwcap), NULL);
>>   }
>>   
>>   static inline void __attribute ((always_inline))
>>
>> *<<<<<<<<<<<<<<<<<<*
> AArch64 added the extra argument to preserve backwards compatibility, which
> is not the case here.  Since ifunc is also used outside glibc, maybe it would
> be better to  use the extendable struct as default:
>
>
>   struct __ifunc_arg_t
>   {
>     unsigned long int _size; /* Size of the struct, so it can grow.  */
>     unsigned long int _hwcap;
>   };
>
>   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) (*) (uint64_t, void *)) (addr)) (&arg);
>   }
>
> And then export __ifunc_arg_t on the sys/ifunc.h header like aarch64.
Adhemerval Zanella June 8, 2022, 1:16 p.m. UTC | #5
On 08/06/2022 03:01, caiyinyu wrote:
> 
> I made some changes:
> 
> 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 *, void *)*) (addr))
>          *(&arg, NULL)*;
> }
> 

Why would you need the extra argument if now you are passing a struct?
The idea is if you need extra space (for instance to pack another
hwcap or any other arch-specific information) you define a new 
__ifunc_arg_t with a different name.  The resolver function will then
check the size before accessing the correct expected struct.

> otherwise:
> 
> 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) (*) *(uint64_t, void *)*) (addr))
>          *((uint64_t) &arg, NULL)*;
> }
> 

I would prefer to avoid alising violations if possible (and uint64_t is
not usually the correct type for pointer to integer conversion).

> THANKS.
> 
> 
>>>>>>>>>>>>>>>
> 
> 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#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
> 
> <<<<<<<<<<<<<<
> 
> 
> 在 2022/6/7 下午9:56, Adhemerval Zanella 写道:
>> On 07/06/2022 06:32, caiyinyu wrote:
>>> +static inline ElfW (Addr) __attribute ((always_inline))
>>> +elf_ifunc_invoke (ElfW (Addr) addr)
>>> +{
>>> +  return ((ElfW (Addr) (*) (void)) (addr)) ();
>>>
>>> At least for RISCV, sparc, aarch64, powerpc, arm; the ifunc resolver expects
>>> a unsigned long int begin the hardware capability from kernelk (AT_HWCAP).
>>>
>>> AArch64 also extends it by passing both uint64_t and a struct with both
>>> AT_HWCAP and AT_HWCAP2.  I am not sure if loongarch will ever use more
>>> than the AT_HWCAP.
>>> *Currently ifuncs (like __memchr_ifunc, __memcpy_ifunc ...) are not used in loongarch, and we will add these in future.*
>>> *or we can add the following patch (now **AT_HWCAP only) though not woking: ****>>>>>>>>>>>*
>>>
>>> diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h
>>> index 0dfe78c217..ef248095b9 100644
>>> --- a/sysdeps/loongarch/dl-irel.h
>>> +++ b/sysdeps/loongarch/dl-irel.h
>>> @@ -21,13 +21,18 @@
>>>  
>>>  #include <stdio.h>
>>>  #include <unistd.h>
>>> +#include <ldsodefs.h>
>>> +#include <sysdep.h>
>>>  
>>>  #define ELF_MACHINE_IRELA 1
>>>  
>>>  static inline ElfW (Addr) __attribute ((always_inline))
>>>  elf_ifunc_invoke (ElfW (Addr) addr)
>>>  {
>>> -  return ((ElfW (Addr) (*) (void)) (addr)) ();
>>> +  /* The second argument is a void pointer to preserve the extension
>>> +     fexibility.  */
>>> +  return ((ElfW(Addr) (*) (uint64_t, void *)) (addr))
>>> +        (GLRO(dl_hwcap), NULL);
>>>  }
>>>  
>>>  static inline void __attribute ((always_inline))
>>>
>>> *<<<<<<<<<<<<<<<<<<*
>> AArch64 added the extra argument to preserve backwards compatibility, which
>> is not the case here.  Since ifunc is also used outside glibc, maybe it would
>> be better to  use the extendable struct as default:
>>
>>
>>  struct __ifunc_arg_t
>>  {
>>    unsigned long int _size; /* Size of the struct, so it can grow.  */
>>    unsigned long int _hwcap;
>>  };
>>
>>  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) (*) (uint64_t, void *)) (addr)) (&arg);
>>  }
>>
>> And then export __ifunc_arg_t on the sys/ifunc.h header like aarch64.
caiyinyu June 9, 2022, 4:01 a.m. UTC | #6
Fixed. Thanks.

 >>>>>>>>>>>>>

diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h
index 0dfe78c217..4440453f06 100644
--- a/sysdeps/loongarch/dl-irel.h
+++ b/sysdeps/loongarch/dl-irel.h
@@ -21,13 +21,19 @@

  #include <stdio.h>
  #include <unistd.h>
+#include <sys/ifunc.h>

  #define ELF_MACHINE_IRELA 1

  static inline ElfW (Addr) __attribute ((always_inline))
  elf_ifunc_invoke (ElfW (Addr) addr)
  {
-  return ((ElfW (Addr) (*) (void)) (addr)) ();
+  __ifunc_arg_t arg =
+  {
+    ._size = sizeof (__ifunc_arg_t),
+    ._hwcap = GLRO(dl_hwcap),
+  };
+  return ((ElfW(Addr) (*) (const __ifunc_arg_t *)) (addr)) (&arg);
  }

<<<<<<<<<<<<<<<<


在 2022/6/8 下午9:16, Adhemerval Zanella 写道:
>
> On 08/06/2022 03:01, caiyinyu wrote:
>> I made some changes:
>>
>> 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 *, void *)*) (addr))
>>           *(&arg, NULL)*;
>> }
>>
> Why would you need the extra argument if now you are passing a struct?
> The idea is if you need extra space (for instance to pack another
> hwcap or any other arch-specific information) you define a new
> __ifunc_arg_t with a different name.  The resolver function will then
> check the size before accessing the correct expected struct.
>
>> otherwise:
>>
>> 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) (*) *(uint64_t, void *)*) (addr))
>>           *((uint64_t) &arg, NULL)*;
>> }
>>
> I would prefer to avoid alising violations if possible (and uint64_t is
> not usually the correct type for pointer to integer conversion).
>
>> THANKS.
>>
>>
>> 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
>> +   <https://www.gnu.org/licenses/>.  */
>> +
>> +#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
>>
>> <<<<<<<<<<<<<<
>>
>>
>> 在 2022/6/7 下午9:56, Adhemerval Zanella 写道:
>>> On 07/06/2022 06:32, caiyinyu wrote:
>>>> +static inline ElfW (Addr) __attribute ((always_inline))
>>>> +elf_ifunc_invoke (ElfW (Addr) addr)
>>>> +{
>>>> +  return ((ElfW (Addr) (*) (void)) (addr)) ();
>>>>
>>>> At least for RISCV, sparc, aarch64, powerpc, arm; the ifunc resolver expects
>>>> a unsigned long int begin the hardware capability from kernelk (AT_HWCAP).
>>>>
>>>> AArch64 also extends it by passing both uint64_t and a struct with both
>>>> AT_HWCAP and AT_HWCAP2.  I am not sure if loongarch will ever use more
>>>> than the AT_HWCAP.
>>>> *Currently ifuncs (like __memchr_ifunc, __memcpy_ifunc ...) are not used in loongarch, and we will add these in future.*
>>>> *or we can add the following patch (now **AT_HWCAP only) though not woking: ****>>>>>>>>>>>*
>>>>
>>>> diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h
>>>> index 0dfe78c217..ef248095b9 100644
>>>> --- a/sysdeps/loongarch/dl-irel.h
>>>> +++ b/sysdeps/loongarch/dl-irel.h
>>>> @@ -21,13 +21,18 @@
>>>>   
>>>>   #include <stdio.h>
>>>>   #include <unistd.h>
>>>> +#include <ldsodefs.h>
>>>> +#include <sysdep.h>
>>>>   
>>>>   #define ELF_MACHINE_IRELA 1
>>>>   
>>>>   static inline ElfW (Addr) __attribute ((always_inline))
>>>>   elf_ifunc_invoke (ElfW (Addr) addr)
>>>>   {
>>>> -  return ((ElfW (Addr) (*) (void)) (addr)) ();
>>>> +  /* The second argument is a void pointer to preserve the extension
>>>> +     fexibility.  */
>>>> +  return ((ElfW(Addr) (*) (uint64_t, void *)) (addr))
>>>> +        (GLRO(dl_hwcap), NULL);
>>>>   }
>>>>   
>>>>   static inline void __attribute ((always_inline))
>>>>
>>>> *<<<<<<<<<<<<<<<<<<*
>>> AArch64 added the extra argument to preserve backwards compatibility, which
>>> is not the case here.  Since ifunc is also used outside glibc, maybe it would
>>> be better to  use the extendable struct as default:
>>>
>>>
>>>   struct __ifunc_arg_t
>>>   {
>>>     unsigned long int _size; /* Size of the struct, so it can grow.  */
>>>     unsigned long int _hwcap;
>>>   };
>>>
>>>   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) (*) (uint64_t, void *)) (addr)) (&arg);
>>>   }
>>>
>>> And then export __ifunc_arg_t on the sys/ifunc.h header like aarch64.
diff mbox series

Patch

diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h
new file mode 100644
index 0000000000..c94cba702a
--- /dev/null
+++ b/sysdeps/loongarch/dl-irel.h
@@ -0,0 +1,48 @@ 
+/* 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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _DL_IREL_H
+#define _DL_IREL_H
+
+#include <stdio.h>
+#include <unistd.h>
+
+#define ELF_MACHINE_IRELA 1
+
+static inline ElfW (Addr) __attribute ((always_inline))
+elf_ifunc_invoke (ElfW (Addr) addr)
+{
+  return ((ElfW (Addr) (*) (void)) (addr)) ();
+}
+
+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
+   <https://www.gnu.org/licenses/>.  */
+
+/* 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/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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _FCNTL_H
+#error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
+#endif
+
+#include <bits/wordsize.h>
+
+/* 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 <bits/fcntl-linux.h>
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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_PROCFS_H
+# error "Never include <bits/procfs.h> directly; use <sys/procfs.h> 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
+   <https://www.gnu.org/licenses/>.  */
+
+/* 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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_SIGSTACK_H
+#define _BITS_SIGSTACK_H 1
+
+#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H
+# error "Never include this file directly.  Use <signal.h> 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
+   <https://www.gnu.org/licenses/>.  */
+
+#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..d29c8056cb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/makecontext.c
@@ -0,0 +1,79 @@ 
+/* 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+#include <sys/ucontext.h>
+#include <stdarg.h>
+#include <assert.h>
+
+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;
+  long int i, sp;
+
+  _Static_assert(LARCH_REG_NARGS == 8,
+		 "__makecontext assumes 8 argument registers");
+
+  /* Set up the stack.  */
+  sp = ((long int) 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] = 0;
+  ucp->uc_mcontext.__gregs[LARCH_REG_S0] = 0;
+  ucp->uc_mcontext.__gregs[LARCH_REG_S1] = (long int) func;
+  ucp->uc_mcontext.__gregs[LARCH_REG_S2] = (long int) ucp->uc_link;
+  ucp->uc_mcontext.__gregs[LARCH_REG_SP] = sp;
+  ucp->uc_mcontext.__pc = (long int) &__start_context;
+
+  /* Put args in a0-a7, then put any remaining args on the stack.  */
+  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 0] = a0;
+  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 1] = a1;
+  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 2] = a2;
+  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 3] = a3;
+  ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 4] = a4;
+
+  if (__glibc_unlikely (argc > 5))
+    {
+      va_list vl;
+      va_start (vl, a4);
+
+      long reg_args = argc < LARCH_REG_NARGS ? argc : LARCH_REG_NARGS;
+      for (i = 5; i < reg_args; i++)
+	ucp->uc_mcontext.__gregs[LARCH_REG_A0 + i] = va_arg (vl, long);
+
+      long int stack_args = argc - reg_args;
+      if (stack_args > 0)
+	{
+	  sp = (sp - stack_args * sizeof (long int)) & ALMASK;
+	  ucp->uc_mcontext.__gregs[LARCH_REG_SP] = sp;
+	  for (i = 0; i < stack_args; i++)
+	    ((long int *) sp)[i] = va_arg (vl, 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..a1216dad69
--- /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
+   <https://www.gnu.org/licenses/>.  */
+#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		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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _SIGCONTEXTINFO_H
+#define _SIGCONTEXTINFO_H
+
+#include <stdint.h>
+#include <sys/ucontext.h>
+
+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
+   <https://www.gnu.org/licenses/>.  */
+
+#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
+   <https://www.gnu.org/licenses/>.  */
+
+/* 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 <features.h>
+
+#include <bits/types/sigset_t.h>
+#include <bits/types/stack_t.h>
+
+#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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_USER_H
+#define _SYS_USER_H 1
+
+#include <stdint.h>
+
+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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _LINUX_LOONGARCH_UCONTEXT_MACROS_H
+#define _LINUX_LOONGARCH_UCONTEXT_MACROS_H
+
+#include <sysdep.h>
+#include <sys/asm.h>
+#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 <inttypes.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/ucontext.h>
+
+-- 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)