[v4,06/13] C-SKY: Linux ABI

Message ID 53924daa4b51c0d552d17d3c5fd9aea09f9fc4b2.1536720821.git.han_mao@c-sky.com
State New, archived
Headers

Commit Message

毛晗 Sept. 12, 2018, 2:56 a.m. UTC
  Linux-specific code that is required for maintaining ABI compatibility.
This doesn't contain the actual system call interface.

	* sysdeps/unix/sysv/linux/csky/Versions: Likewise.
	* sysdeps/unix/sysv/linux/csky/bits/mman.h: New file.
	* sysdeps/unix/sysv/linux/csky/bits/shm.h: Likewise.
	* sysdeps/unix/sysv/linux/csky/c++-types.data: Likewise.
	* sysdeps/unix/sysv/linux/csky/abiv2/ucontext_i.sym: Likewise.
	* sysdeps/unix/sysv/linux/csky/ipc_priv.h: Likewise.
	* sysdeps/unix/sysv/linux/csky/jmp_buf-macros.h: Likewise.
	* sysdeps/unix/sysv/linux/csky/kernel-features.h: Likewise.
	* sysdeps/unix/sysv/linux/csky/localplt.data: Likewise.
	* sysdeps/unix/sysv/linux/csky/makecontext.c: Likewise.
	* sysdeps/unix/sysv/linux/csky/profil-counter.h: Likewise.
	* sysdeps/unix/sysv/linux/csky/register-dump.h: Likewise.
	* sysdeps/unix/sysv/linux/csky/shlib-versions: Likewise.
	* sysdeps/unix/sysv/linux/csky/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/csky/sys/cachectl.h: Likewise.
	* sysdeps/unix/sysv/linux/csky/sys/procfs.h: Likewise.
	* sysdeps/unix/sysv/linux/csky/sys/ucontext.h: Likewise.
	* sysdeps/unix/sysv/linux/csky/sys/user.h: Likewise.
	* sysdeps/unix/sysv/linux/csky/sysdep.h: Likewise.
---
 sysdeps/unix/sysv/linux/csky/Versions             |   5 +
 sysdeps/unix/sysv/linux/csky/abiv2/ucontext_i.sym |  32 ++
 sysdeps/unix/sysv/linux/csky/bits/mman.h          |  44 ++
 sysdeps/unix/sysv/linux/csky/bits/shm.h           | 104 +++++
 sysdeps/unix/sysv/linux/csky/c++-types.data       |  67 +++
 sysdeps/unix/sysv/linux/csky/ipc_priv.h           |  21 +
 sysdeps/unix/sysv/linux/csky/jmp_buf-macros.h     |   6 +
 sysdeps/unix/sysv/linux/csky/kernel-features.h    |  23 +
 sysdeps/unix/sysv/linux/csky/localplt.data        |  19 +
 sysdeps/unix/sysv/linux/csky/makecontext.c        |  74 +++
 sysdeps/unix/sysv/linux/csky/profil-counter.h     |  31 ++
 sysdeps/unix/sysv/linux/csky/register-dump.h      | 193 ++++++++
 sysdeps/unix/sysv/linux/csky/shlib-versions       |   7 +
 sysdeps/unix/sysv/linux/csky/sigcontextinfo.h     |  32 ++
 sysdeps/unix/sysv/linux/csky/sys/cachectl.h       |  38 ++
 sysdeps/unix/sysv/linux/csky/sys/procfs.h         | 123 +++++
 sysdeps/unix/sysv/linux/csky/sys/ucontext.h       |  89 ++++
 sysdeps/unix/sysv/linux/csky/sys/user.h           |  60 +++
 sysdeps/unix/sysv/linux/csky/sysdep.h             | 534 ++++++++++++++++++++++
 19 files changed, 1502 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/csky/Versions
 create mode 100644 sysdeps/unix/sysv/linux/csky/abiv2/ucontext_i.sym
 create mode 100644 sysdeps/unix/sysv/linux/csky/bits/mman.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/bits/shm.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/c++-types.data
 create mode 100644 sysdeps/unix/sysv/linux/csky/ipc_priv.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/jmp_buf-macros.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/kernel-features.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/localplt.data
 create mode 100644 sysdeps/unix/sysv/linux/csky/makecontext.c
 create mode 100644 sysdeps/unix/sysv/linux/csky/profil-counter.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/register-dump.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/shlib-versions
 create mode 100644 sysdeps/unix/sysv/linux/csky/sigcontextinfo.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/sys/cachectl.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/sys/procfs.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/sys/ucontext.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/sys/user.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/sysdep.h
  

Comments

Arnd Bergmann Sept. 12, 2018, 1:40 p.m. UTC | #1
On Wed, Sep 12, 2018 at 4:58 AM Mao Han <han_mao@c-sky.com> wrote:
>
> Linux-specific code that is required for maintaining ABI compatibility.
> This doesn't contain the actual system call interface.
>
>         * sysdeps/unix/sysv/linux/csky/Versions: Likewise.
>         * sysdeps/unix/sysv/linux/csky/bits/mman.h: New file.
>         * sysdeps/unix/sysv/linux/csky/bits/shm.h: Likewise.
>         * sysdeps/unix/sysv/linux/csky/c++-types.data: Likewise.
>         * sysdeps/unix/sysv/linux/csky/abiv2/ucontext_i.sym: Likewise.
>         * sysdeps/unix/sysv/linux/csky/ipc_priv.h: Likewise.
>         * sysdeps/unix/sysv/linux/csky/jmp_buf-macros.h: Likewise.
>         * sysdeps/unix/sysv/linux/csky/kernel-features.h: Likewise.
>         * sysdeps/unix/sysv/linux/csky/localplt.data: Likewise.
>         * sysdeps/unix/sysv/linux/csky/makecontext.c: Likewise.
>         * sysdeps/unix/sysv/linux/csky/profil-counter.h: Likewise.
>         * sysdeps/unix/sysv/linux/csky/register-dump.h: Likewise.
>         * sysdeps/unix/sysv/linux/csky/shlib-versions: Likewise.
>         * sysdeps/unix/sysv/linux/csky/sigcontextinfo.h: Likewise.
>         * sysdeps/unix/sysv/linux/csky/sys/cachectl.h: Likewise.
>         * sysdeps/unix/sysv/linux/csky/sys/procfs.h: Likewise.
>         * sysdeps/unix/sysv/linux/csky/sys/ucontext.h: Likewise.
>         * sysdeps/unix/sysv/linux/csky/sys/user.h: Likewise.
>         * sysdeps/unix/sysv/linux/csky/sysdep.h: Likewise.
> ---
>  sysdeps/unix/sysv/linux/csky/Versions             |   5 +
>  sysdeps/unix/sysv/linux/csky/abiv2/ucontext_i.sym |  32 ++
>  sysdeps/unix/sysv/linux/csky/bits/mman.h          |  44 ++
>  sysdeps/unix/sysv/linux/csky/bits/shm.h           | 104 +++++
>  sysdeps/unix/sysv/linux/csky/c++-types.data       |  67 +++
>  sysdeps/unix/sysv/linux/csky/ipc_priv.h           |  21 +
>  sysdeps/unix/sysv/linux/csky/jmp_buf-macros.h     |   6 +
>  sysdeps/unix/sysv/linux/csky/kernel-features.h    |  23 +
>  sysdeps/unix/sysv/linux/csky/localplt.data        |  19 +
>  sysdeps/unix/sysv/linux/csky/makecontext.c        |  74 +++
>  sysdeps/unix/sysv/linux/csky/profil-counter.h     |  31 ++
>  sysdeps/unix/sysv/linux/csky/register-dump.h      | 193 ++++++++
>  sysdeps/unix/sysv/linux/csky/shlib-versions       |   7 +
>  sysdeps/unix/sysv/linux/csky/sigcontextinfo.h     |  32 ++
>  sysdeps/unix/sysv/linux/csky/sys/cachectl.h       |  38 ++
>  sysdeps/unix/sysv/linux/csky/sys/procfs.h         | 123 +++++
>  sysdeps/unix/sysv/linux/csky/sys/ucontext.h       |  89 ++++
>  sysdeps/unix/sysv/linux/csky/sys/user.h           |  60 +++
>  sysdeps/unix/sysv/linux/csky/sysdep.h             | 534 ++++++++++++++++++++++

I'm surprised to see copies of bits/shm.h, bits/mman.h and sys/procfs.h.
Since the kernel port just uses the generic interfaces that all other
architectures used in the past decade, shouldn't the glibc defaults
match be enough here?

       Arnd
  
Joseph Myers Sept. 12, 2018, 2:21 p.m. UTC | #2
On Wed, 12 Sep 2018, Arnd Bergmann wrote:

> I'm surprised to see copies of bits/shm.h, bits/mman.h and sys/procfs.h.
> Since the kernel port just uses the generic interfaces that all other
> architectures used in the past decade, shouldn't the glibc defaults
> match be enough here?

There's no generic bits/mman.h for systems using the Linux kernel; a lot 
is shared through bits/mman-linux.h and bits/mman-shared.h, but all 
architectures need their own bits/mman.h as well.

In practice there's no generic sys/procfs.h either 
(sysdeps/unix/sysv/linux/sys/procfs.h exists but all architectures 
override it - so if there's something in common between many architectures 
such that they don't need their own files, it's quite likely that file 
does not reflect whatever is common).
  
Arnd Bergmann Sept. 12, 2018, 3:34 p.m. UTC | #3
On Wed, Sep 12, 2018 at 5:18 PM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Wed, 12 Sep 2018, Arnd Bergmann wrote:
>
> > I'm surprised to see copies of bits/shm.h, bits/mman.h and sys/procfs.h.
> > Since the kernel port just uses the generic interfaces that all other
> > architectures used in the past decade, shouldn't the glibc defaults
> > match be enough here?
>
> There's no generic bits/mman.h for systems using the Linux kernel; a lot
> is shared through bits/mman-linux.h and bits/mman-shared.h, but all
> architectures need their own bits/mman.h as well.

Ok. I checked a couple that should be using the generic kernel
implementation and found that at least nios2, aarch64 and riscv
differ only in comments, so this is probably something that can
be improved by creating a common version.

> In practice there's no generic sys/procfs.h either
> (sysdeps/unix/sysv/linux/sys/procfs.h exists but all architectures
> override it - so if there's something in common between many architectures
> such that they don't need their own files, it's quite likely that file
> does not reflect whatever is common).

This one seems worse: looking at the same architectures above,
I find that at least nios2 is wrong: pr_uid/pr_gid are declared as
'unsigned short' here, compat to a signed 'long int' for riscv and
'unsigned int' for aarch64.

In the kernel, these are all 'unsigned int' except on some older 32-bit
architectures (arm, m68k, s390-32, sh, sparc32, sparc64, and
x86-32).

Aside from that, they are basically identical, except for the
regset array types that match the number of registers.

Speaking of this file, I think we still need a solution for elf_prstatus
containing a 'timeval' after time_t becomes 64-bit wide. I actually
have a patch to change the kernel header file declaring the
same structure, but I had not realized that glibc contains another
copy.

https://sourceware.org/glibc/wiki/Y2038ProofnessDesign mentions
that type, but not what to do about it. What I did in the kernel
was to change the type of pr_utime/pr_stime/pr_cutime/pr_cstime
to something that keeps using 'long' fields. Given that we can't
change the file format in an incompatible way, and that 32-bit
is sufficient here, that seemed like the most appropriate solution.

        Arnd
  
