[v4,09/13] LoongArch: Linux ABI

Message ID 20220509022611.1248063-10-caiyinyu@loongson.cn
State Superseded
Headers
Series GLIBC LoongArch PATCHES |

Commit Message

caiyinyu May 9, 2022, 2:26 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

Arnd Bergmann May 11, 2022, 7:08 a.m. UTC | #1
On Mon, May 9, 2022 at 4:26 AM caiyinyu <caiyinyu@loongson.cn> wrote:
> +
> +#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

Not sure why these are provided here, the kernel has no loongarch64 specific
interface for flock in the current version, so either this refers to
an older version
of the kernel port, or it is something that could be generalized into an
architecture-independent file in glibc.

        Arnd
  
Adhemerval Zanella May 11, 2022, 1:27 p.m. UTC | #2
On 11/05/2022 04:08, Arnd Bergmann wrote:
> On Mon, May 9, 2022 at 4:26 AM caiyinyu <caiyinyu@loongson.cn> wrote:
>> +
>> +#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
> 
> Not sure why these are provided here, the kernel has no loongarch64 specific
> interface for flock in the current version, so either this refers to
> an older version
> of the kernel port, or it is something that could be generalized into an
> architecture-independent file in glibc.

Indeed this is a missing spot in Linux support, the generic
sysdeps/unix/sysv/linux/bits/fcntl.h is just a #error stating each
architecture should define its own.

glibc does have a generic interface on generic subfolder,
sysdeps/unix/sysv/linux/generic/bits/fcntl.h; however loongarch is
not using it because it does not add the folder on 
sysdeps/unix/sysv/linux/loongarch/Implies. NIOS2, for instance,
which as the original architecture that pushed for the generic
folder (as a easier way to provide the new UAPI kernel definitions)
has:

$ cat ./sysdeps/unix/sysv/linux/nios2/Implies
nios2/nptl
unix/sysv/linux/generic/wordsize-32
unix/sysv/linux/generic

Making loongarch use it will change some implementation selections,
so it would require to check it it is ok for the architecture.

My long term plan is to just remove the generic and subfolder to avoid
this exact confusion.
  
Joseph Myers May 11, 2022, 5:32 p.m. UTC | #3
On Wed, 11 May 2022, Adhemerval Zanella via Libc-alpha wrote:

> glibc does have a generic interface on generic subfolder,
> sysdeps/unix/sysv/linux/generic/bits/fcntl.h; however loongarch is
> not using it because it does not add the folder on 
> sysdeps/unix/sysv/linux/loongarch/Implies. NIOS2, for instance,
> which as the original architecture that pushed for the generic
> folder (as a easier way to provide the new UAPI kernel definitions)
> has:

generic was originally added to glibc for Tile (the Tile port having since 
been removed from glibc after it was removed from the kernel).
  
caiyinyu May 15, 2022, 3:32 a.m. UTC | #4
在 2022/5/11 下午3:08, Arnd Bergmann 写道:
> On Mon, May 9, 2022 at 4:26 AM caiyinyu <caiyinyu@loongson.cn> wrote:
>> +
>> +#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
> Not sure why these are provided here, the kernel has no loongarch64 specific
> interface for flock in the current version, so either this refers to
> an older version
> of the kernel port, or it is something that could be generalized into an
> architecture-independent file in glibc.
>
>          Arnd


There are struct flock and flock64 we need in glibc bits/fcntl.h, but
the macro F_GETLK64 F_SETLK64 F_SETLKW64 in
sysdeps/unix/sysv/linux/bits/fcntl-linux.h are:

...
# define F_GETLK64      12      /* Get record locking info.  */
# define F_SETLK64      13      /* Set record locking info 
(non-blocking).  */
# define F_SETLKW64     14      /* Set record locking info (blocking).  */
...

what we need:

+#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).  */

x86 ia64 s390 and aarch64 have the same problem and they all use their 
own fcntl.h.

Define new value of these macro in 
sysdeps/unix/sysv/linux/bits/fcntl-linux.h or
add fcntl-linux.h in loongarch port or keep the status quo??

any ideas??
  
