[07/11] nds32: Linux Syscall Interface

Message ID 1525617685-32083-8-git-send-email-vincentc@andestech.com
State New
Headers show
Series
  • nds32 glibc Port v1
Related show

Commit Message

Vincent Chen May 6, 2018, 2:41 p.m.
This patch contains the Linux system call interface, as well as the
definitions of a handful of system calls.
---
 sysdeps/unix/sysv/linux/nds32/arch-fork.h      |  27 ++
 sysdeps/unix/sysv/linux/nds32/clone.S          |  66 +++++
 sysdeps/unix/sysv/linux/nds32/profil-counter.h |  31 +++
 sysdeps/unix/sysv/linux/nds32/pt-vfork.S       |   1 +
 sysdeps/unix/sysv/linux/nds32/readahead.c      |  36 +++
 sysdeps/unix/sysv/linux/nds32/syscall.c        |  39 +++
 sysdeps/unix/sysv/linux/nds32/syscalls.list    |   2 +
 sysdeps/unix/sysv/linux/nds32/sysdep.c         |  30 +++
 sysdeps/unix/sysv/linux/nds32/sysdep.h         | 337 +++++++++++++++++++++++++
 9 files changed, 569 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/nds32/arch-fork.h
 create mode 100644 sysdeps/unix/sysv/linux/nds32/clone.S
 create mode 100644 sysdeps/unix/sysv/linux/nds32/profil-counter.h
 create mode 100644 sysdeps/unix/sysv/linux/nds32/pt-vfork.S
 create mode 100644 sysdeps/unix/sysv/linux/nds32/readahead.c
 create mode 100644 sysdeps/unix/sysv/linux/nds32/syscall.c
 create mode 100644 sysdeps/unix/sysv/linux/nds32/syscalls.list
 create mode 100644 sysdeps/unix/sysv/linux/nds32/sysdep.c
 create mode 100644 sysdeps/unix/sysv/linux/nds32/sysdep.h

Comments