Florian Weimer Sept. 12, 2018, 9:28 p.m. UTC | #4
On 09/12/2018 05:34 PM, Arnd Bergmann wrote:
> Speaking of this file, I think we still need a solution for elf_prstatus
> containing a 'timeval' after time_t becomes 64-bit wide. I actually
> have a patch to change the kernel header file declaring the
> same structure, but I had not realized that glibc contains another
> copy.
> 
> https://sourceware.org/glibc/wiki/Y2038ProofnessDesign  mentions
> that type, but not what to do about it. What I did in the kernel
> was to change the type of pr_utime/pr_stime/pr_cutime/pr_cstime
> to something that keeps using 'long' fields. Given that we can't
> change the file format in an incompatible way, and that 32-bit
> is sufficient here, that seemed like the most appropriate solution.

Keeping 32 bits there looks reasonable.  I thought we had a port where 
time_t isn't long, but that doesn't seem to be the case.

Ah, I think it's actually s390, where suseconds_t is int, not long.

Presumably that will need a special case so that existing format 
specifiers etc. are not disturbed unnecessarily.

Thanks,
Florian
  
毛晗 Sept. 13, 2018, 8:17 a.m. UTC | #5
On Wed, Sep 12, 2018 at 03:40:35PM +0200, Arnd Bergmann wrote:
> On Wed, Sep 12, 2018 at 4:58 AM Mao Han <han_mao@c-sky.com> wrote:
> >
> > Linux-specific code that is required for maintaining ABI compatibility.
> > This doesn't contain the actual system call interface.
> >  sysdeps/unix/sysv/linux/csky/sys/user.h           |  60 +++
> >  sysdeps/unix/sysv/linux/csky/sysdep.h             | 534 ++++++++++++++++++++++
> 
> I'm surprised to see copies of bits/shm.h, bits/mman.h and sys/procfs.h.
> Since the kernel port just uses the generic interfaces that all other
> architectures used in the past decade, shouldn't the glibc defaults
> match be enough here?
> 
>        Arnd

We have SHMLBA defined to __getpagesize () << 2 in the linux port not
__getpagesize () in the generic version in glibc. So an arch specific
bits/shm.h seems needed.
The generic sys/procfs.h in glibc define pr_uid/pr_gid as 'unsigned short',
we have __kernel_uid_t define as "unsigned int"  in linux/include/uapi/
asm-generic/posix_types.h. So I need an arch specific sys/procfs.h
with pr_uid/pr_gid define as "unsigned int".

Thanks
Han Mao
  
Arnd Bergmann Sept. 13, 2018, 8:46 a.m. UTC | #6
On Thu, Sep 13, 2018 at 10:17 AM Mao Han <han_mao@c-sky.com> wrote:
>
> On Wed, Sep 12, 2018 at 03:40:35PM +0200, Arnd Bergmann wrote:
> > On Wed, Sep 12, 2018 at 4:58 AM Mao Han <han_mao@c-sky.com> wrote:
> > >
> > > Linux-specific code that is required for maintaining ABI compatibility.
> > > This doesn't contain the actual system call interface.
> > >  sysdeps/unix/sysv/linux/csky/sys/user.h           |  60 +++
> > >  sysdeps/unix/sysv/linux/csky/sysdep.h             | 534 ++++++++++++++++++++++
> >
> > I'm surprised to see copies of bits/shm.h, bits/mman.h and sys/procfs.h.
> > Since the kernel port just uses the generic interfaces that all other
> > architectures used in the past decade, shouldn't the glibc defaults
> > match be enough here?

>
> We have SHMLBA defined to __getpagesize () << 2 in the linux port not
> __getpagesize () in the generic version in glibc. So an arch specific
> bits/shm.h seems needed.

Right, that makes sense.You need that for aliasing virtually indexed
caches, correct?

In the kernel, I'd probably try to change the generic file to allow an
architecture specific override, but I don't know what
the policy for this is in glibc.

> The generic sys/procfs.h in glibc define pr_uid/pr_gid as 'unsigned short',
> we have __kernel_uid_t define as "unsigned int"  in linux/include/uapi/
> asm-generic/posix_types.h. So I need an arch specific sys/procfs.h
> with pr_uid/pr_gid define as "unsigned int".

This sounds like something that should be improved in glibc, by
changing the default to the common case, and letting the less
common ones override it.

Here is what I see in glibc:

sysdeps/unix/sysv/linux/aarch64/sys/procfs.h:    unsigned int pr_uid;
sysdeps/unix/sysv/linux/alpha/sys/procfs.h:    unsigned int pr_uid;
sysdeps/unix/sysv/linux/arm/sys/procfs.h:    unsigned short int pr_uid;
sysdeps/unix/sysv/linux/hppa/sys/procfs.h:    unsigned int pr_uid;
sysdeps/unix/sysv/linux/ia64/sys/procfs.h:    unsigned int pr_uid;
sysdeps/unix/sysv/linux/m68k/sys/procfs.h:    unsigned short int pr_uid;
sysdeps/unix/sysv/linux/microblaze/sys/procfs.h:    unsigned short int pr_uid;
sysdeps/unix/sysv/linux/mips/sys/procfs.h:    long pr_uid;
sysdeps/unix/sysv/linux/nios2/sys/procfs.h:    unsigned short int pr_uid;
sysdeps/unix/sysv/linux/powerpc/sys/procfs.h:    __uid_t pr_uid;  # __U32_TYPE
sysdeps/unix/sysv/linux/riscv/sys/procfs.h:    long int pr_uid;
sysdeps/unix/sysv/linux/s390/sys/procfs.h:    unsigned int pr_uid;  # s390-64
sysdeps/unix/sysv/linux/s390/sys/procfs.h:    unsigned short int
pr_uid; # s390-32
sysdeps/unix/sysv/linux/sh/sys/procfs.h:    unsigned short int pr_uid;
sysdeps/unix/sysv/linux/sparc/sys/procfs.h:    unsigned int pr_uid;  # sparc64
sysdeps/unix/sysv/linux/sparc/sys/procfs.h:    unsigned short int
pr_uid; # sparc32
sysdeps/unix/sysv/linux/x86/sys/procfs.h:    unsigned short int pr_uid; # i386
sysdeps/unix/sysv/linux/x86/sys/procfs.h:    unsigned int pr_uid; # x86-64
sysdeps/unix/sysv/linux/sys/procfs.h:    unsigned short int pr_uid; #
everything else

and what we have in the kernel:

arch/arm/include/uapi/asm/posix_types.h:typedef unsigned short
 __kernel_uid_t;
arch/m68k/include/uapi/asm/posix_types.h:typedef unsigned short __kernel_uid_t;
arch/s390/include/uapi/asm/posix_types.h:typedef unsigned short
__kernel_uid_t; # s390-32
arch/s390/include/uapi/asm/posix_types.h:typedef unsigned int
__kernel_uid_t; # s390-64
arch/sh/include/uapi/asm/posix_types_32.h:typedef unsigned short
 __kernel_uid_t;
arch/sparc/include/uapi/asm/posix_types.h:typedef unsigned short
  __kernel_uid_t; # sparc32
arch/x86/include/uapi/asm/posix_types_32.h:typedef unsigned short
 __kernel_uid_t; # i386
include/uapi/asm-generic/posix_types.h:typedef unsigned int
__kernel_uid_t; # everything else

From what I can tell, mips64, riscv64, nios2, and microblaze are all wrong, and
the generic default would be wrong as well if picked up by anything else (but
nothing seems to use it).

        Arnd
  
Arnd Bergmann Sept. 13, 2018, 10:48 a.m. UTC | #7
On Wed, Sep 12, 2018 at 11:28 PM Florian Weimer <fweimer@redhat.com> wrote:
>
> On 09/12/2018 05:34 PM, Arnd Bergmann wrote:
> > Speaking of this file, I think we still need a solution for elf_prstatus
> > containing a 'timeval' after time_t becomes 64-bit wide. I actually
> > have a patch to change the kernel header file declaring the
> > same structure, but I had not realized that glibc contains another
> > copy.
> >
> > https://sourceware.org/glibc/wiki/Y2038ProofnessDesign  mentions
> > that type, but not what to do about it. What I did in the kernel
> > was to change the type of pr_utime/pr_stime/pr_cutime/pr_cstime
> > to something that keeps using 'long' fields. Given that we can't
> > change the file format in an incompatible way, and that 32-bit
> > is sufficient here, that seemed like the most appropriate solution.
>
> Keeping 32 bits there looks reasonable.  I thought we had a port where
> time_t isn't long, but that doesn't seem to be the case.

Ok. I'll change it to 'struct __kernel_old_timeval' in the kernel
headers then, keeping the existing definition we have for timeval.
I did that patch a while ago, but think I've never posted it
for inclusion so far.

The same thing also gets used in the implementation for
the wait4()/waitid() and getrusage() syscalls, which carry the same
data as the core file, as well as the various VDSO implementations
that we can't change over.

I'm still undecided on whether we want a version of waitid and
getrusage that takes a 64-bit timespec or 64-bit timeval
for consistency, or just let the libc deal with the conversion from
the 32-bit timeval here.

> Ah, I think it's actually s390, where suseconds_t is int, not long.

Odd: in the kernel, suseconds_t is long on s390, but int on
sparc and parisc. Were you thinking of sparc64 instead of s390
maybe? I would guess that parisc64 is actually wrong here, but
since there are not a lot of users on parisc and they tend to run
32-bit user space, it's plausible that this never got caught.

I totally missed the sparc/parisc oddity about suseconds_t
in the past, I'll have to modify my patch for that.

       Arnd
  
Florian Weimer Sept. 13, 2018, 10:56 a.m. UTC | #8
On 09/13/2018 12:48 PM, Arnd Bergmann wrote:
>> Ah, I think it's actually s390, where suseconds_t is int, not long.

> Odd: in the kernel, suseconds_t is long on s390, but int on
> sparc and parisc. Were you thinking of sparc64 instead of s390
> maybe?

Correct; sparc it is.  I was off by a line.

Thanks,
Florian
  
Joseph Myers Sept. 13, 2018, 3:32 p.m. UTC | #9
On Thu, 13 Sep 2018, Arnd Bergmann wrote:

> From what I can tell, mips64, riscv64, nios2, and microblaze are all wrong, and
> the generic default would be wrong as well if picked up by anything else (but
> nothing seems to use it).

A question for cleaning this up and possibly unifying versions of this 
header: for multi-ABI architectures, in userspace, what are these 
structures meant to refer to?  The structures that would be produced by a 
core dump for the current process, as opposed to those that might be 
produced by a core dump for another ABI?

I can confirm that the struct elf_prpsinfo defined in sys/procfs.h for 
MIPS n64 has size 0x90 whereas an n64 core dump has data size 0x88 for 
NT_PRPSINFO, indicating the pr_uid / pr_gid types are indeed wrong.  But 
I'm concerned here about n32 and about other fields in the structure.  
The code (dating back to the original addition of support for 64-bit MIPS 
ABIs to glibc in 2003) uses type unsigned long long int for pr_flag for 
n32.  But if I core dump an n32 process, I get 0x80 for the size of 
NT_PRPSINFO (while the userspace structure has size 0x88).  And similarly 
there are n32 conditionals in struct elf_prstatus - the core dump has size 
0x1b8 for NT_PRSTATUS but the userspace structure has size 0x1c0.  If the 
structure is meant to correspond to the current ABI, that suggests those 
n32 conditionals are wrong (the conditional on the definition of 
elf_greg_t, however, is correct, as n32 does use 64-bit registers).
  