Adhemerval Zanella May 16, 2022, 6:49 p.m. UTC | #5
On 15/05/2022 00:32, caiyinyu wrote:
> 
> 在 2022/5/11 下午3:08, Arnd Bergmann 写道:
>> On Mon, May 9, 2022 at 4:26 AM caiyinyu <caiyinyu@loongson.cn> wrote:
>>> +
>>> +#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
>> Not sure why these are provided here, the kernel has no loongarch64 specific
>> interface for flock in the current version, so either this refers to
>> an older version
>> of the kernel port, or it is something that could be generalized into an
>> architecture-independent file in glibc.
>>
>>          Arnd
> 
> 
> There are struct flock and flock64 we need in glibc bits/fcntl.h, but
> the macro F_GETLK64 F_SETLK64 F_SETLKW64 in
> sysdeps/unix/sysv/linux/bits/fcntl-linux.h are:
> 
> ...
> # define F_GETLK64      12      /* Get record locking info.  */
> # define F_SETLK64      13      /* Set record locking info (non-blocking).  */
> # define F_SETLKW64     14      /* Set record locking info (blocking).  */
> ...
> 
> what we need:
> 
> +#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).  */
> 
> x86 ia64 s390 and aarch64 have the same problem and they all use their own fcntl.h.
> 
> Define new value of these macro in sysdeps/unix/sysv/linux/bits/fcntl-linux.h or
> add fcntl-linux.h in loongarch port or keep the status quo??

Ideally I would like to have sysdeps/unix/sysv/linux/bits/fcntl.h with the
common fcntl.h definitions (including flock/flock64 definitions) and move
any arch-specific bits to sysdeps/unix/sysv/linux/<arch>/bits/fcntl-arch.h
and have a generic fcntl-arch.h with current linux UAPI definition (so
newer ports won't need to add anything, assuming its uses the expected
Linux definitions).

It would require to change some non loongarch code, so I don't expect you
do push for this to get the loongarch code.  Having a loonarch fcntl.h
should be fine for now.
  
caiyinyu May 18, 2022, 3:40 a.m. UTC | #6
在 2022/5/11 下午3:08, Arnd Bergmann 写道:
> On Mon, May 9, 2022 at 4:26 AM caiyinyu <caiyinyu@loongson.cn> wrote:
>> +
>> +#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
> Not sure why these are provided here, the kernel has no loongarch64 
> specific
> interface for flock in the current version, so either this refers to
> an older version
> of the kernel port, or it is something that could be generalized into an
> architecture-independent file in glibc.
>
> Arnd


There are struct flock and flock64 we need in glibc bits/fcntl.h, but
the macro F_GETLK64 F_SETLK64 F_SETLKW64 in
sysdeps/unix/sysv/linux/bits/fcntl-linux.h are:

...
# define F_GETLK64      12      /* Get record locking info.  */
# define F_SETLK64      13      /* Set record locking info 
(non-blocking).  */
# define F_SETLKW64     14      /* Set record locking info (blocking).  */
...

what we need:

+#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).  */

x86 ia64 s390 and aarch64 have the same problem and they all use their 
own fcntl.h.

Define new value of these macro in 
sysdeps/unix/sysv/linux/bits/fcntl-linux.h or
add fcntl-linux.h in loongarch port or keep the status quo??

any ideas??

Thanks.
  
Arnd Bergmann May 18, 2022, 7:33 a.m. UTC | #7
On Wed, May 18, 2022 at 4:40 AM caiyinyu <caiyinyu@loongson.cn> wrote:
> 在 2022/5/11 下午3:08, Arnd Bergmann 写道:
> > On Mon, May 9, 2022 at 4:26 AM caiyinyu <caiyinyu@loongson.cn> wrote:
>
> There are struct flock and flock64 we need in glibc bits/fcntl.h, but
> the macro F_GETLK64 F_SETLK64 F_SETLKW64 in
> sysdeps/unix/sysv/linux/bits/fcntl-linux.h are:
>
> ...
> # define F_GETLK64      12      /* Get record locking info.  */
> # define F_SETLK64      13      /* Set record locking info
> (non-blocking).  */
> # define F_SETLKW64     14      /* Set record locking info (blocking).  */
> ...
>
> what we need:
>
> +#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).  */
>
> x86 ia64 s390 and aarch64 have the same problem and they all use their
> own fcntl.h.
>
> Define new value of these macro in
> sysdeps/unix/sysv/linux/bits/fcntl-linux.h or
> add fcntl-linux.h in loongarch port or keep the status quo??
>
> any ideas??

I think the problem is different views of the macros in Linux and glibc:

- In Linux, all 32-bit architectures use the 'flock64' interface, while
  all 64-bit architectures use 'flock'. Older 32-bit architectures
  also provide the 32-bit 'off_t' interfaces with 'flock' for compatibility
  with existing user space.

- glibc describes the same interfaces differently. Here, all architectures
  have both the traditional 'flock' and the new 'flock64' version that
  gets used when building with largerfile64 support enabled, but they
  may get aliased to the same one depending on which off_t definition
  glibc was using when the port was started.

Adhemerval's suggestion for addressing this in glibc sounds good to
me, so you can just keep you extra copy of the same logic for
the moment and someone can consolidate the workarounds for
64-bit architectures in the future.

          Arnd
  

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)