Adhemerval Zanella May 8, 2018, 9:27 p.m. | #1
On 06/05/2018 11:41, vincentc wrote:
> This patch contains the Linux system call interface, as well as the
> definitions of a handful of system calls.
> ---
>  sysdeps/unix/sysv/linux/nds32/arch-fork.h      |  27 ++
>  sysdeps/unix/sysv/linux/nds32/clone.S          |  66 +++++
>  sysdeps/unix/sysv/linux/nds32/profil-counter.h |  31 +++
>  sysdeps/unix/sysv/linux/nds32/pt-vfork.S       |   1 +
>  sysdeps/unix/sysv/linux/nds32/readahead.c      |  36 +++
>  sysdeps/unix/sysv/linux/nds32/syscall.c        |  39 +++
>  sysdeps/unix/sysv/linux/nds32/syscalls.list    |   2 +
>  sysdeps/unix/sysv/linux/nds32/sysdep.c         |  30 +++
>  sysdeps/unix/sysv/linux/nds32/sysdep.h         | 337 +++++++++++++++++++++++++
>  9 files changed, 569 insertions(+)
>  create mode 100644 sysdeps/unix/sysv/linux/nds32/arch-fork.h
>  create mode 100644 sysdeps/unix/sysv/linux/nds32/clone.S
>  create mode 100644 sysdeps/unix/sysv/linux/nds32/profil-counter.h
>  create mode 100644 sysdeps/unix/sysv/linux/nds32/pt-vfork.S
>  create mode 100644 sysdeps/unix/sysv/linux/nds32/readahead.c
>  create mode 100644 sysdeps/unix/sysv/linux/nds32/syscall.c
>  create mode 100644 sysdeps/unix/sysv/linux/nds32/syscalls.list
>  create mode 100644 sysdeps/unix/sysv/linux/nds32/sysdep.c
>  create mode 100644 sysdeps/unix/sysv/linux/nds32/sysdep.h
> 
> diff --git a/sysdeps/unix/sysv/linux/nds32/arch-fork.h b/sysdeps/unix/sysv/linux/nds32/arch-fork.h
> new file mode 100644
> index 0000000..e86143a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/nds32/arch-fork.h
> @@ -0,0 +1,27 @@
> +/* ARCH_FORK definition for Linux fork implementation, Andes Linux/nds32 version.
> +   Copyright (C) 2002-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 <sched.h>
> +#include <sysdep.h>
> +#include <tls.h>
> +
> +#define ARCH_FORK() \
> +  INLINE_SYSCALL (clone, 5,                                                  \
> +                 CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,     \
> +                 NULL, NULL, &THREAD_SELF->tid)
> +

The clone syscall for fork implementation was consolidate (commit
3dc214977beccc95f0df3b90fa4ca2557fe1bdd2).  The new ports need to redefine
it iff the clone kernel ABI does not follow the generic expect one
(check sysdeps/unix/sysv/linux/kernel-features.h:119).


> diff --git a/sysdeps/unix/sysv/linux/nds32/readahead.c b/sysdeps/unix/sysv/linux/nds32/readahead.c
> new file mode 100644
> index 0000000..5559619
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/nds32/readahead.c

Joseph already noted this files should not be required.

> diff --git a/sysdeps/unix/sysv/linux/nds32/syscall.c b/sysdeps/unix/sysv/linux/nds32/syscall.c
> new file mode 100644
> index 0000000..77af6bb
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/nds32/syscall.c
> @@ -0,0 +1,39 @@
> +/* System call interface, Andes nds32 version.
> +   Copyright (C) 2001-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 <errno.h>
> +#include <stdarg.h>
> +#include <sysdep.h>
> +long int syscall (long int __sysno, ...)
> +{
> +
> +	int result;
> +	unsigned long arg1,arg2,arg3,arg4,arg5,arg6;
> +	va_list arg;
> +	va_start (arg, __sysno);
> +	arg1 = va_arg (arg, unsigned long);
> +	arg2 = va_arg (arg, unsigned long);
> +	arg3 = va_arg (arg, unsigned long);
> +	arg4 = va_arg (arg, unsigned long);
> +	arg5 = va_arg (arg, unsigned long);
> +	arg6 = va_arg (arg, unsigned long);
> +	va_end (arg);
> +	__asm__ volatile ( "" ::: "memory" );
> +	result = INLINE_SYSCALL_NCS(__sysno,6,arg1,arg2,arg3,arg4,arg5,arg6);
> +	return result;
> +}

Maybe we could it as a generic version, the only points I am not sure if why
you need a compiler memory barrier here.
Vincent Chen May 9, 2018, 1:46 p.m. | #2
On Wed, May 09, 2018 at 05:27:16AM +0800, Adhemerval Zanella wrote:
> 
> 
> On 06/05/2018 11:41, vincentc wrote:
> > This patch contains the Linux system call interface, as well as the
> > definitions of a handful of system calls.
> > ---
> >  sysdeps/unix/sysv/linux/nds32/arch-fork.h      |  27 ++
> >  sysdeps/unix/sysv/linux/nds32/clone.S          |  66 +++++
> >  sysdeps/unix/sysv/linux/nds32/profil-counter.h |  31 +++
> >  sysdeps/unix/sysv/linux/nds32/pt-vfork.S       |   1 +
> >  sysdeps/unix/sysv/linux/nds32/readahead.c      |  36 +++
> >  sysdeps/unix/sysv/linux/nds32/syscall.c        |  39 +++
> >  sysdeps/unix/sysv/linux/nds32/syscalls.list    |   2 +
> >  sysdeps/unix/sysv/linux/nds32/sysdep.c         |  30 +++
> >  sysdeps/unix/sysv/linux/nds32/sysdep.h         | 337 +++++++++++++++++++++++++
> >  9 files changed, 569 insertions(+)
> >  create mode 100644 sysdeps/unix/sysv/linux/nds32/arch-fork.h
> >  create mode 100644 sysdeps/unix/sysv/linux/nds32/clone.S
> >  create mode 100644 sysdeps/unix/sysv/linux/nds32/profil-counter.h
> >  create mode 100644 sysdeps/unix/sysv/linux/nds32/pt-vfork.S
> >  create mode 100644 sysdeps/unix/sysv/linux/nds32/readahead.c
> >  create mode 100644 sysdeps/unix/sysv/linux/nds32/syscall.c
> >  create mode 100644 sysdeps/unix/sysv/linux/nds32/syscalls.list
> >  create mode 100644 sysdeps/unix/sysv/linux/nds32/sysdep.c
> >  create mode 100644 sysdeps/unix/sysv/linux/nds32/sysdep.h
> > 
> > diff --git a/sysdeps/unix/sysv/linux/nds32/arch-fork.h b/sysdeps/unix/sysv/linux/nds32/arch-fork.h
> > new file mode 100644
> > index 0000000..e86143a
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/nds32/arch-fork.h
> > @@ -0,0 +1,27 @@
> > +/* ARCH_FORK definition for Linux fork implementation, Andes Linux/nds32 version.
> > +   Copyright (C) 2002-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 <sched.h>
> > +#include <sysdep.h>
> > +#include <tls.h>
> > +
> > +#define ARCH_FORK() \
> > +  INLINE_SYSCALL (clone, 5,                                                  \
> > +                 CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,     \
> > +                 NULL, NULL, &THREAD_SELF->tid)
> > +
> 
> The clone syscall for fork implementation was consolidate (commit
> 3dc214977beccc95f0df3b90fa4ca2557fe1bdd2).  The new ports need to redefine
> it iff the clone kernel ABI does not follow the generic expect one
> (check sysdeps/unix/sysv/linux/kernel-features.h:119).
> 
>

OK, I will modify it in the next version patch.
 
> > diff --git a/sysdeps/unix/sysv/linux/nds32/readahead.c b/sysdeps/unix/sysv/linux/nds32/readahead.c
> > new file mode 100644
> > index 0000000..5559619
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/nds32/readahead.c
> 
> Joseph already noted this files should not be required.
> 

OK.

> > diff --git a/sysdeps/unix/sysv/linux/nds32/syscall.c b/sysdeps/unix/sysv/linux/nds32/syscall.c
> > new file mode 100644
> > index 0000000..77af6bb
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/nds32/syscall.c
> > @@ -0,0 +1,39 @@
> > +/* System call interface, Andes nds32 version.
> > +   Copyright (C) 2001-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 <errno.h>
> > +#include <stdarg.h>
> > +#include <sysdep.h>
> > +long int syscall (long int __sysno, ...)
> > +{
> > +
> > +	int result;
> > +	unsigned long arg1,arg2,arg3,arg4,arg5,arg6;
> > +	va_list arg;
> > +	va_start (arg, __sysno);
> > +	arg1 = va_arg (arg, unsigned long);
> > +	arg2 = va_arg (arg, unsigned long);
> > +	arg3 = va_arg (arg, unsigned long);
> > +	arg4 = va_arg (arg, unsigned long);
> > +	arg5 = va_arg (arg, unsigned long);
> > +	arg6 = va_arg (arg, unsigned long);
> > +	va_end (arg);
> > +	__asm__ volatile ( "" ::: "memory" );
> > +	result = INLINE_SYSCALL_NCS(__sysno,6,arg1,arg2,arg3,arg4,arg5,arg6);
> > +	return result;
> > +}
> 
> Maybe we could it as a generic version, the only points I am not sure if why
> you need a compiler memory barrier here.

The compiler memory barrier is used to ensuring that the input argument has been
stored to the targeted register before issuing syscall in compile time.


Thanks for your suggestions

Best regards
Vincent Chen
Adhemerval Zanella May 9, 2018, 1:57 p.m. | #3
On 09/05/2018 10:46, Vincent Chen wrote:
> On Wed, May 09, 2018 at 05:27:16AM +0800, Adhemerval Zanella wrote:
>>
>>
>> On 06/05/2018 11:41, vincentc wrote:
>>> This patch contains the Linux system call interface, as well as the

[...]

>>> +#include <errno.h>
>>> +#include <stdarg.h>
>>> +#include <sysdep.h>
>>> +long int syscall (long int __sysno, ...)
>>> +{
>>> +
>>> +	int result;
>>> +	unsigned long arg1,arg2,arg3,arg4,arg5,arg6;
>>> +	va_list arg;
>>> +	va_start (arg, __sysno);
>>> +	arg1 = va_arg (arg, unsigned long);
>>> +	arg2 = va_arg (arg, unsigned long);
>>> +	arg3 = va_arg (arg, unsigned long);
>>> +	arg4 = va_arg (arg, unsigned long);
>>> +	arg5 = va_arg (arg, unsigned long);
>>> +	arg6 = va_arg (arg, unsigned long);
>>> +	va_end (arg);
>>> +	__asm__ volatile ( "" ::: "memory" );
>>> +	result = INLINE_SYSCALL_NCS(__sysno,6,arg1,arg2,arg3,arg4,arg5,arg6);
>>> +	return result;
>>> +}
>>
>> Maybe we could it as a generic version, the only points I am not sure if why
>> you need a compiler memory barrier here.
> 
> The compiler memory barrier is used to ensuring that the input argument has been
> stored to the targeted register before issuing syscall in compile time.

My understanding is INLINE_SYSCALL_NCS is already issues the syscall with a asm 
volatile, so it should prevent any instruction reordering from compiler to mess
with expected kernel register allocation.  Are you seeing a miscompile without
the barrier?
Vincent Chen May 10, 2018, 2:58 a.m. | #4
On Wed, May 09, 2018 at 10:57:25AM -0300, Adhemerval Zanella wrote:
> 
> 
> On 09/05/2018 10:46, Vincent Chen wrote:
> > On Wed, May 09, 2018 at 05:27:16AM +0800, Adhemerval Zanella wrote:
> >>
> >>
> >> On 06/05/2018 11:41, vincentc wrote:
> >>> This patch contains the Linux system call interface, as well as the
> 
> [...]
> 
> >>> +#include <errno.h>
> >>> +#include <stdarg.h>
> >>> +#include <sysdep.h>
> >>> +long int syscall (long int __sysno, ...)
> >>> +{
> >>> +
> >>> +	int result;
> >>> +	unsigned long arg1,arg2,arg3,arg4,arg5,arg6;
> >>> +	va_list arg;
> >>> +	va_start (arg, __sysno);
> >>> +	arg1 = va_arg (arg, unsigned long);
> >>> +	arg2 = va_arg (arg, unsigned long);
> >>> +	arg3 = va_arg (arg, unsigned long);
> >>> +	arg4 = va_arg (arg, unsigned long);
> >>> +	arg5 = va_arg (arg, unsigned long);
> >>> +	arg6 = va_arg (arg, unsigned long);
> >>> +	va_end (arg);
> >>> +	__asm__ volatile ( "" ::: "memory" );
> >>> +	result = INLINE_SYSCALL_NCS(__sysno,6,arg1,arg2,arg3,arg4,arg5,arg6);
> >>> +	return result;
> >>> +}
> >>
> >> Maybe we could it as a generic version, the only points I am not sure if why
> >> you need a compiler memory barrier here.
> > 
> > The compiler memory barrier is used to ensuring that the input argument has been
> > stored to the targeted register before issuing syscall in compile time.
> 
> My understanding is INLINE_SYSCALL_NCS is already issues the syscall with a asm 
> volatile, so it should prevent any instruction reordering from compiler to mess
> with expected kernel register allocation.  Are you seeing a miscompile without
> the barrier?

I apologize for giving you incorrect information. After I rechecking the git log
of this file, I think this memory barrier is not needed anymore. Originally, we
need to push the 6-th argument to the stack before invoking the system call. In
order to make sure that the value of 6-th argument is correct in stack, we need
a memory barrier which is located between storing 6-th argument to register $r6
and pushing register $r6 to stack. However, the above procedure was not needed
after we modified system call ABI. So, I think the memory barrier is not needed
now. I will remove it in the next version patch.


Thanks for your suggestions.

Best regards
Vincent Chen
Florian Weimer May 12, 2018, 7:21 a.m. | #5
On 05/10/2018 04:58 AM, Vincent Chen wrote:
>>>>> +#include <errno.h>
>>>>> +#include <stdarg.h>
>>>>> +#include <sysdep.h>
>>>>> +long int syscall (long int __sysno, ...)
>>>>> +{
>>>>> +
>>>>> +	int result;
>>>>> +	unsigned long arg1,arg2,arg3,arg4,arg5,arg6;
>>>>> +	va_list arg;
>>>>> +	va_start (arg, __sysno);
>>>>> +	arg1 = va_arg (arg, unsigned long);
>>>>> +	arg2 = va_arg (arg, unsigned long);
>>>>> +	arg3 = va_arg (arg, unsigned long);
>>>>> +	arg4 = va_arg (arg, unsigned long);
>>>>> +	arg5 = va_arg (arg, unsigned long);
>>>>> +	arg6 = va_arg (arg, unsigned long);
>>>>> +	va_end (arg);
>>>>> +	__asm__ volatile ( "" ::: "memory" );
>>>>> +	result = INLINE_SYSCALL_NCS(__sysno,6,arg1,arg2,arg3,arg4,arg5,arg6);
>>>>> +	return result;
>>>>> +}

> So, I think the memory barrier is not needed
> now. I will remove it in the next version patch.

Please also fix the style issues—syscall should be at the start of the 
line, and there should be spaces after the commas, before (, but not 
after ( and before ).

Thanks,
Florian
Vincent Chen May 14, 2018, 5:29 a.m. | #6
On Sat, May 12, 2018 at 03:21:22PM +0800, Florian Weimer wrote:
> On 05/10/2018 04:58 AM, Vincent Chen wrote:
> >>>>> +#include <errno.h>
> >>>>> +#include <stdarg.h>
> >>>>> +#include <sysdep.h>
> >>>>> +long int syscall (long int __sysno, ...)
> >>>>> +{
> >>>>> +
> >>>>> +	int result;
> >>>>> +	unsigned long arg1,arg2,arg3,arg4,arg5,arg6;
> >>>>> +	va_list arg;
> >>>>> +	va_start (arg, __sysno);
> >>>>> +	arg1 = va_arg (arg, unsigned long);
> >>>>> +	arg2 = va_arg (arg, unsigned long);
> >>>>> +	arg3 = va_arg (arg, unsigned long);
> >>>>> +	arg4 = va_arg (arg, unsigned long);
> >>>>> +	arg5 = va_arg (arg, unsigned long);
> >>>>> +	arg6 = va_arg (arg, unsigned long);
> >>>>> +	va_end (arg);
> >>>>> +	__asm__ volatile ( "" ::: "memory" );
> >>>>> +	result = INLINE_SYSCALL_NCS(__sysno,6,arg1,arg2,arg3,arg4,arg5,arg6);
> >>>>> +	return result;
> >>>>> +}
> 
> > So, I think the memory barrier is not needed
> > now. I will remove it in the next version patch.
> 
> Please also fix the style issues???syscall should be at the start of the 
> line, and there should be spaces after the commas, before (, but not 
> after ( and before ).
> 
> Thanks,
> Florian

OK, I will modify it in the next version patch.

Thanks for your suggestions.

Best regards
Vincent Chen

Patch

diff --git a/sysdeps/unix/sysv/linux/nds32/arch-fork.h b/sysdeps/unix/sysv/linux/nds32/arch-fork.h
new file mode 100644
index 0000000..e86143a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nds32/arch-fork.h
@@ -0,0 +1,27 @@ 
+/* ARCH_FORK definition for Linux fork implementation, Andes Linux/nds32 version.
+   Copyright (C) 2002-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 <sched.h>
+#include <sysdep.h>
+#include <tls.h>
+
+#define ARCH_FORK() \
+  INLINE_SYSCALL (clone, 5,                                                  \
+                 CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,     \
+                 NULL, NULL, &THREAD_SELF->tid)
+
diff --git a/sysdeps/unix/sysv/linux/nds32/clone.S b/sysdeps/unix/sysv/linux/nds32/clone.S
new file mode 100644
index 0000000..c7ce891
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nds32/clone.S
@@ -0,0 +1,66 @@ 
+/* Wrapper around clone system call, Andes nds32 version.
+   Copyright (C) 1996-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/>.  */
+
+/* clone() is even more special than fork() as it mucks with stacks
+   and invokes a function in the right context after its all over.  */
+
+#include <sysdep.h>
+#define _ERRNO_H	1
+#include <bits/errno.h>
+
+/* int clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+	    void *parent_tidptr, void *tls, void *child_tidptr).  */
+
+ENTRY(__clone)
+	/* Sanity check arguments.  */
+	beqz	$r0, 1f
+	bnez	$r1, 2f
+1:
+	movi	$r0, -EINVAL
+5:
+	j	SYSCALL_ERROR_LABEL
+2:
+	/* Child's $sp will be $r1, push to child's stack only.  */
+	addi	$r1, $r1, -4
+	swi.p	$r3, [$r1], -4
+	swi	$r0, [$r1]
+
+	/* Do the system call.  */
+	move	$r0, $r2
+	move    $r3, $r5
+	move    $r2, $r4
+        lwi     $r4, [$sp]
+	__do_syscall (clone)
+
+	beqz    $r0, 4f
+	bltz    $r0, 5b
+	ret
+4:
+	.cfi_undefined lp
+        /* Restore the arg for user's function.  */
+	pop	$r1	/* Function pointer.  */
+	pop	$r0	/* Argument pointer.  */
+
+        /* Call the user's function.  */
+	bral	$r1
+
+	__do_syscall (exit)
+
+PSEUDO_END (__clone)
+libc_hidden_def (__clone)
+weak_alias (__clone, clone)
diff --git a/sysdeps/unix/sysv/linux/nds32/profil-counter.h b/sysdeps/unix/sysv/linux/nds32/profil-counter.h
new file mode 100644
index 0000000..106371a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nds32/profil-counter.h
@@ -0,0 +1,31 @@ 
+/* Low-level statistical profiling support function, Andes Linux/nds32 version.
+   Copyright (C) 1996-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>
+
+static void
+__profil_counter (int signo, struct ucontext_t * 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/nds32/pt-vfork.S b/sysdeps/unix/sysv/linux/nds32/pt-vfork.S
new file mode 100644
index 0000000..1cc8931
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nds32/pt-vfork.S
@@ -0,0 +1 @@ 
+/* Not needed.  */
diff --git a/sysdeps/unix/sysv/linux/nds32/readahead.c b/sysdeps/unix/sysv/linux/nds32/readahead.c
new file mode 100644
index 0000000..5559619
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nds32/readahead.c
@@ -0,0 +1,36 @@ 
+/* Provide kernel hint to read ahead, Andes nds32 version.
+   Copyright (C) 2002-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 <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+
+
+ssize_t
+__readahead (int fd, off64_t offset, size_t count)
+{
+  return INLINE_SYSCALL (readahead, 5, fd, 0,
+			 __LONG_LONG_PAIR ((off_t) (offset >> 32),
+					   (off_t) (offset & 0xffffffff)),
+			 count);
+}
+
+weak_alias (__readahead, readahead)
diff --git a/sysdeps/unix/sysv/linux/nds32/syscall.c b/sysdeps/unix/sysv/linux/nds32/syscall.c
new file mode 100644
index 0000000..77af6bb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nds32/syscall.c
@@ -0,0 +1,39 @@ 
+/* System call interface, Andes nds32 version.
+   Copyright (C) 2001-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 <errno.h>
+#include <stdarg.h>
+#include <sysdep.h>
+long int syscall (long int __sysno, ...)
+{
+
+	int result;
+	unsigned long arg1,arg2,arg3,arg4,arg5,arg6;
+	va_list arg;
+	va_start (arg, __sysno);
+	arg1 = va_arg (arg, unsigned long);
+	arg2 = va_arg (arg, unsigned long);
+	arg3 = va_arg (arg, unsigned long);
+	arg4 = va_arg (arg, unsigned long);
+	arg5 = va_arg (arg, unsigned long);
+	arg6 = va_arg (arg, unsigned long);
+	va_end (arg);
+	__asm__ volatile ( "" ::: "memory" );
+	result = INLINE_SYSCALL_NCS(__sysno,6,arg1,arg2,arg3,arg4,arg5,arg6);
+	return result;
+}
diff --git a/sysdeps/unix/sysv/linux/nds32/syscalls.list b/sysdeps/unix/sysv/linux/nds32/syscalls.list
new file mode 100644
index 0000000..11cd965
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nds32/syscalls.list
@@ -0,0 +1,2 @@ 
+# File name	Caller	Syscall name	Args	Strong name
+cacheflush	-	cacheflush	i:pii	cacheflush	
diff --git a/sysdeps/unix/sysv/linux/nds32/sysdep.c b/sysdeps/unix/sysv/linux/nds32/sysdep.c
new file mode 100644
index 0000000..9bcf642
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nds32/sysdep.c
@@ -0,0 +1,30 @@ 
+/* Stach an error number into errno
+   Copyright (C) 2011-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 <sysdep.h>
+#include <errno.h>
+
+/* This routine is jumped to by all the syscall handlers, to stash
+   an error number into errno.  */
+long
+__syscall_error (long err)
+{
+  __set_errno (- err);
+  return -1;
+}
diff --git a/sysdeps/unix/sysv/linux/nds32/sysdep.h b/sysdeps/unix/sysv/linux/nds32/sysdep.h
new file mode 100644
index 0000000..20a06a4
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nds32/sysdep.h
@@ -0,0 +1,337 @@ 
+/* Assembly macros for Andes nds32.
+   Copyright (C) 2011-2018
+   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_NDS32_SYSDEP_H
+#define _LINUX_NDS32_SYSDEP_H 1
+
+#include <sysdeps/unix/sysdep.h>
+#include <sysdeps/nds32/sysdep.h>
+#include <sysdeps/unix/sysv/linux/generic/sysdep.h>
+
+#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__
+
+# define __do_syscall(syscall_name)		\
+  movi	$r15,	SYS_ify (syscall_name);		\
+  syscall	0x0;
+
+# define ADJUST_GP				\
+	smw.adm $sp,[$sp],$sp,#0x6;		\
+	cfi_startproc;				\
+	.cfi_adjust_cfa_offset 8;		\
+	.cfi_rel_offset gp, 0;			\
+	.cfi_rel_offset lp, 4;			\
+	GET_GTABLE ($gp)
+
+# define RECOVER_GP				\
+	lmw.bim $sp,[$sp],$sp,#0x6;		\
+	.cfi_adjust_cfa_offset -8;		\
+	.cfi_restore gp;			\
+	.cfi_restore lp;			\
+	cfi_endproc;
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)	\
+  .align 2;					\
+	ENTRY(name);                          	\
+	__do_syscall (syscall_name);            \
+	bgez $r0, 2f;				\
+	sltsi	$r1, $r0, -4096;		\
+	beqz	$r1, SYSCALL_ERROR_LABEL;	\
+  2:
+
+# undef PSEUDO_END
+# define PSEUDO_END(sym)			\
+	cfi_endproc;				\
+	SYSCALL_ERROR_HANDLER			\
+	cfi_startproc;				\
+	END(sym)
+
+/* Performs a system call, not setting errno.  */
+# define PSEUDO_NOERRNO(name, syscall_name, args) \
+  ENTRY (name);                                  \
+  __do_syscall (syscall_name);
+
+# undef PSEUDO_END_NOERRNO
+# define PSEUDO_END_NOERRNO(name)                \
+  END (name)
+
+/* Perfroms a system call, returning the error code.  */
+# undef PSEUDO_ERRVAL
+# define PSEUDO_ERRVAL(name, syscall_name, args) \
+  PSEUDO_NOERRNO (name, syscall_name, args)	\
+  neg $r0, $r0;
+
+# undef PSEUDO_END_ERRVAL
+# define PSEUDO_END_ERRVAL(sym) END (sym)
+
+# define ret_ERRVAL ret
+
+# define ret_NOERRNO ret
+
+# if !IS_IN (libc)
+#  if RTLD_PRIVATE_ERRNO
+#   define SYSCALL_ERROR_HANDLER			\
+SYSCALL_ERROR_LABEL:					\
+	ADJUST_GP					\
+	la	$r1,	(rtld_errno@GOT);		\
+	neg	$r0, 	$r0;				\
+	sw 	$r0,	[$r1];				\
+	li	$r0, 	-1;				\
+	RECOVER_GP					\
+	ret;
+#  else
+#   ifdef PIC
+#    define SYSCALL_ERROR_HANDLER			\
+SYSCALL_ERROR_LABEL:					\
+	ADJUST_GP					\
+	neg	$r0,	$r0;				\
+        sethi   $r15, 	hi20(errno@GOTTPOFF);		\
+        ori     $r15, 	$r15, lo12(errno@GOTTPOFF);	\
+	lw	$r15,	[$r15 + $gp];			\
+	sw	$r0,	[$r25 + $r15];			\
+	li	$r0,	-1;				\
+	RECOVER_GP					\
+	ret;
+#   else
+#    define SYSCALL_ERROR_HANDLER			\
+SYSCALL_ERROR_LABEL:					\
+	neg	$r0,	$r0;				\
+        sethi 	$r15, 	hi20(errno@GOTTPOFF);		\
+        lwi 	$r15, 	[$r15 + lo12(errno@GOTTPOFF)];	\
+	sw	$r0,	[$r25 + $r15];			\
+	li	$r0,	-1;				\
+	ret;
+#   endif /* !PIC */
+#  endif
+# else
+#  ifdef PIC
+#   define SYSCALL_ERROR_HANDLER			\
+SYSCALL_ERROR_LABEL:					\
+	ADJUST_GP					\
+	bal	__syscall_error;			\
+	RECOVER_GP					\
+	ret;
+#  else
+#   define SYSCALL_ERROR_HANDLER			\
+SYSCALL_ERROR_LABEL:					\
+	b	__syscall_error;
+#  endif /* !PIC */
+# endif /* In LIBC */
+
+#else
+
+/* List of system calls which are supported as vsyscalls.  */
+# define HAVE_GETTIMEOFDAY_VSYSCALL	1
+# define HAVE_CLOCK_GETRES_VSYSCALL	1
+# define HAVE_CLOCK_GETTIME_VSYSCALL	1
+
+# define __issue_syscall(syscall_name)                   \
+"       syscall  0x0;\n"
+
+/* Define a macro which expands into the inline wrapper code for a system
+   call.  */
+# undef INLINE_SYSCALL
+# define INLINE_SYSCALL(name, nr, args...)                       \
+  ({                                                             \
+     INTERNAL_SYSCALL_DECL (err);                                \
+     long result_var = INTERNAL_SYSCALL (name, err, nr, args);   \
+     if (INTERNAL_SYSCALL_ERROR_P (result_var, err))             \
+       {                                                         \
+         __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \
+			result_var = -1 ;			 \
+       }                                                         \
+     result_var;                                                 \
+  })
+
+# undef INLINE_SYSCALL_NC
+# define INLINE_SYSCALL_NCS(name, nr, args...)                     \
+  ({                                                               \
+     INTERNAL_SYSCALL_DECL (err);                                  \
+     long result_var = INTERNAL_SYSCALL_NCS (name, err, nr, args); \
+     if (INTERNAL_SYSCALL_ERROR_P (result_var, err))               \
+       {                                                           \
+         __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err));   \
+			result_var = -1 ;			   \
+       }                                                           \
+     result_var;                                                   \
+  })
+# 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) >= 0xfffff001u)
+
+# undef INTERNAL_SYSCALL_ERRNO
+# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
+
+# undef INTERNAL_SYSCALL
+# define INTERNAL_SYSCALL(name, err, nr, args...) \
+       internal_syscall##nr (__NR_##name, err, args)
+
+# undef INTERNAL_SYSCALL_NCS
+# define INTERNAL_SYSCALL_NCS(syscallno, err, nr, args...) \
+       internal_syscall##nr (syscallno, err, args)
+
+# define internal_syscall0(name, err, dummy...)                  \
+  ({                                                             \
+       register long __res  asm ("$r0");                         \
+       register long __num asm ("$r15") = (long) (name);   	 \
+       __asm__ volatile (                                        \
+       __issue_syscall (name)                                    \
+       : "=r" (__res)                                            \
+       : "r" (__num)                                             \
+       : __SYSCALL_CLOBBERS);                                    \
+       __res;							 \
+  })
+
+# define internal_syscall1(name, err, arg1)                      \
+  ({                                                             \
+       register long __res  asm ("$r0");                         \
+       register long __num asm ("$r15") = (long) (name);   	 \
+       register long __arg1 asm ("$r0") = (long) (arg1);         \
+       __asm__ volatile (                                        \
+       __issue_syscall (name)                                    \
+       : "=r" (__res)                                            \
+       : "r" (__num)                                             \
+       , "r" (__arg1)                                            \
+       : __SYSCALL_CLOBBERS);                                    \
+        __res;                                                   \
+  })
+
+# define internal_syscall2(name, err, arg1, arg2)                \
+  ({                                                             \
+       register long __res  asm ("$r0");                         \
+       register long __num asm ("$r15") = (long) (name);   	 \
+       register long __arg1 asm ("$r0") = (long) (arg1);         \
+       register long __arg2 asm ("$r1") = (long) (arg2);         \
+       __asm__ volatile (                                        \
+       __issue_syscall (name)                                    \
+       : "=r" (__res)                                            \
+       : "r" (__num)                                             \
+       , "r" (__arg1)                                            \
+       , "r" (__arg2)                                            \
+       : __SYSCALL_CLOBBERS);                                    \
+        __res;                                                   \
+  })
+
+# define internal_syscall3(name, err, arg1, arg2, arg3)          \
+  ({                                                             \
+       register long __res  asm ("$r0");                         \
+       register long __num asm ("$r15") = (long) (name);   	 \
+       register long __arg1 asm ("$r0") = (long) (arg1);         \
+       register long __arg2 asm ("$r1") = (long) (arg2);         \
+       register long __arg3 asm ("$r2") = (long) (arg3);         \
+       __asm__ volatile (                                        \
+       __issue_syscall (name)                                    \
+       : "=r" (__res)                                            \
+       : "r" (__num)                                             \
+       , "r" (__arg1)                                            \
+       , "r" (__arg2)                                            \
+       , "r" (__arg3)                                            \
+       : __SYSCALL_CLOBBERS);                                    \
+        __res;                                                   \
+  })
+
+# define internal_syscall4(name, err, arg1, arg2, arg3, arg4)    \
+  ({                                                             \
+       register long __res  asm ("$r0");                         \
+       register long __num asm ("$r15") = (long) (name);   	 \
+       register long __arg1 asm ("$r0") = (long) (arg1);         \
+       register long __arg2 asm ("$r1") = (long) (arg2);         \
+       register long __arg3 asm ("$r2") = (long) (arg3);         \
+       register long __arg4 asm ("$r3") = (long) (arg4);         \
+       __asm__ volatile (                                        \
+       __issue_syscall (name)                                    \
+       : "=r" (__res)                                            \
+       : "r" (__num)                                             \
+       , "r" (__arg1)                                            \
+       , "r" (__arg2)                                            \
+       , "r" (__arg3)                                            \
+       , "r" (__arg4)                                            \
+       : __SYSCALL_CLOBBERS);                                    \
+        __res;                                                   \
+  })
+
+# define internal_syscall5(name, err, arg1, arg2, arg3, arg4, arg5) \
+  ({                                                             \
+       register long __res  asm ("$r0");                         \
+       register long __num asm ("$r15") = (long) (name);   	 \
+       register long __arg1 asm ("$r0") = (long) (arg1);         \
+       register long __arg2 asm ("$r1") = (long) (arg2);         \
+       register long __arg3 asm ("$r2") = (long) (arg3);         \
+       register long __arg4 asm ("$r3") = (long) (arg4);         \
+       register long __arg5 asm ("$r4") = (long) (arg5);         \
+       __asm__ volatile (                                        \
+       __issue_syscall (name)                                    \
+       : "=r" (__res)                                            \
+       : "r" (__num)                                             \
+       , "r" (__arg1)                                            \
+       , "r" (__arg2)                                            \
+       , "r" (__arg3)                                            \
+       , "r" (__arg4)                                            \
+       , "r" (__arg5)                                            \
+       : __SYSCALL_CLOBBERS);                                    \
+        __res;                                                   \
+  })
+
+# define internal_syscall6(name, err, arg1, arg2, arg3, arg4, arg5, arg6) \
+  ({                                                             \
+       register long __res  asm ("$r0");                         \
+       register long __num asm ("$r15") = (long) (name);   	 \
+       register long __arg1 asm ("$r0") = (long) (arg1);         \
+       register long __arg2 asm ("$r1") = (long) (arg2);         \
+       register long __arg3 asm ("$r2") = (long) (arg3);         \
+       register long __arg4 asm ("$r3") = (long) (arg4);         \
+       register long __arg5 asm ("$r4") = (long) (arg5);         \
+       register long __arg6 asm ("$r5") = (long) (arg6);         \
+       __asm__ volatile (                                        \
+       __issue_syscall (name)                                    \
+       : "=r" (__res)                                            \
+       : "r" (__num)                                             \
+       , "r" (__arg1)                                            \
+       , "r" (__arg2)                                            \
+       , "r" (__arg3)                                            \
+       , "r" (__arg4)                                            \
+       , "r" (__arg5)                                            \
+       , "r" (__arg6)                                            \
+       : __SYSCALL_CLOBBERS);                                    \
+        __res;                                                   \
+  })
+
+#define __SYSCALL_CLOBBERS "memory"
+
+#endif /* !__ASSEMBLER__  */
+
+#define PTR_MANGLE(var) (void) (var)
+#define PTR_DEMANGLE(var) (void) (var)
+
+#endif /* linux/nds32/sysdep.h  */