Joseph Myers Sept. 13, 2018, 4:34 p.m. UTC | #10
On Thu, 13 Sep 2018, Joseph Myers wrote:

> On Thu, 13 Sep 2018, Arnd Bergmann wrote:
> 
> > From what I can tell, mips64, riscv64, nios2, and microblaze are all wrong, and
> > the generic default would be wrong as well if picked up by anything else (but
> > nothing seems to use it).
> 
> A question for cleaning this up and possibly unifying versions of this 
> header: for multi-ABI architectures, in userspace, what are these 
> structures meant to refer to?  The structures that would be produced by a 
> core dump for the current process, as opposed to those that might be 
> produced by a core dump for another ABI?

Also, I tried writing a test for the glibc testsuite to verify 
compatibility of the layout of these structures in the glibc and Linux 
headers, but found that a simple

#include <linux/elfcore.h>

using the installed uapi headers doesn't compile, because of unknown type 
names size_t, elf_greg_t, elf_gregset_t, elf_fpregset_t, elf_fpxregset_t, 
pid_t.  And indeed, e.g. elf_greg_t is not defined in any of the uapi 
headers, for many architectures.  What are the Linux kernel expectations 
regarding installed uapi headers actually being usable from userspace 
without needing additional type definitions provided by the user?

If that include worked, and produced the expected layout for the ABI used 
in the current compilation, it would be very helpful for writing such 
tests and ensuring bugs in this area can be found and fixed and avoided in 
future (and more general tests of consistency between glibc and Linux 
headers are probably possible as long as includes of the Linux headers 
from make headers_install do reliably compile without external 
dependencies).
  
Arnd Bergmann Sept. 13, 2018, 8:31 p.m. UTC | #11
On Thu, Sep 13, 2018 at 5:32 PM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Thu, 13 Sep 2018, Arnd Bergmann wrote:
>
> > From what I can tell, mips64, riscv64, nios2, and microblaze are all wrong, and
> > the generic default would be wrong as well if picked up by anything else (but
> > nothing seems to use it).
>
> A question for cleaning this up and possibly unifying versions of this
> header: for multi-ABI architectures, in userspace, what are these
> structures meant to refer to?  The structures that would be produced by a
> core dump for the current process, as opposed to those that might be
> produced by a core dump for another ABI?

The structures match the process that they describe. We use them for
three distinct things in the kernel:

/proc/kcore describes the kernel itself, in core dump format that can
be used with gdb etc to look at the currently running kernel

/proc/vmcore can be used for crash dump analysis when a kernel
crashes and we restart into a new kernel (kdump), making the
crashed one available in the same format

Core files generated by the kernel for running processes (the most
common case). A 32-bit task running on a 64-bit kernel should produce
the same core file as one running on a 32-bit kernel. At least that's
what the code is trying to do, looking up the sources I came across
a patch for a bug in that area[1]

> I can confirm that the struct elf_prpsinfo defined in sys/procfs.h for
> MIPS n64 has size 0x90 whereas an n64 core dump has data size 0x88 for
> NT_PRPSINFO, indicating the pr_uid / pr_gid types are indeed wrong.  But
> I'm concerned here about n32 and about other fields in the structure.
> The code (dating back to the original addition of support for 64-bit MIPS
> ABIs to glibc in 2003) uses type unsigned long long int for pr_flag for
> n32.  But if I core dump an n32 process, I get 0x80 for the size of
> NT_PRPSINFO (while the userspace structure has size 0x88).  And similarly
> there are n32 conditionals in struct elf_prstatus - the core dump has size
> 0x1b8 for NT_PRSTATUS but the userspace structure has size 0x1c0.  If the
> structure is meant to correspond to the current ABI, that suggests those
> n32 conditionals are wrong (the conditional on the definition of
> elf_greg_t, however, is correct, as n32 does use 64-bit registers).

We have four definitions in the kernel for these structures: The native
structure for the ELF implementation [2], the generic compat implementation[3]
for everything other than MIPS, and the two MIPS variants [4][5].
Looking at the sources, the last three seem to use identical layouts,
aside from the elf_gregset_t, which uses 64-bit registers on n64 but
32-bit registers everywhere else, and the architecture specific
ELF_NGREG constant.

         Arnd

[1] https://www.linux-mips.org/archives/linux-mips/2009-05/msg00135.html
[2] https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/elfcore.h
[3] https://elixir.bootlin.com/linux/latest/source/include/linux/elfcore-compat.h
[4] https://elixir.bootlin.com/linux/latest/source/arch/mips/kernel/binfmt_elfo32.c
[5] https://elixir.bootlin.com/linux/latest/source/arch/mips/kernel/binfmt_elfn32.c
  
Arnd Bergmann Sept. 13, 2018, 8:46 p.m. UTC | #12
On Thu, Sep 13, 2018 at 6:35 PM Joseph Myers <joseph@codesourcery.com> wrote:
> On Thu, 13 Sep 2018, Joseph Myers wrote:
> > On Thu, 13 Sep 2018, Arnd Bergmann wrote:
> > > From what I can tell, mips64, riscv64, nios2, and microblaze are all wrong, and
> > > the generic default would be wrong as well if picked up by anything else (but
> > > nothing seems to use it).
> >
> > A question for cleaning this up and possibly unifying versions of this
> > header: for multi-ABI architectures, in userspace, what are these
> > structures meant to refer to?  The structures that would be produced by a
> > core dump for the current process, as opposed to those that might be
> > produced by a core dump for another ABI?
>
> Also, I tried writing a test for the glibc testsuite to verify
> compatibility of the layout of these structures in the glibc and Linux
> headers, but found that a simple
>
> #include <linux/elfcore.h>
>
> using the installed uapi headers doesn't compile, because of unknown type
> names size_t, elf_greg_t, elf_gregset_t, elf_fpregset_t, elf_fpxregset_t,
> pid_t.  And indeed, e.g. elf_greg_t is not defined in any of the uapi
> headers, for many architectures.  What are the Linux kernel expectations
> regarding installed uapi headers actually being usable from userspace
> without needing additional type definitions provided by the user?

I think the expectations are generally mismatched with reality for our
headers. It's something that's been bugging me for a while and that
is not trivial to fix. We've had developers in the past that tried to
ensure that each exported uapi header can be included by itself,
but they (I forget who last worked on that) got too frustrated over
time to finish the job.  What you found is clearly a bug on our side
and we should try to fix it.

> If that include worked, and produced the expected layout for the ABI used
> in the current compilation, it would be very helpful for writing such
> tests and ensuring bugs in this area can be found and fixed and avoided in
> future (and more general tests of consistency between glibc and Linux
> headers are probably possible as long as includes of the Linux headers
> from make headers_install do reliably compile without external
> dependencies).

Agreed. I think the main problem is that the kernel still provides certain
types that are also provided by the C library, and other kernel headers
have interdependencies with these.

One example that is particularly nasty are kernel structures that
are defined in terms of 'timeval' and 'timespec'. Those are provided
by either <time.h> or <linux/time.h>, with an inconsistent set of
#ifdef guards between them, and (in the future) incompatible definitions.

Some instances in the kernel need to get changed to a type that
is independent of the libc type (e.g. the elf_prstatus here), while
others need to use the libc type (e.g. ioctl structures with
CLOCK_REALTIME timestamp members), and then need to include
<time.h> in user space.

        Arnd
  
Joseph Myers Sept. 13, 2018, 8:48 p.m. UTC | #13
On Thu, 13 Sep 2018, Arnd Bergmann wrote:

> We have four definitions in the kernel for these structures: The native
> structure for the ELF implementation [2], the generic compat implementation[3]
> for everything other than MIPS, and the two MIPS variants [4][5].
> Looking at the sources, the last three seem to use identical layouts,
> aside from the elf_gregset_t, which uses 64-bit registers on n64 but
> 32-bit registers everywhere else, and the architecture specific
> ELF_NGREG constant.

A 64-bit MIPS kernel is n64, not n32, so "unsigned long" in 
binfmt_elfn32.c is actually a 64-bit type for registers (as expected).

I think this confirms that the other two n32 conditionals in 
sysdeps/unix/sysv/linux/mips/sys/procfs.h are incorrect, as they would 
result in a field having the size it does for n64, not that for n32.
  
Joseph Myers Sept. 13, 2018, 8:59 p.m. UTC | #14
On Thu, 13 Sep 2018, Arnd Bergmann wrote:

> I think the expectations are generally mismatched with reality for our
> headers. It's something that's been bugging me for a while and that
> is not trivial to fix. We've had developers in the past that tried to
> ensure that each exported uapi header can be included by itself,
> but they (I forget who last worked on that) got too frustrated over
> time to finish the job.  What you found is clearly a bug on our side
> and we should try to fix it.

I note the recent proposed changes to make uapi headers build as C++ just 
fudges this issue, by providing dummy definitions of all the required 
types.  Which can't work for my purpose, because we need the actual 
definition of elf_gregset_t that the kernel uses when generating core 
dumps, not a dummy unsigned long[1] array, for tests of sizes and offsets 
to work.

> Agreed. I think the main problem is that the kernel still provides certain
> types that are also provided by the C library, and other kernel headers
> have interdependencies with these.

The types in question (in both linux/elfcore.h and sys/procfs.h) are of 
course types provided in both places - but in this case I'm not concerned 
about being able to include both headers at once, my test includes each in 
a separate file and compares the resulting sets of sizes and offsets (and 
if the kernel header tried to delegate to the libc header to get the type 
definitions when included from userspace code, that would defeat the point 
of my test).  If various types in the kernel header were to gain 
__kernel_* prefixes, that would be fine for my purposes.
  
Arnd Bergmann Sept. 13, 2018, 9:32 p.m. UTC | #15
On Thu, Sep 13, 2018 at 10:59 PM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Thu, 13 Sep 2018, Arnd Bergmann wrote:
>
> > I think the expectations are generally mismatched with reality for our
> > headers. It's something that's been bugging me for a while and that
> > is not trivial to fix. We've had developers in the past that tried to
> > ensure that each exported uapi header can be included by itself,
> > but they (I forget who last worked on that) got too frustrated over
> > time to finish the job.  What you found is clearly a bug on our side
> > and we should try to fix it.
>
> I note the recent proposed changes to make uapi headers build as C++ just
> fudges this issue, by providing dummy definitions of all the required
> types.  Which can't work for my purpose, because we need the actual
> definition of elf_gregset_t that the kernel uses when generating core
> dumps, not a dummy unsigned long[1] array, for tests of sizes and offsets
> to work.

Ah, I had missed that email thread. Since David Howells is now working
on the issue overall, I'm sure we will figure something out.

I haven't seen the part about the unsigned long[1] array, but I would
assume this is something that can and should be cahnged to make
it work for you.

> > Agreed. I think the main problem is that the kernel still provides certain
> > types that are also provided by the C library, and other kernel headers
> > have interdependencies with these.
>
> The types in question (in both linux/elfcore.h and sys/procfs.h) are of
> course types provided in both places - but in this case I'm not concerned
> about being able to include both headers at once, my test includes each in
> a separate file and compares the resulting sets of sizes and offsets (and
> if the kernel header tried to delegate to the libc header to get the type
> definitions when included from userspace code, that would defeat the point
> of my test).  If various types in the kernel header were to gain
> __kernel_* prefixes, that would be fine for my purposes.

 I need to think about this a bit more, and talk to a few other people.
A first step is probably to identify all structures that are provided
by both glibc and linux and classify them. In some cases, simply
renaming will be appropriate, in others it is not. One issue is that
we try to remain compatible with whatever behavior we had before,
and renaming e.g. 'struct stat' would work for glibc but not necessarily
all other libc implementations, unless we put some extra logic in
there to get the old name /unless/ we get included from glibc.

Another issue is structures that are intentionally ambiguous,
e.g. In the uapi headers there is an ioctl command definition
include/uapi/linux/ppdev.h:#define PPGETTIME    _IOR(PP_IOCTL, 0x95,
struct timeval)
This gets included by an application passing a pointer to
a 'struct timeval' into the kernel, which now implements two
commands, based on codes
drivers/char/ppdev.c:#define PPGETTIME32   _IOR(PP_IOCTL, 0x95, s32[2])
drivers/char/ppdev.c:#define PPGETTIME64   _IOR(PP_IOCTL, 0x95, s64[2])
so it can work with any user space.

         Arnd
  
Arnd Bergmann Sept. 13, 2018, 9:38 p.m. UTC | #16
On Thu, Sep 13, 2018 at 10:48 PM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Thu, 13 Sep 2018, Arnd Bergmann wrote:
>
> > We have four definitions in the kernel for these structures: The native
> > structure for the ELF implementation [2], the generic compat implementation[3]
> > for everything other than MIPS, and the two MIPS variants [4][5].
> > Looking at the sources, the last three seem to use identical layouts,
> > aside from the elf_gregset_t, which uses 64-bit registers on n64 but
> > 32-bit registers everywhere else, and the architecture specific
> > ELF_NGREG constant.
>
> A 64-bit MIPS kernel is n64, not n32, so "unsigned long" in
> binfmt_elfn32.c is actually a 64-bit type for registers (as expected).
>
> I think this confirms that the other two n32 conditionals in
> sysdeps/unix/sysv/linux/mips/sys/procfs.h are incorrect, as they would
> result in a field having the size it does for n64, not that for n32.

Yes, that sounds right. From what I can tell, the n32 ABI has come
out of fashion a bit: the embedded stuff tends to be 32-bit only
so it uses o32, and the Debian and Fedora ports port do either
n64 or o32 but not n32. There was a partial Fedora 12 n32 port, but
that was 7 years ago.

        Arnd
  
Joseph Myers Sept. 13, 2018, 10:57 p.m. UTC | #17
On Thu, 13 Sep 2018, Arnd Bergmann wrote:

> I haven't seen the part about the unsigned long[1] array, but I would
> assume this is something that can and should be cahnged to make
> it work for you.

It's the hack in the test 
<https://lwn.net/ml/linux-api/153616295066.23468.6133013878008690375.stgit@warthog.procyon.org.uk/> 
where it has a load of type and macro definitions before trying to include 
the uapi headers, including

+typedef unsigned long		elf_greg_t;
+typedef elf_greg_t		elf_gregset_t[1];

(but presumably most of the other type and macro definitions shouldn't be 
needed either, if the uapi headers are to work properly when included on 
their own).
  

Patch

diff --git a/sysdeps/unix/sysv/linux/csky/Versions b/sysdeps/unix/sysv/linux/csky/Versions
new file mode 100644
index 0000000..b61b3b2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/Versions
@@ -0,0 +1,5 @@ 
+libc {
+  GLIBC_2.29 {
+    cacheflush;
+  }
+}
diff --git a/sysdeps/unix/sysv/linux/csky/abiv2/ucontext_i.sym b/sysdeps/unix/sysv/linux/csky/abiv2/ucontext_i.sym
new file mode 100644
index 0000000..4581b65
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/abiv2/ucontext_i.sym
@@ -0,0 +1,32 @@ 
+#include <inttypes.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/ucontext.h>
+
+SIG_BLOCK
+SIG_SETMASK
+
+-- Offsets of the fields in the ucontext_t structure.
+#define ucontext(member)	offsetof (ucontext_t, member)
+#define mcontext(member)	ucontext (uc_mcontext.member)
+#define greg(member)		mcontext (__gregs.member)
+#define fpreg(member)		mcontext (__fpregs.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)
+
+MCONTEXT_CSKY_PC		greg (__pc)
+MCONTEXT_CSKY_SP		greg (__usp)
+MCONTEXT_CSKY_LR		greg (__lr)
+MCONTEXT_CSKY_A0		greg (__a0)
+MCONTEXT_CSKY_R8		greg (__regs[2])
+MCONTEXT_CSKY_R16		greg (__exregs[0])
+MCONTEXT_CSKY_HI		greg (__rhi)
+MCONTEXT_CSKY_LO		greg (__rlo)
+MCONTEXT_CSKY_R4		greg (__regs[0])
+MCONTEXT_CSKY_FESR		fpreg (__fesr)
+MCONTEXT_CSKY_FCR		fpreg (__fcr)
+MCONTEXT_CSKY_FR0		fpreg (__vr[0])
diff --git a/sysdeps/unix/sysv/linux/csky/bits/mman.h b/sysdeps/unix/sysv/linux/csky/bits/mman.h
new file mode 100644
index 0000000..cbb16dc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/bits/mman.h
@@ -0,0 +1,44 @@ 
+/* Definitions for POSIX memory map interface.  Linux/C-SKY version.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_MMAN_H
+# error "Never use <bits/mman.h> directly; include <sys/mman.h> instead."
+#endif
+
+/* The following definitions basically come from the kernel headers.
+   But the kernel header is not namespace clean.  */
+
+/* These are Linux-specific.  */
+#ifdef __USE_MISC
+# define MAP_GROWSDOWN	0x00100		/* Stack-like segment.  */
+# define MAP_DENYWRITE	0x00800		/* ETXTBSY */
+# define MAP_EXECUTABLE	0x01000		/* Mark it as an executable.  */
+# define MAP_LOCKED	0x02000		/* Lock the mapping.  */
+# define MAP_NORESERVE	0x04000		/* Don't check for reservations.  */
+# define MAP_POPULATE	0x08000		/* Populate (prefault) pagetables.  */
+# define MAP_NONBLOCK	0x10000		/* Do not block on IO.  */
+# define MAP_STACK	0x20000		/* Allocation is for a stack.  */
+# define MAP_HUGETLB	0x40000		/* Create huge page mapping.  */
+# define MAP_SYNC	0x80000		/* Perform synchronous page
+					   faults for the mapping.  */
+# define MAP_FIXED_NOREPLACE 0x100000   /* MAP_FIXED but do not unmap
+                                           underlying mapping.  */
+#endif
+
+/* Include generic Linux declarations.  */
+#include <bits/mman-linux.h>
diff --git a/sysdeps/unix/sysv/linux/csky/bits/shm.h b/sysdeps/unix/sysv/linux/csky/bits/shm.h
new file mode 100644
index 0000000..cc4347e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/bits/shm.h
@@ -0,0 +1,104 @@ 
+/* Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_SHM_H
+# error "Never include <bits/shm.h> directly; use <sys/shm.h> instead."
+#endif
+
+#include <bits/types.h>
+
+/* Permission flag for shmget.  */
+#define SHM_R		0400		/* or S_IRUGO from <linux/stat.h> */
+#define SHM_W		0200		/* or S_IWUGO from <linux/stat.h> */
+
+/* Flags for `shmat'.  */
+#define SHM_RDONLY	010000		/* attach read-only else read-write */
+#define SHM_RND		020000		/* round attach address to SHMLBA */
+#define SHM_REMAP	040000		/* take-over region on attach */
+#define SHM_EXEC	0100000		/* execution access */
+
+/* Commands for `shmctl'.  */
+#define SHM_LOCK	11		/* lock segment (root only) */
+#define SHM_UNLOCK	12		/* unlock segment (root only) */
+
+__BEGIN_DECLS
+
+/* Segment low boundary address multiple.  */
+#define SHMLBA		(__getpagesize () << 2)
+extern int __getpagesize (void) __THROW __attribute__ ((__const__));
+
+
+/* Type to count number of attaches.  */
+typedef unsigned long int shmatt_t;
+
+/* Data structure describing a shared memory segment.  */
+struct shmid_ds
+  {
+    struct ipc_perm shm_perm;		/* operation permission struct */
+    size_t shm_segsz;			/* size of segment in bytes */
+    __time_t shm_atime;			/* time of last shmat() */
+    unsigned long int __glibc_reserved1;
+    __time_t shm_dtime;			/* time of last shmdt() */
+    unsigned long int __glibc_reserved2;
+    __time_t shm_ctime;			/* time of last change by shmctl() */
+    unsigned long int __glibc_reserved3;
+    __pid_t shm_cpid;			/* pid of creator */
+    __pid_t shm_lpid;			/* pid of last shmop */
+    shmatt_t shm_nattch;		/* number of current attaches */
+    unsigned long int __glibc_reserved4;
+    unsigned long int __glibc_reserved5;
+  };
+
+#ifdef __USE_MISC
+
+/* ipcs ctl commands */
+# define SHM_STAT 	13
+# define SHM_INFO 	14
+# define SHM_STAT_ANY   15
+
+/* shm_mode upper byte flags */
+# define SHM_DEST	01000	/* segment will be destroyed on last detach */
+# define SHM_LOCKED	02000   /* segment will not be swapped */
+# define SHM_HUGETLB	04000	/* segment is mapped via hugetlb */
+# define SHM_NORESERVE	010000	/* don't check for reservations */
+
+struct	shminfo
+  {
+    unsigned long int shmmax;
+    unsigned long int shmmin;
+    unsigned long int shmmni;
+    unsigned long int shmseg;
+    unsigned long int shmall;
+    unsigned long int __glibc_reserved1;
+    unsigned long int __glibc_reserved2;
+    unsigned long int __glibc_reserved3;
+    unsigned long int __glibc_reserved4;
+  };
+
+struct shm_info
+  {
+    int used_ids;
+    unsigned long int shm_tot;	/* total allocated shm */
+    unsigned long int shm_rss;	/* total resident shm */
+    unsigned long int shm_swp;	/* total swapped shm */
+    unsigned long int swap_attempts;
+    unsigned long int swap_successes;
+  };
+
+#endif /* __USE_MISC */
+
+__END_DECLS
diff --git a/sysdeps/unix/sysv/linux/csky/c++-types.data b/sysdeps/unix/sysv/linux/csky/c++-types.data
new file mode 100644
index 0000000..303f457
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/c++-types.data
@@ -0,0 +1,67 @@ 
+blkcnt64_t:x
+blkcnt_t:l
+blksize_t:i
+caddr_t:Pc
+clockid_t:i
+clock_t:l
+daddr_t:i
+dev_t:y
+fd_mask:l
+fsblkcnt64_t:y
+fsblkcnt_t:m
+fsfilcnt64_t:y
+fsfilcnt_t:m
+fsid_t:8__fsid_t
+gid_t:j
+id_t:j
+ino64_t:y
+ino_t:m
+int16_t:s
+int32_t:i
+int64_t:x
+int8_t:a
+intptr_t:i
+key_t:i
+loff_t:x
+mode_t:j
+nlink_t:j
+off64_t:x
+off_t:l
+pid_t:i
+pthread_attr_t:14pthread_attr_t
+pthread_barrier_t:17pthread_barrier_t
+pthread_barrierattr_t:21pthread_barrierattr_t
+pthread_cond_t:14pthread_cond_t
+pthread_condattr_t:18pthread_condattr_t
+pthread_key_t:j
+pthread_mutex_t:15pthread_mutex_t
+pthread_mutexattr_t:19pthread_mutexattr_t
+pthread_once_t:i
+pthread_rwlock_t:16pthread_rwlock_t
+pthread_rwlockattr_t:20pthread_rwlockattr_t
+pthread_spinlock_t:i
+pthread_t:m
+quad_t:x
+register_t:i
+rlim64_t:y
+rlim_t:m
+sigset_t:10__sigset_t
+size_t:j
+socklen_t:j
+ssize_t:i
+suseconds_t:l
+time_t:l
+u_char:h
+uid_t:j
+uint:j
+u_int:j
+u_int16_t:t
+u_int32_t:j
+u_int64_t:y
+u_int8_t:h
+ulong:m
+u_long:m
+u_quad_t:y
+useconds_t:j
+ushort:t
+u_short:t
diff --git a/sysdeps/unix/sysv/linux/csky/ipc_priv.h b/sysdeps/unix/sysv/linux/csky/ipc_priv.h
new file mode 100644
index 0000000..56ded89
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/ipc_priv.h
@@ -0,0 +1,21 @@ 
+/* Old SysV permission definition for Linux.  C-SKY version.
+   Copyright (C) 2017-2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/ipc.h>  /* For __key_t  */
+
+#define __IPC_64	0x0
diff --git a/sysdeps/unix/sysv/linux/csky/jmp_buf-macros.h b/sysdeps/unix/sysv/linux/csky/jmp_buf-macros.h
new file mode 100644
index 0000000..5a390c7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/jmp_buf-macros.h
@@ -0,0 +1,6 @@ 
+#define JMP_BUF_SIZE 268
+#define SIGJMP_BUF_SIZE 268
+#define JMP_BUF_ALIGN 4
+#define SIGJMP_BUF_ALIGN 4
+#define MASK_WAS_SAVED_OFFSET 136
+#define SAVED_MASK_OFFSET 140
diff --git a/sysdeps/unix/sysv/linux/csky/kernel-features.h b/sysdeps/unix/sysv/linux/csky/kernel-features.h
new file mode 100644
index 0000000..854865b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/kernel-features.h
@@ -0,0 +1,23 @@ 
+/* Set flags signalling availability of kernel features based on given
+   kernel version number.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include_next <kernel-features.h>
+
+/* fadvise64_64 reorganize the syscall arguments.  */
+#define __ASSUME_FADVISE64_64_6ARG	1
diff --git a/sysdeps/unix/sysv/linux/csky/localplt.data b/sysdeps/unix/sysv/linux/csky/localplt.data
new file mode 100644
index 0000000..14c02cb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/localplt.data
@@ -0,0 +1,19 @@ 
+# 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: memalign
+libc.so: realloc
+# The main malloc is interposed into the dynamic linker, for
+# allocations after the initial link (when dlopen is used).
+ld.so: malloc
+ld.so: calloc
+ld.so: realloc
+ld.so: free
+# 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/csky/makecontext.c b/sysdeps/unix/sysv/linux/csky/makecontext.c
new file mode 100644
index 0000000..c0d7d1e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/makecontext.c
@@ -0,0 +1,74 @@ 
+/* Create new context.  C-SKY version.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdarg.h>
+#include <ucontext.h>
+
+/* Number of arguments that go in registers.  */
+#define NREG_ARGS  4
+
+/* Take a context previously prepared via getcontext() and set to
+   call func() with the given int only args.  */
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+  extern void __startcontext (void);
+  unsigned long *funcstack;
+  va_list vl;
+  unsigned long *regptr;
+  unsigned int reg;
+  int misaligned;
+
+  /* Start at the top of stack.  */
+  funcstack = (unsigned long *) (ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
+
+  /* Ensure the stack stays eight byte aligned.  */
+  misaligned = ((unsigned long) funcstack & 4) != 0;
+
+  if ((argc > NREG_ARGS) && (argc & 1) != 0)
+    misaligned = !misaligned;
+
+  if (misaligned)
+    funcstack -= 1;
+
+  va_start (vl, argc);
+
+  /* Reserve space for the on-stack arguments.  */
+  if (argc > NREG_ARGS)
+    funcstack -= (argc - NREG_ARGS);
+
+  ucp->uc_mcontext.__gregs.__usp = (unsigned long) funcstack;
+  ucp->uc_mcontext.__gregs.__pc = (unsigned long) func;
+
+  /* Exit to startcontext() with the next context in R9.  */
+  ucp->uc_mcontext.__gregs.__regs[5] = (unsigned long) ucp->uc_link;
+  ucp->uc_mcontext.__gregs.__lr = (unsigned long) __startcontext;
+
+  /* The first four arguments go into registers.  */
+  regptr = &(ucp->uc_mcontext.__gregs.__a0);
+
+  for (reg = 0; (reg < argc) && (reg < NREG_ARGS); reg++)
+    *regptr++ = va_arg (vl, unsigned long);
+
+  /* And the remainder on the stack.  */
+  for (; reg < argc; reg++)
+    *funcstack++ = va_arg (vl, unsigned long);
+
+  va_end (vl);
+}
+weak_alias (__makecontext, makecontext)
diff --git a/sysdeps/unix/sysv/linux/csky/profil-counter.h b/sysdeps/unix/sysv/linux/csky/profil-counter.h
new file mode 100644
index 0000000..1f7ec7a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/profil-counter.h
@@ -0,0 +1,31 @@ 
+/* Low-level statistical profiling support function.  Linux/C-SKY version.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <signal.h>
+#include <sigcontextinfo.h>
+
+void
+__profil_counter (int signo, const SIGCONTEXT scp)
+{
+  profil_count ((void *) GET_PC (scp));
+
+  /* This is a hack to prevent the compiler from implementing the
+     above function call as a sibcall.  The sibcall would overwrite
+     the signal context.  */
+  asm volatile ("");
+}
diff --git a/sysdeps/unix/sysv/linux/csky/register-dump.h b/sysdeps/unix/sysv/linux/csky/register-dump.h
new file mode 100644
index 0000000..9abe87a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/register-dump.h
@@ -0,0 +1,193 @@ 
+/* Dump registers.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/uio.h>
+#include <_itoa.h>
+#include <bits/sigcontext.h>
+#include <sys/ucontext.h>
+
+/* abiv1 register dump in this format:
+
+ PSR: XXXXXXXX  PC: XXXXXXXX   SP: XXXXXXXX   LR: XXXXXXXX
+ MASK: XXXXXXXX
+
+ A0: XXXXXXXX   A1: XXXXXXXX   A2: XXXXXXXX   A3: XXXXXXXX
+ R6: XXXXXXXX   R7: XXXXXXXX   R8: XXXXXXXX   R9: XXXXXXXX
+ R10: XXXXXXXX  R11: XXXXXXXX  R12: XXXXXXXX  R13: XXXXXXXX
+ R14: XXXXXXXX  R1: XXXXXXXX
+
+ abiv2 register dump in this format:
+
+ PSR: XXXXXXXX  PC: XXXXXXXX   SP: XXXXXXXX   LR: XXXXXXXX
+ MASK: XXXXXXXX
+
+ A0: XXXXXXXX   A1: XXXXXXXX   A2: XXXXXXXX   A3: XXXXXXXX
+ R4: XXXXXXXX   R5: XXXXXXXX   R6: XXXXXXXX   R7: XXXXXXXX
+ R8: XXXXXXXX   R9: XXXXXXXX   R10: XXXXXXXX  R11: XXXXXXXX
+ R12: XXXXXXXX  R13: XXXXXXXX  R14: XXXXXXXX  R15: XXXXXXXX
+ R16: XXXXXXXX  R17: XXXXXXXX  R18: XXXXXXXX  R19: XXXXXXXX
+ R20: XXXXXXXX  R21: XXXXXXXX  R22: XXXXXXXX  R23: XXXXXXXX
+ R24: XXXXXXXX  R25: XXXXXXXX  R26: XXXXXXXX  R27: XXXXXXXX
+ R28: XXXXXXXX  R29: XXXXXXXX  R30: XXXXXXXX  R31: XXXXXXXX
+
+ */
+
+static void
+hexvalue (unsigned long int value, char *buf, size_t len)
+{
+  char *cp = _itoa_word (value, buf + len, 16, 0);
+  while (cp > buf)
+    *--cp = '0';
+}
+
+static void
+register_dump (int fd, const struct ucontext_t *ctx)
+{
+  char regs[35][8];
+  struct iovec iov[97];
+  size_t nr = 0;
+
+#define ADD_STRING(str) \
+  iov[nr].iov_base = (char *) str;					      \
+  iov[nr].iov_len = strlen (str);					      \
+  ++nr
+#define ADD_MEM(str, len) \
+  iov[nr].iov_base = str;						      \
+  iov[nr].iov_len = len;						      \
+  ++nr
+
+  /* Generate strings of register contents.  */
+  hexvalue (ctx->uc_mcontext.__gregs.__sr, regs[0], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__pc, regs[1], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__usp, regs[2], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__lr, regs[3], 8);
+  hexvalue (ctx->uc_mcontext.__mask, regs[4], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__a0, regs[5], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__a1, regs[6], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__a2, regs[7], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__a3, regs[8], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__regs[0], regs[9], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__regs[1], regs[10], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__regs[2], regs[11], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__regs[3], regs[12], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__regs[4], regs[13], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__regs[5], regs[14], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__regs[6], regs[15], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__regs[7], regs[16], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__regs[8], regs[17], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__regs[9], regs[18], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[0], regs[19], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[1], regs[20], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[2], regs[21], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[3], regs[22], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[4], regs[23], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[5], regs[24], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[6], regs[25], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[7], regs[26], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[8], regs[27], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[9], regs[28], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[10], regs[29], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[11], regs[30], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[12], regs[31], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[13], regs[32], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__exregs[14], regs[33], 8);
+  hexvalue (ctx->uc_mcontext.__gregs.__tls, regs[34], 8);
+
+  /* Generate the output.  */
+  ADD_STRING ("Register dump:\n\n PSR: ");
+  ADD_MEM (regs[0], 8);
+  ADD_STRING ("  PC: ");
+  ADD_MEM (regs[1], 8);
+  ADD_STRING ("   SP: ");
+  ADD_MEM (regs[2], 8);
+  ADD_STRING ("   LR: ");
+  ADD_MEM (regs[3], 8);
+  ADD_STRING ("\n MASK: ");
+  ADD_MEM (regs[4], 8);
+  ADD_STRING ("\n\n A0: ");
+  ADD_MEM (regs[5], 8);
+  ADD_STRING ("   A1: ");
+  ADD_MEM (regs[6], 8);
+  ADD_STRING ("   A2: ");
+  ADD_MEM (regs[7], 8);
+  ADD_STRING ("   A3: ");
+  ADD_MEM (regs[8], 8);
+  ADD_STRING ("\n R4: ");
+  ADD_MEM (regs[9], 8);
+  ADD_STRING ("   r5: ");
+  ADD_MEM (regs[10], 8);
+  ADD_STRING ("   r6: ");
+  ADD_MEM (regs[11], 8);
+  ADD_STRING ("   r7: ");
+  ADD_MEM (regs[12], 8);
+  ADD_STRING ("\n R8: ");
+  ADD_MEM (regs[13], 8);
+  ADD_STRING ("   R9: ");
+  ADD_MEM (regs[14], 8);
+  ADD_STRING ("   R10: ");
+  ADD_MEM (regs[15], 8);
+  ADD_STRING ("  R11: ");
+  ADD_MEM (regs[16], 8);
+  ADD_STRING ("\n R12: ");
+  ADD_MEM (regs[17], 8);
+  ADD_STRING ("  R13: ");
+  ADD_MEM (regs[18], 8);
+  ADD_STRING ("  R14: ");
+  ADD_MEM (regs[19], 8);
+  ADD_STRING ("  R15: ");
+  ADD_MEM (regs[20], 8);
+  ADD_STRING ("\n R16: ");
+  ADD_MEM (regs[21], 8);
+  ADD_STRING ("  R17: ");
+  ADD_MEM (regs[22], 8);
+  ADD_STRING ("  R18: ");
+  ADD_MEM (regs[23], 8);
+  ADD_STRING ("  R19: ");
+  ADD_MEM (regs[24], 8);
+  ADD_STRING ("\n R20: ");
+  ADD_MEM (regs[25], 8);
+  ADD_STRING ("  R21: ");
+  ADD_MEM (regs[26], 8);
+  ADD_STRING ("  R22: ");
+  ADD_MEM (regs[27], 8);
+  ADD_STRING ("  R23: ");
+  ADD_MEM (regs[28], 8);
+  ADD_STRING ("\n R24: ");
+  ADD_MEM (regs[29], 8);
+  ADD_STRING ("  R25: ");
+  ADD_MEM (regs[30], 8);
+  ADD_STRING ("  R26: ");
+  ADD_MEM (regs[31], 8);
+  ADD_STRING ("  R27: ");
+  ADD_MEM (regs[32], 8);
+  ADD_STRING ("\n R28: ");
+  ADD_MEM (regs[33], 8);
+  ADD_STRING ("  R29: ");
+  ADD_MEM (regs[34], 8);
+  ADD_STRING ("  R30: ");
+  ADD_MEM (regs[33], 8);
+  ADD_STRING ("  TP: ");
+  ADD_MEM (regs[34], 8);
+
+  ADD_STRING ("\n");
+
+  /* Write the stuff out.  */
+  writev (fd, iov, nr);
+}
+
+#define REGISTER_DUMP register_dump (fd, ctx)
diff --git a/sysdeps/unix/sysv/linux/csky/shlib-versions b/sysdeps/unix/sysv/linux/csky/shlib-versions
new file mode 100644
index 0000000..1451971
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/shlib-versions
@@ -0,0 +1,7 @@ 
+DEFAULT			GLIBC_2.29
+
+%if CSKYABI == 2
+ld=ld-linux-cskyv2-le.so.1
+%else
+%error cannot determine ABI
+%endif
diff --git a/sysdeps/unix/sysv/linux/csky/sigcontextinfo.h b/sysdeps/unix/sysv/linux/csky/sigcontextinfo.h
new file mode 100644
index 0000000..b9054d3
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/sigcontextinfo.h
@@ -0,0 +1,32 @@ 
+/* C-SKY definitions for signal handling calling conventions.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#define SIGCONTEXT siginfo_t *_si, struct ucontext_t *
+#define GET_PC(ctx)     ((void *) (ctx)->uc_mcontext.__gregs.__pc)
+
+/* There is no reliable way to get the sigcontext unless we use a
+   three-argument signal handler.  */
+#define __sigaction(sig, act, oact) ({ \
+  (act)->sa_flags |= SA_SIGINFO; \
+  (__sigaction) (sig, act, oact); \
+})
+
+#define sigaction(sig, act, oact) ({ \
+  (act)->sa_flags |= SA_SIGINFO; \
+  (sigaction) (sig, act, oact); \
+})
diff --git a/sysdeps/unix/sysv/linux/csky/sys/cachectl.h b/sysdeps/unix/sysv/linux/csky/sys/cachectl.h
new file mode 100644
index 0000000..bdc7dbb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/sys/cachectl.h
@@ -0,0 +1,38 @@ 
+/* C-SKY cache flushing interface.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_CACHECTL_H
+#define _SYS_CACHECTL_H 1
+
+#include <features.h>
+
+/* Get the kernel definition for the op bits.  */
+#include <asm/cachectl.h>
+
+__BEGIN_DECLS
+
+#ifdef __USE_MISC
+extern int cacheflush (void *__addr, const int __nbytes,
+		       const int __op) __THROW;
+#endif
+extern int _flush_cache (char *__addr, const int __nbytes,
+		         const int __op) __THROW;
+
+__END_DECLS
+
+#endif /* sys/cachectl.h */
diff --git a/sysdeps/unix/sysv/linux/csky/sys/procfs.h b/sysdeps/unix/sysv/linux/csky/sys/procfs.h
new file mode 100644
index 0000000..e48eaba
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/sys/procfs.h
@@ -0,0 +1,123 @@ 
+/* Core image file related definitions, C-SKY version.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_PROCFS_H
+#define _SYS_PROCFS_H	1
+
+/* This is somewhat modelled after the file of the same name on SVR4
+   systems.  It provides a definition of the core file format for ELF
+   used on Linux.  It doesn't have anything to do with the /proc file
+   system, even though Linux has one.
+
+   Anyway, the whole purpose of this file is for GDB and GDB only.
+   Don't read too much into it.  Don't use it for anything other than
+   GDB unless you know what you are doing.  */
+
+#include <features.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/user.h>
+
+__BEGIN_DECLS
+
+/* Type for a general-purpose register.  */
+typedef unsigned long elf_greg_t;
+
+/* And the whole bunch of them.  We could have used `struct
+   user_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) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* Register set for the floating-point registers.  */
+typedef struct user_fpregs elf_fpregset_t;
+
+/* Signal info.  */
+struct elf_siginfo
+  {
+    int si_signo;			/* Signal number.  */
+    int si_code;			/* Extra code.  */
+    int si_errno;			/* Errno.  */
+  };
+
+/* Definitions to generate Intel SVR4-like core files.  These mostly
+   have the same names as the SVR4 types with "elf_" tacked on the
+   front to prevent clashes with Linux definitions, and the typedef
+   forms have been avoided.  This is mostly like the SVR4 structure,
+   but more Linuxy, with things that Linux does not support and which
+   GDB doesn't really use excluded.  */
+
+struct elf_prstatus
+  {
+    struct elf_siginfo pr_info;		/* Info associated with signal.  */
+    short int pr_cursig;		/* Current signal.  */
+    unsigned long int pr_sigpend;	/* Set of pending signals.  */
+    unsigned long int pr_sighold;	/* Set of held signals.  */
+    __pid_t pr_pid;
+    __pid_t pr_ppid;
+    __pid_t pr_pgrp;
+    __pid_t pr_sid;
+    struct timeval pr_utime;		/* User time.  */
+    struct timeval pr_stime;		/* System time.  */
+    struct timeval pr_cutime;		/* Cumulative user time.  */
+    struct timeval pr_cstime;		/* Cumulative system time.  */
+    elf_gregset_t pr_reg;		/* GP registers.  */
+    int pr_fpvalid;			/* True if math copro being used.  */
+  };
+
+
+#define ELF_PRARGSZ     (80)    /* Number of chars for args.  */
+
+struct elf_prpsinfo
+  {
+    char pr_state;			/* Numeric process state.  */
+    char pr_sname;			/* Char for pr_state.  */
+    char pr_zomb;			/* Zombie.  */
+    char pr_nice;			/* Nice val.  */
+    unsigned long int pr_flag;		/* Flags.  */
+    unsigned short int pr_uid;
+    unsigned short int pr_gid;
+    int pr_pid, pr_ppid, pr_pgrp, pr_sid;
+    /* Lots missing */
+    char pr_fname[16];			/* Filename of executable.  */
+    char pr_psargs[ELF_PRARGSZ];	/* Initial part of arg list.  */
+  };
+
+/* The rest of this file provides the types for emulation of the
+   Solaris <proc_service.h> interfaces that should be implemented by
+   users of libthread_db.  */
+
+/* Addresses.  */
+typedef void *psaddr_t;
+
+/* Register sets.  Linux has different names.  */
+typedef elf_gregset_t prgregset_t;
+typedef elf_fpregset_t prfpregset_t;
+
+/* We don't have any differences between processes and threads,
+   therefore have only one PID type.  */
+typedef __pid_t lwpid_t;
+
+/* Process status and info.  In the end we do provide typedefs for them.  */
+typedef struct elf_prstatus prstatus_t;
+typedef struct elf_prpsinfo prpsinfo_t;
+
+__END_DECLS
+
+#endif /* sys/procfs.h */
diff --git a/sysdeps/unix/sysv/linux/csky/sys/ucontext.h b/sysdeps/unix/sysv/linux/csky/sys/ucontext.h
new file mode 100644
index 0000000..b784ddd
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/sys/ucontext.h
@@ -0,0 +1,89 @@ 
+/* struct ucontext definition, C-SKY version.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_UCONTEXT_H
+#define _SYS_UCONTEXT_H	1
+
+#include <features.h>
+
+#include <bits/types/sigset_t.h>
+#include <bits/types/stack_t.h>
+
+typedef struct
+  {
+    unsigned long __tls;
+    unsigned long __lr;
+    unsigned long __pc;
+    unsigned long __sr;
+    unsigned long __usp;
+
+    /*
+     * a0, a1, a2, a3:
+     * abiv2: r0, r1, r2, r3
+     */
+
+    unsigned long __orig_a0;
+    unsigned long __a0;
+    unsigned long __a1;
+    unsigned long __a2;
+    unsigned long __a3;
+
+    /*
+     * ABIV2: r4 ~ r13
+     */
+    unsigned long __regs[10];
+
+    /* r16 ~ r30 */
+    unsigned long __exregs[15];
+
+    unsigned long __rhi;
+    unsigned long __rlo;
+    unsigned long __glibc_reserved;
+  } gregset_t;
+
+typedef struct
+  {
+    unsigned long __vr[64];
+    unsigned long __fcr;
+    unsigned long __fesr;
+    unsigned long __fid;
+    unsigned long __glibc_reserved;
+  } fpregset_t;
+
+/* Context to describe whole processor state.  */
+typedef struct
+  {
+    unsigned long __mask;
+    gregset_t __gregs;
+    fpregset_t __fpregs;
+  } mcontext_t;
+
+/* Userlevel context.  */
+typedef struct ucontext_t
+  {
+    unsigned long int __uc_flags;
+    struct ucontext_t *uc_link;
+    stack_t uc_stack;
+    mcontext_t uc_mcontext;
+    sigset_t uc_sigmask;
+  } ucontext_t;
+
+#undef __ctx
+
+
+#endif /* sys/ucontext.h */
diff --git a/sysdeps/unix/sysv/linux/csky/sys/user.h b/sysdeps/unix/sysv/linux/csky/sys/user.h
new file mode 100644
index 0000000..6064734
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/sys/user.h
@@ -0,0 +1,60 @@ 
+/* ptrace register data format definitions.  C-SKY version.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_USER_H
+#define _SYS_USER_H  1
+
+struct user_fpregs {
+  unsigned long fsr;		/* fpu status reg */
+  unsigned long fesr;		/* fpu exception status reg */
+  unsigned long fp[32];		/* fpu general regs */
+};
+
+struct user_regs {
+  unsigned long int uregs[34];	/* CSKY V2 has 32 general rgister.  */
+};
+
+/* When the kernel dumps core, it starts by dumping the user struct -
+   this will be used by gdb to figure out where the data and stack segments
+   are within the file, and what virtual addresses to use.  */
+struct user{
+/* We start with the registers, to mimic the way that "memory" is returned
+   from the ptrace(3,...) function.  */
+  struct user_regs    regs;        /* The registers are actually stored.  */
+  int                 u_fpvalid;   /* True if math co-processor being used.  */
+
+/* The rest of this junk is to help gdb figure out what goes where.  */
+  unsigned long int   u_tsize;     /* Text segment size (pages).  */
+  unsigned long int   u_dsize;     /* Data segment size (pages).  */
+  unsigned long int   u_ssize;     /* Stack segment size (pages).  */
+  unsigned long       start_code;  /* Starting virtual address of text.  */
+  unsigned long       start_stack; /* Starting virtual address of stack area.
+				      This is actually the bottom of the stack
+				      the top of the stack is always found in
+				      the esp register.  */
+  long int            signal;      /* Signal that caused the core dump.  */
+  int                 reserved;    /* No longer used.  */
+  struct user_regs *  u_ar0;       /* Used by gdb to help find the values
+				      for the registers.  */
+  unsigned long       magic;       /* To uniquely identify a core file.  */
+  char                u_comm[32];  /* User command that was responsible.  */
+  struct user_fpregs  u_fp;
+  struct user_fpregs* u_fpstate;   /* Math Co-processor pointer.  */
+};
+
+#endif /* _SYS_USER_H */
diff --git a/sysdeps/unix/sysv/linux/csky/sysdep.h b/sysdeps/unix/sysv/linux/csky/sysdep.h
new file mode 100644
index 0000000..3fd456f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/csky/sysdep.h
@@ -0,0 +1,534 @@ 
+/* Assembly macros for C-SKY.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LINUX_CSKY_SYSDEP_H
+#define _LINUX_CSKY_SYSDEP_H 1
+
+/* There is some commonality.  */
+#include <sysdeps/unix/sysv/linux/generic/sysdep.h>
+#include <sysdeps/unix/sysv/linux/sysdep.h>
+#include <sysdeps/csky/sysdep.h>
+
+/* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO.  */
+#include <dl-sysdep.h>
+
+#include <tls.h>
+
+/* In order to get __set_errno() definition in INLINE_SYSCALL.  */
+#ifndef __ASSEMBLER__
+# include <errno.h>
+#endif
+
+#undef SYS_ify
+#define SYS_ify(syscall_name)  (__NR_##syscall_name)
+
+#ifdef __ASSEMBLER__
+/* Linux uses a negative return value to indicate syscall errors,
+   unlike most Unices, which use the condition codes' carry flag.
+
+   Since version 2.1 the return value of a system call might be
+   negative even if the call succeeded.  E.g., the `lseek' system call
+   might return a large offset.  Therefore we must not anymore test
+   for < 0, but test for a real error by making sure the value in R0
+   is a real error number.  Linus said he will make sure the no syscall
+   returns a value in -1 .. -4095 as a valid result so we can safely
+   test with -4095.  */
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)	\
+  .text;					\
+  ENTRY (name);					\
+  DO_CALL (syscall_name, args);
+
+# define GETGB				\
+	grs	t0, .Lgetpc;		\
+.Lgetpc:				\
+	lrw	gb, .Lgetpc@GOTPC;	\
+	addu	gb, t0;
+
+# if IS_IN (libc)
+#  ifdef __PIC__
+#   define PSEUDO_RET			\
+	btsti	a0, 31;			\
+	bf	1f;			\
+	subi	sp, 8;			\
+	st.w	lr, (sp);		\
+	st.w	gb, (sp, 4);		\
+	GETGB;				\
+	lrw	a2, SYSCALL_ERROR@PLT;	\
+	add	a2, gb;			\
+	ld.w	a2, (a2);		\
+	jsr	a2;			\
+	ld.w	lr, (sp);		\
+	ld.w	gb, (sp, 4);		\
+	addi	sp, 8;			\
+1:					\
+	rts
+#  else
+#   define PSEUDO_RET			\
+	btsti	a0, 31;			\
+	bf	1f;			\
+	jmpi	SYSCALL_ERROR;		\
+1:					\
+	rts
+#  endif
+# else
+#  ifdef __PIC__
+#   define PSEUDO_RET			\
+	btsti	a0, 31;			\
+	bf	1f;			\
+	subi	sp, 8;			\
+	st.w	lr, (sp);		\
+	st.w	gb, (sp, 4);		\
+	GETGB;				\
+	bsr	SYSCALL_ERROR;		\
+	ld.w	lr, (sp);		\
+	ld.w	gb, (sp, 4);		\
+	addi	sp, 8;			\
+1:					\
+	rts
+#  else
+#   define PSEUDO_RET			\
+	btsti	a0, 31;			\
+	bt	SYSCALL_ERROR;		\
+	rts
+#  endif
+# endif
+
+# undef ret
+# define ret PSEUDO_RET
+
+# undef PSEUDO_END
+# define PSEUDO_END(name)		\
+  .align 4;				\
+  SYSCALL_ERROR_HANDLER;		\
+  END (name)
+
+# undef PSEUDO_NOERRNO
+# define PSEUDO_NOERRNO(name, syscall_name, args)	\
+  .text;						\
+  ENTRY (name);						\
+  DO_CALL (syscall_name, args)
+
+# define PSEUDO_RET_NOERRNO rts
+
+# undef ret_NOERRNO
+# define ret_NOERRNO PSEUDO_RET_NOERRNO
+
+# undef PSEUDO_END_NOERRNO
+# define PSEUDO_END_NOERRNO(name) END (name)
+
+/* The function has to return the error code.  */
+# undef PSEUDO_ERRVAL
+# define PSEUDO_ERRVAL(name, syscall_name, args)	\
+  .text;						\
+  ENTRY (name)						\
+  DO_CALL (syscall_name, args);				\
+  not	a0;						\
+  addi	a0, 1
+
+# undef PSEUDO_END_ERRVAL
+# define PSEUDO_END_ERRVAL(name) END (name)
+
+# define ret_ERRVAL rts
+
+# if !IS_IN (libc)
+#  define SYSCALL_ERROR __local_syscall_error
+#  if RTLD_PRIVATE_ERRNO
+#   ifdef __PIC__
+#    define SYSCALL_ERROR_HANDLER	\
+__local_syscall_error:			\
+	lrw	a1, rtld_errno@PLT; 	\
+	addu	a1, gb;			\
+	ldw	a1, (a1);		\
+	rsubi	a0, 0;			\
+	stw	a0, (a1);		\
+	bmaski	a0, 0;			\
+	rts
+#   else /* __PIC__ */
+#    define SYSCALL_ERROR_HANDLER	\
+__local_syscall_error:			\
+	lrw	a1, rtld_errno;		\
+	rsubi	a0, 0;			\
+	stw	a0, (a1);		\
+	bmaski	a0, 0;			\
+	rts
+#   endif /* __PIC__ */
+#  else /* !RTLD_PRIVATE_ERRNO */
+#   ifdef __PIC__
+#    define SYSCALL_ERROR_HANDLER		\
+__local_syscall_error:				\
+	subi	sp, 8;				\
+	stw	a0, (sp, 0);			\
+	stw	r15, (sp, 4);			\
+	lrw	a1, __errno_location@PLT;	\
+	add	a1, gb;				\
+	ldw	a1, (a1);			\
+	jsr	a1;				\
+	ldw	a1, (sp, 0); /* load errno*/	\
+	ldw	r15, (sp, 4);			\
+	addi	sp, 8;				\
+	movi	a2, 0;				\
+	rsub	a1, a1, a2;			\
+	stw	a1, (a0);			\
+	bmaski	a0, 0;				\
+	rts
+#    else
+#     define SYSCALL_ERROR_HANDLER 		\
+__local_syscall_error:				\
+	subi	sp, 8;				\
+	stw	a0, (sp, 0);			\
+	stw	r15, (sp, 4);			\
+	lrw	a1, __errno_location;		\
+	jsr	a1;				\
+	ldw	a1, (sp, 0); /* load errno */	\
+	ldw	r15, (sp, 4);			\
+	addi	sp, 8;				\
+	movi	a2, 0;				\
+	rsub	a1, a1, a2;			\
+	stw	a1, (a0);			\
+	bmaski	a0, 0;				\
+	rts
+#   endif /* __PIC__ */
+#  endif/* RTLD_PRIVATE_ERROR */
+# else
+#  define SYSCALL_ERROR_HANDLER  /* Nothing here; code in sysdep.S is used.  */
+#  define SYSCALL_ERROR __syscall_error
+# endif/* IS_IN (libc) */
+
+/* define DO_CALL */
+# undef DO_CALL
+# define DO_CALL(syscall_name, args)	\
+  DOARGS_##args;			\
+  lrw	r7, SYS_ify(syscall_name);	\
+  trap	0;				\
+  UNDOARGS_##args
+
+# undef  DOARGS_0
+# define DOARGS_0			\
+	subi	sp, 8;			\
+	cfi_adjust_cfa_offset (8);	\
+	stw	r7, (sp, 0);		\
+	cfi_rel_offset (r7, 0);
+
+# undef  DOARGS_1
+# define DOARGS_1 DOARGS_0
+# undef  DOARGS_2
+# define DOARGS_2 DOARGS_0
+# undef  DOARGS_3
+# define DOARGS_3 DOARGS_0
+# undef  DOARGS_4
+# define DOARGS_4 DOARGS_0
+# undef  DOARGS_5
+# define DOARGS_5			\
+	subi	sp, 8;			\
+	cfi_adjust_cfa_offset (8);	\
+	stw	r7, (sp, 0);		\
+	cfi_rel_offset (7, 0);		\
+	stw	r4, (sp, 4);		\
+	cfi_rel_offset (4, 4);		\
+	ldw	r4, (sp, 8)
+# undef  DOARGS_6
+# define DOARGS_6			\
+	subi	sp, 16;			\
+	cfi_adjust_cfa_offset (16);	\
+	stw	r7, (sp, 0);		\
+	cfi_rel_offset (7, 0);		\
+	stw	r4, (sp, 4);		\
+	cfi_rel_offset (4, 4);		\
+	stw	r5, (sp, 8);		\
+	cfi_rel_offset (5, 8);		\
+	ldw	r4, (sp, 16);		\
+	ldw	r5, (sp, 20)
+
+# undef  UNDOARGS_0
+# define UNDOARGS_0 \
+  ldw  r7, (sp, 0); \
+  cfi_restore (r7); \
+  addi sp, 8;   \
+  cfi_adjust_cfa_offset (-8);
+
+# undef  UNDOARGS_1
+# define UNDOARGS_1 UNDOARGS_0
+# undef  UNDOARGS_2
+# define UNDOARGS_2 UNDOARGS_0
+# undef  UNDOARGS_3
+# define UNDOARGS_3 UNDOARGS_0
+# undef  UNDOARGS_4
+# define UNDOARGS_4 UNDOARGS_0
+# undef  UNDOARGS_5
+# define UNDOARGS_5			\
+	ldw	r7, (sp, 0);		\
+	cfi_restore (r4);		\
+	ldw	r4, (sp, 4);		\
+	cfi_restore (r4);		\
+	addi	sp, 8;			\
+	cfi_adjust_cfa_offset (-8);
+
+# undef  UNDOARGS_6
+# define UNDOARGS_6			\
+	ldw	r7, (sp, 0);		\
+	cfi_restore (r7);		\
+	ldw	r4, (sp, 4);		\
+	cfi_restore (r4);		\
+	ldw	r5, (sp, 8);		\
+	cfi_restore (r5);		\
+	addi	sp, 16;			\
+	cfi_adjust_cfa_offset (-16);
+
+#else /* not __ASSEMBLER__ */
+
+/* Define a macro which expands into the inline wrapper code for a system
+   call.  */
+# undef INLINE_SYSCALL
+# define INLINE_SYSCALL(name, nr, args...)				\
+  ({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args);	\
+     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result,), 0))	\
+       {								\
+	 __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, ));		\
+	 _sys_result = (unsigned int) -1;				\
+       }								\
+     (int) _sys_result; })
+
+# undef INTERNAL_SYSCALL_DECL
+# define INTERNAL_SYSCALL_DECL(err) do { } while (0)
+
+# undef INTERNAL_SYSCALL_ERROR_P
+# define INTERNAL_SYSCALL_ERROR_P(val, err) \
+  ((unsigned int) (val) >= 0xffffff01u)
+
+# undef INTERNAL_SYSCALL_ERRNO
+# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
+
+# undef INTERNAL_SYSCALL_RAW
+# define INTERNAL_SYSCALL_RAW0(name, err, dummy...)			\
+  ({unsigned int __sys_result;						\
+     {									\
+       register int _a1 __asm__ ("a0"), _nr __asm__ ("r7");		\
+       _nr = name;							\
+       __asm__ __volatile__ ("trap  0 \n\t"				\
+			     : "=r" (_a1)				\
+			     : "r" (_nr)				\
+			     : "memory");				\
+	       __sys_result = _a1;					\
+     }									\
+     (int) __sys_result; })
+
+# define INTERNAL_SYSCALL_RAW1(name, err, arg1)			\
+  ({unsigned int __sys_result;						\
+    register int _tmp_arg1 = (int)(arg1);				\
+     {									\
+       register int _a1 __asm__ ("a0"), _nr __asm__ ("r7");		\
+       _a1 = _tmp_arg1;							\
+       _nr = name;							\
+       __asm__ __volatile__ ("trap  0 \n\t"				\
+			     : "=r" (_a1)				\
+			     : "r" (_nr), "r" (_a1)			\
+			     : "memory");				\
+	       __sys_result = _a1;					\
+     }									\
+     (int) __sys_result; })
+
+# define INTERNAL_SYSCALL_RAW2(name, err, arg1, arg2)			\
+  ({unsigned int __sys_result;						\
+    register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2);	\
+     {									\
+       register int _nr __asm__ ("r7");					\
+       register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1");		\
+       _a1 = _tmp_arg1, _a2 = _tmp_arg2;				\
+       _nr = name;							\
+       __asm__ __volatile__ ("trap  0 \n\t"				\
+			     : "=r" (_a1)				\
+			     : "r" (_nr), "r" (_a1), "r" (_a2)		\
+			     : "memory");				\
+	       __sys_result = _a1;					\
+     }									\
+     (int) __sys_result; })
+
+# define INTERNAL_SYSCALL_RAW3(name, err, arg1, arg2, arg3)		\
+  ({unsigned int __sys_result;						\
+    register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2);	\
+    register int _tmp_arg3 = (int)(arg3);				\
+     {									\
+       register int _nr __asm__ ("r7");					\
+       register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1");		\
+       register int _a3 __asm__ ("a2");					\
+       _a1 = _tmp_arg1;							\
+       _a2 = _tmp_arg2;							\
+       _a3 = _tmp_arg3;							\
+       _nr = name;							\
+       __asm__ __volatile__ ("trap  0 \n\t"				\
+			     : "=r" (_a1)				\
+			     : "r" (_nr), "r" (_a1), "r" (_a2),		\
+			       "r" (_a3)				\
+			     : "memory");				\
+	       __sys_result = _a1;					\
+     }									\
+     (int) __sys_result; })
+
+# define INTERNAL_SYSCALL_RAW4(name, err, arg1, arg2, arg3, arg4)	\
+  ({unsigned int __sys_result;						\
+    register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2);	\
+    register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4);	\
+     {									\
+       register int _nr __asm__ ("r7");					\
+       register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1");		\
+       register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3");		\
+       _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3;		\
+       _a4 = _tmp_arg4;							\
+       _nr = name;							\
+       __asm__ __volatile__ ("trap  0 \n\t"				\
+			     : "=r" (_a1)				\
+			     : "r" (_nr), "r" (_a1), "r" (_a2),		\
+			       "r" (_a3), "r" (_a4)			\
+			     : "memory");				\
+	       __sys_result = _a1;					\
+     }									\
+     (int) __sys_result; })
+
+# define INTERNAL_SYSCALL_RAW5(name, err, arg1, arg2, arg3, arg4,	\
+			      arg5)					\
+  ({unsigned int __sys_result;						\
+    register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2);	\
+    register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4);	\
+    register int _tmp_arg5 = (int)(arg5);				\
+     {									\
+       register int _nr __asm__ ("r7");					\
+       register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1");		\
+       register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3");		\
+       register int _a5 __asm__ ("r4");					\
+       _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3;		\
+       _a4 = _tmp_arg4, _a5 = _tmp_arg5;				\
+       _nr = name;							\
+       __asm__ __volatile__ ("trap  0 \n\t"				\
+			     : "=r" (_a1)				\
+			     : "r" (_nr), "r" (_a1), "r" (_a2),		\
+			       "r" (_a3), "r" (_a4), "r" (_a5)		\
+			     : "memory");				\
+	       __sys_result = _a1;					\
+     }									\
+     (int) __sys_result; })
+
+# define INTERNAL_SYSCALL_RAW6(name, err, arg1, arg2, arg3, arg4,	\
+			      arg5, arg6)				\
+  ({unsigned int __sys_result;						\
+    register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2);	\
+    register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4);	\
+    register int _tmp_arg5 = (int)(arg5), _tmp_arg6 = (int)(arg6);	\
+     {									\
+       register int _nr __asm__ ("r7");					\
+       register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1");		\
+       register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3");		\
+       register int _a5 __asm__ ("r4"), _a6 __asm__ ("r5");		\
+       _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3;		\
+       _a4 = _tmp_arg4, _a5 = _tmp_arg5, _a6 = _tmp_arg6;		\
+       _nr = name;							\
+       __asm__ __volatile__ ("trap  0 \n\t"				\
+			     : "=r" (_a1)				\
+			     : "r" (_nr), "r" (_a1), "r" (_a2),		\
+			       "r" (_a3), "r" (_a4), "r" (_a5),		\
+			       "r" (_a6)				\
+			     : "memory");				\
+	       __sys_result = _a1;					\
+     }									\
+     (int) __sys_result; })
+
+# define INTERNAL_SYSCALL_RAW7(name, err, arg1, arg2, arg3, arg4,	\
+			      arg5, arg6, arg7)				\
+  ({unsigned int __sys_result;						\
+    register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2);	\
+    register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4);	\
+    register int _tmp_arg5 = (int)(arg5), _tmp_arg6 = (int)(arg6);	\
+    register int _tmp_arg7 = (int)(arg7);				\
+     {									\
+       register int _nr __asm__ ("r7");					\
+       register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1");		\
+       register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3");		\
+       register int _a5 __asm__ ("r4"), _a6 __asm__ ("r5");		\
+       register int _a7 __asm__ ("r6");					\
+       _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3;		\
+       _a4 = _tmp_arg4, _a5 = _tmp_arg5, _a6 = _tmp_arg6;		\
+       _a7 = _tmp_arg7;							\
+       _nr = name;							\
+       __asm__ __volatile__ ("trap  0 \n\t"				\
+			     : "=r" (_a1)				\
+			     : "r" (_nr), "r" (_a1), "r" (_a2),		\
+			       "r" (_a3), "r" (_a4), "r" (_a5),		\
+			       "r" (_a6), "r" (_a7)			\
+			     : "memory");				\
+	       __sys_result = _a1;					\
+     }									\
+     (int) __sys_result; })
+
+# undef INTERNAL_SYSCALL
+# define INTERNAL_SYSCALL(name, err, nr, args...)		\
+  INTERNAL_SYSCALL_RAW##nr(SYS_ify(name), err, args)
+
+# undef INTERNAL_SYSCALL_NCS
+# define INTERNAL_SYSCALL_NCS(number, err, nr, args...)		\
+  INTERNAL_SYSCALL_RAW##nr (number, err, args)
+
+#endif /* __ASSEMBLER__ */
+
+/* Pointer mangling support.  */
+#if (IS_IN (rtld) || \
+     (!defined SHARED && (IS_IN (libc) || IS_IN (libpthread))))
+# ifdef __ASSEMBLER__
+#  define PTR_MANGLE(dst, src, guard)			\
+	grs	t0, 1f;					\
+1:							\
+	lrw	guard, 1b@GOTPC;			\
+	addu	t0, guard;				\
+	lrw	guard, __pointer_chk_guard_local@GOT;	\
+	ldr.w	guard, (t0, guard << 0);		\
+	ldw	guard, (guard, 0);			\
+	xor	dst, src, guard;
+#  define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
+#  define PTR_MANGLE2(dst, src, guard) \
+	xor	dst, src, guard
+#  define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
+# else
+extern uintptr_t __pointer_chk_guard_local;
+#  define PTR_MANGLE(var) \
+  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
+#  define PTR_DEMANGLE(var) PTR_MANGLE (var)
+# endif
+#else
+# ifdef __ASSEMBLER__
+#  define PTR_MANGLE(dst, src, guard)		\
+	grs	t0, 1f;				\
+1:						\
+	lrw	guard, 1b@GOTPC;		\
+	addu	t0, guard;			\
+	lrw	guard, __pointer_chk_guard@GOT;	\
+	ldr.w	guard, (t0, guard << 0);	\
+	ldw	guard, (guard, 0);		\
+	xor	dst, src, guard;
+#  define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
+#  define PTR_MANGLE2(dst, src, guard) \
+	xor	dst, src, guard
+#  define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
+# else
+extern uintptr_t __pointer_chk_guard;
+#  define PTR_MANGLE(var) \
+  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
+#  define PTR_DEMANGLE(var) PTR_MANGLE (var)
+# endif
+#endif
+
+#endif /* linux/csky/sysdep.h */