[v2,10/15] RISC-V: Linux Syscall Interface

Message ID 20171220072022.26909-11-palmer@dabbelt.com
State New, archived
Headers

Commit Message

Palmer Dabbelt Dec. 20, 2017, 7:20 a.m. UTC
  Contains the Linux system call interface, as well as the definitions of
a handful of system calls.
---
 sysdeps/riscv/nptl/nptl-sysdep.S                |   2 +
 sysdeps/unix/sysv/linux/riscv/arch-fork.h       |   1 +
 sysdeps/unix/sysv/linux/riscv/clone.S           |  85 +++++++
 sysdeps/unix/sysv/linux/riscv/getmsg.c          |   1 +
 sysdeps/unix/sysv/linux/riscv/kernel-features.h |  23 ++
 sysdeps/unix/sysv/linux/riscv/profil-counter.h  |   2 +
 sysdeps/unix/sysv/linux/riscv/pt-vfork.S        |   1 +
 sysdeps/unix/sysv/linux/riscv/putmsg.c          |   1 +
 sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c    |   1 +
 sysdeps/unix/sysv/linux/riscv/rv32/readahead.c  |   1 +
 sysdeps/unix/sysv/linux/riscv/syscall.c         |  38 +++
 sysdeps/unix/sysv/linux/riscv/sysdep.S          |  51 ++++
 sysdeps/unix/sysv/linux/riscv/sysdep.h          | 316 ++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/riscv/vfork.S           |  44 ++++
 14 files changed, 567 insertions(+)
 create mode 100644 sysdeps/riscv/nptl/nptl-sysdep.S
 create mode 100644 sysdeps/unix/sysv/linux/riscv/arch-fork.h
 create mode 100644 sysdeps/unix/sysv/linux/riscv/clone.S
 create mode 100644 sysdeps/unix/sysv/linux/riscv/getmsg.c
 create mode 100644 sysdeps/unix/sysv/linux/riscv/kernel-features.h
 create mode 100644 sysdeps/unix/sysv/linux/riscv/profil-counter.h
 create mode 100644 sysdeps/unix/sysv/linux/riscv/pt-vfork.S
 create mode 100644 sysdeps/unix/sysv/linux/riscv/putmsg.c
 create mode 100644 sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c
 create mode 100644 sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
 create mode 100644 sysdeps/unix/sysv/linux/riscv/syscall.c
 create mode 100644 sysdeps/unix/sysv/linux/riscv/sysdep.S
 create mode 100644 sysdeps/unix/sysv/linux/riscv/sysdep.h
 create mode 100644 sysdeps/unix/sysv/linux/riscv/vfork.S
  

Comments

Adhemerval Zanella Dec. 20, 2017, 4:57 p.m. UTC | #1
On 20/12/2017 05:20, Palmer Dabbelt wrote:
> Contains the Linux system call interface, as well as the definitions of
> a handful of system calls.
> ---
>  sysdeps/riscv/nptl/nptl-sysdep.S                |   2 +
>  sysdeps/unix/sysv/linux/riscv/arch-fork.h       |   1 +
>  sysdeps/unix/sysv/linux/riscv/clone.S           |  85 +++++++
>  sysdeps/unix/sysv/linux/riscv/getmsg.c          |   1 +
>  sysdeps/unix/sysv/linux/riscv/kernel-features.h |  23 ++
>  sysdeps/unix/sysv/linux/riscv/profil-counter.h  |   2 +
>  sysdeps/unix/sysv/linux/riscv/pt-vfork.S        |   1 +
>  sysdeps/unix/sysv/linux/riscv/putmsg.c          |   1 +
>  sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c    |   1 +
>  sysdeps/unix/sysv/linux/riscv/rv32/readahead.c  |   1 +
>  sysdeps/unix/sysv/linux/riscv/syscall.c         |  38 +++
>  sysdeps/unix/sysv/linux/riscv/sysdep.S          |  51 ++++
>  sysdeps/unix/sysv/linux/riscv/sysdep.h          | 316 ++++++++++++++++++++++++
>  sysdeps/unix/sysv/linux/riscv/vfork.S           |  44 ++++
>  14 files changed, 567 insertions(+)
>  create mode 100644 sysdeps/riscv/nptl/nptl-sysdep.S
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/arch-fork.h
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/clone.S
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/getmsg.c
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/kernel-features.h
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/profil-counter.h
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/pt-vfork.S
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/putmsg.c
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/syscall.c
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/sysdep.S
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/sysdep.h
>  create mode 100644 sysdeps/unix/sysv/linux/riscv/vfork.S
> 
> diff --git a/sysdeps/riscv/nptl/nptl-sysdep.S b/sysdeps/riscv/nptl/nptl-sysdep.S
> new file mode 100644
> index 000000000000..3f5c2a364afd
> --- /dev/null
> +++ b/sysdeps/riscv/nptl/nptl-sysdep.S
> @@ -0,0 +1,2 @@
> +/* Pull in __syscall_error.  */
> +#include <sysdep.S>
> diff --git a/sysdeps/unix/sysv/linux/riscv/arch-fork.h b/sysdeps/unix/sysv/linux/riscv/arch-fork.h
> new file mode 100644
> index 000000000000..5f945378eec0
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/riscv/arch-fork.h
> @@ -0,0 +1 @@
> +#include <sysdeps/unix/sysv/linux/i386/arch-fork.h>

I would prefer for new ports if we refrain to continue doing this cross arch
code references, it ties implementations that should be independent of each
other and make future cleanups more complex and required to adequate multiple
architecture at once.
  
Joseph Myers Dec. 20, 2017, 5:24 p.m. UTC | #2
On Tue, 19 Dec 2017, Palmer Dabbelt wrote:

> diff --git a/sysdeps/unix/sysv/linux/riscv/getmsg.c b/sysdeps/unix/sysv/linux/riscv/getmsg.c
> new file mode 100644
> index 000000000000..3a1fa0852504
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/riscv/getmsg.c
> @@ -0,0 +1 @@
> +#include <sysdeps/unix/sysv/linux/i386/getmsg.c>

Really?  I don't see getpmsg in the generic or RISC-V syscall ABI.

> diff --git a/sysdeps/unix/sysv/linux/riscv/kernel-features.h b/sysdeps/unix/sysv/linux/riscv/kernel-features.h

My comments from 
<https://sourceware.org/ml/libc-alpha/2017-06/msg00661.html> still apply: 
you shouldn't need this file.

> diff --git a/sysdeps/unix/sysv/linux/riscv/putmsg.c b/sysdeps/unix/sysv/linux/riscv/putmsg.c
> new file mode 100644
> index 000000000000..ebc1680ca7d1
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/riscv/putmsg.c
> @@ -0,0 +1 @@
> +#include <sysdeps/unix/sysv/linux/i386/putmsg.c>

Same comment as for getmsg.

> diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c b/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
> new file mode 100644
> index 000000000000..80170c3e8a4d
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
> @@ -0,0 +1 @@
> +#include <sysdeps/unix/sysv/linux/arm/readahead.c>

I commented on this before 
<https://sourceware.org/ml/libc-alpha/2017-06/msg00661.html>.  Are you 
sure about it?  The ARM file is dealing with a peculiarity of the syscall 
interface in the case where (a) it follows the C function interface and 
(b) a 32-bit function argument followed by a 64-bit function argument 
requires a one-register gap between them.

Now, RISC-V doesn't seem to do anything special for this syscall in the 
kernel, so I presume it does follow the C function interface.  But 
<https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md> 
says that aligned register pairs are only used for variadic arguments, and 
readahead is not a variadic function.  So I'd expect there not to be a gap 
in the arguments to this syscall, and so use of the ARM function to be 
wrong.  (As the syscall has no errors and no testable semantic effect, as 
long as the fd argument is valid, getting this wrong would not result in 
any test failures.)

> +#ifdef __ASSEMBLER__
> +
> +#include <sys/asm.h>
> +
> +#define ENTRY(name) LEAF(name)

Missing preprocessor indentation here and subsequently (inconsistently) in 
this file.

> +#endif /* linux/mips/sysdep.h */

This comment is clearly wrong here.
  
Palmer Dabbelt Dec. 24, 2017, 12:24 a.m. UTC | #3
On Wed, 20 Dec 2017 08:57:48 PST (-0800), adhemerval.zanella@linaro.org wrote:
>
>
> On 20/12/2017 05:20, Palmer Dabbelt wrote:
>> Contains the Linux system call interface, as well as the definitions of
>> a handful of system calls.
>> ---
>>  sysdeps/riscv/nptl/nptl-sysdep.S                |   2 +
>>  sysdeps/unix/sysv/linux/riscv/arch-fork.h       |   1 +
>>  sysdeps/unix/sysv/linux/riscv/clone.S           |  85 +++++++
>>  sysdeps/unix/sysv/linux/riscv/getmsg.c          |   1 +
>>  sysdeps/unix/sysv/linux/riscv/kernel-features.h |  23 ++
>>  sysdeps/unix/sysv/linux/riscv/profil-counter.h  |   2 +
>>  sysdeps/unix/sysv/linux/riscv/pt-vfork.S        |   1 +
>>  sysdeps/unix/sysv/linux/riscv/putmsg.c          |   1 +
>>  sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c    |   1 +
>>  sysdeps/unix/sysv/linux/riscv/rv32/readahead.c  |   1 +
>>  sysdeps/unix/sysv/linux/riscv/syscall.c         |  38 +++
>>  sysdeps/unix/sysv/linux/riscv/sysdep.S          |  51 ++++
>>  sysdeps/unix/sysv/linux/riscv/sysdep.h          | 316 ++++++++++++++++++++++++
>>  sysdeps/unix/sysv/linux/riscv/vfork.S           |  44 ++++
>>  14 files changed, 567 insertions(+)
>>  create mode 100644 sysdeps/riscv/nptl/nptl-sysdep.S
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/arch-fork.h
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/clone.S
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/getmsg.c
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/kernel-features.h
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/profil-counter.h
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/pt-vfork.S
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/putmsg.c
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/syscall.c
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/sysdep.S
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/sysdep.h
>>  create mode 100644 sysdeps/unix/sysv/linux/riscv/vfork.S
>>
>> diff --git a/sysdeps/riscv/nptl/nptl-sysdep.S b/sysdeps/riscv/nptl/nptl-sysdep.S
>> new file mode 100644
>> index 000000000000..3f5c2a364afd
>> --- /dev/null
>> +++ b/sysdeps/riscv/nptl/nptl-sysdep.S
>> @@ -0,0 +1,2 @@
>> +/* Pull in __syscall_error.  */
>> +#include <sysdep.S>
>> diff --git a/sysdeps/unix/sysv/linux/riscv/arch-fork.h b/sysdeps/unix/sysv/linux/riscv/arch-fork.h
>> new file mode 100644
>> index 000000000000..5f945378eec0
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/riscv/arch-fork.h
>> @@ -0,0 +1 @@
>> +#include <sysdeps/unix/sysv/linux/i386/arch-fork.h>
>
> I would prefer for new ports if we refrain to continue doing this cross arch
> code references, it ties implementations that should be independent of each
> other and make future cleanups more complex and required to adequate multiple
> architecture at once.

OK, no problem.  I've gone and replaced the #include with the contents of the 
included file for every instance where we were doing this.  I'll include this
as part of a v3 patch set.

Thanks for reviewing our port!
  
Palmer Dabbelt Dec. 25, 2017, 7:47 p.m. UTC | #4
On Wed, 20 Dec 2017 09:24:21 PST (-0800), joseph@codesourcery.com wrote:
> On Tue, 19 Dec 2017, Palmer Dabbelt wrote:
>
>> diff --git a/sysdeps/unix/sysv/linux/riscv/getmsg.c b/sysdeps/unix/sysv/linux/riscv/getmsg.c
>> new file mode 100644
>> index 000000000000..3a1fa0852504
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/riscv/getmsg.c
>> @@ -0,0 +1 @@
>> +#include <sysdeps/unix/sysv/linux/i386/getmsg.c>
>
> Really?  I don't see getpmsg in the generic or RISC-V syscall ABI.
>
>> diff --git a/sysdeps/unix/sysv/linux/riscv/kernel-features.h b/sysdeps/unix/sysv/linux/riscv/kernel-features.h
>
> My comments from
> <https://sourceware.org/ml/libc-alpha/2017-06/msg00661.html> still apply:
> you shouldn't need this file.
>
>> diff --git a/sysdeps/unix/sysv/linux/riscv/putmsg.c b/sysdeps/unix/sysv/linux/riscv/putmsg.c
>> new file mode 100644
>> index 000000000000..ebc1680ca7d1
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/riscv/putmsg.c
>> @@ -0,0 +1 @@
>> +#include <sysdeps/unix/sysv/linux/i386/putmsg.c>
>
> Same comment as for getmsg.

Thanks, we must have gotten our signals crossed on your original messages.  
You're right here, I'll remove the files for the v3.

>> diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c b/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
>> new file mode 100644
>> index 000000000000..80170c3e8a4d
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
>> @@ -0,0 +1 @@
>> +#include <sysdeps/unix/sysv/linux/arm/readahead.c>
>
> I commented on this before
> <https://sourceware.org/ml/libc-alpha/2017-06/msg00661.html>.  Are you
> sure about it?  The ARM file is dealing with a peculiarity of the syscall
> interface in the case where (a) it follows the C function interface and
> (b) a 32-bit function argument followed by a 64-bit function argument
> requires a one-register gap between them.
>
> Now, RISC-V doesn't seem to do anything special for this syscall in the
> kernel, so I presume it does follow the C function interface.  But
> <https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md>
> says that aligned register pairs are only used for variadic arguments, and
> readahead is not a variadic function.  So I'd expect there not to be a gap
> in the arguments to this syscall, and so use of the ARM function to be
> wrong.  (As the syscall has no errors and no testable semantic effect, as
> long as the fd argument is valid, getting this wrong would not result in
> any test failures.)

Sorry, again, that we missed that.  You're correct here, we'll remove it for 
the v3.

>> +#ifdef __ASSEMBLER__
>> +
>> +#include <sys/asm.h>
>> +
>> +#define ENTRY(name) LEAF(name)
>
> Missing preprocessor indentation here and subsequently (inconsistently) in
> this file.
>
>> +#endif /* linux/mips/sysdep.h */
>
> This comment is clearly wrong here.

These should all be fixed.  Thanks!
  
Joseph Myers Jan. 1, 2018, 12:56 a.m. UTC | #5
On Sat, 23 Dec 2017, Palmer Dabbelt wrote:

> > > diff --git a/sysdeps/unix/sysv/linux/riscv/arch-fork.h
> > > b/sysdeps/unix/sysv/linux/riscv/arch-fork.h
> > > new file mode 100644
> > > index 000000000000..5f945378eec0
> > > --- /dev/null
> > > +++ b/sysdeps/unix/sysv/linux/riscv/arch-fork.h
> > > @@ -0,0 +1 @@
> > > +#include <sysdeps/unix/sysv/linux/i386/arch-fork.h>
> > 
> > I would prefer for new ports if we refrain to continue doing this cross arch
> > code references, it ties implementations that should be independent of each
> > other and make future cleanups more complex and required to adequate
> > multiple
> > architecture at once.
> 
> OK, no problem.  I've gone and replaced the #include with the contents of the
> included file for every instance where we were doing this.  I'll include this
> as part of a v3 patch set.

Copying the included file isn't particularly good either.  Rather, each 
such case, whether a copy from another architecture or a #include from 
another architecture, indicates a case where refactoring is needed to 
avoid such duplication - if the code can be generic for all new ports it 
should be in a generic location, while if it's generic for ports with a 
particular property things should be factored so a port only needs to 
declare that it has that property.  (Of course such refactoring is risky 
so not typically appropriate during a release freeze.)

Often, the files for i386 are actually generic for *old* ports and so if 
you're copying or including such a file (or one from another old 
architecture) you need to be particularly careful that it actually 
represents the desired way to do things now, rather than compatibility 
with old ABIs or old versions of the syscall interface.
  
Christoph Hellwig Jan. 3, 2018, 1:43 p.m. UTC | #6
On Mon, Jan 01, 2018 at 12:56:14AM +0000, Joseph Myers wrote:
> such case, whether a copy from another architecture or a #include from 
> another architecture, indicates a case where refactoring is needed to 
> avoid such duplication - if the code can be generic for all new ports it 
> should be in a generic location, while if it's generic for ports with a 
> particular property things should be factored so a port only needs to 
> declare that it has that property.  (Of course such refactoring is risky 
> so not typically appropriate during a release freeze.)
> 
> Often, the files for i386 are actually generic for *old* ports and so if 
> you're copying or including such a file (or one from another old 
> architecture) you need to be particularly careful that it actually 
> represents the desired way to do things now, rather than compatibility 
> with old ABIs or old versions of the syscall interface.

clone is a hodegepodge, but the clone(2) manpage documents it well.
There are two major camps, and risv implements on of those.  And then
there are various oddballs.

So for now it might make sense to just duplicate the i386 file for
riscv, or follow the example of various forks to include it.  In the
long run having a generic implementation for the two common versions
might be useful.
  
Adhemerval Zanella Jan. 3, 2018, 3:56 p.m. UTC | #7
On 03/01/2018 11:43, Christoph Hellwig wrote:
> On Mon, Jan 01, 2018 at 12:56:14AM +0000, Joseph Myers wrote:
>> such case, whether a copy from another architecture or a #include from 
>> another architecture, indicates a case where refactoring is needed to 
>> avoid such duplication - if the code can be generic for all new ports it 
>> should be in a generic location, while if it's generic for ports with a 
>> particular property things should be factored so a port only needs to 
>> declare that it has that property.  (Of course such refactoring is risky 
>> so not typically appropriate during a release freeze.)
>>
>> Often, the files for i386 are actually generic for *old* ports and so if 
>> you're copying or including such a file (or one from another old 
>> architecture) you need to be particularly careful that it actually 
>> represents the desired way to do things now, rather than compatibility 
>> with old ABIs or old versions of the syscall interface.
> 
> clone is a hodegepodge, but the clone(2) manpage documents it well.
> There are two major camps, and risv implements on of those.  And then
> there are various oddballs.
> 
> So for now it might make sense to just duplicate the i386 file for
> riscv, or follow the example of various forks to include it.  In the
> long run having a generic implementation for the two common versions
> might be useful.
> 

Sometime ago I tried to check if it was worth to simplify the arch-fork.h
by defining the supported kernel variations and adding a arch-specific
define (maybe on kernel-features.h).  I did not follow up, but I think it
might be feasible: afaik Linux defines 4 variants:

  - CONFIG_CLONE_BACKWARDS
  - CONFIG_CLONE_BACKWARDS2
  - CONFIG_CLONE_BACKWARDS3
  - And the generic one which I assume it is meant for newer ports.

So I think we expand the arch-fork.h generic to issue the clone based on
arch-specific flags with a generic one as default.  It will make unnecessary
for newer ports to add a arch-fork.h implementation.
  
Palmer Dabbelt Jan. 9, 2018, 1:30 a.m. UTC | #8
On Wed, 03 Jan 2018 07:56:32 PST (-0800), adhemerval.zanella@linaro.org wrote:
>
>
> On 03/01/2018 11:43, Christoph Hellwig wrote:
>> On Mon, Jan 01, 2018 at 12:56:14AM +0000, Joseph Myers wrote:
>>> such case, whether a copy from another architecture or a #include from
>>> another architecture, indicates a case where refactoring is needed to
>>> avoid such duplication - if the code can be generic for all new ports it
>>> should be in a generic location, while if it's generic for ports with a
>>> particular property things should be factored so a port only needs to
>>> declare that it has that property.  (Of course such refactoring is risky
>>> so not typically appropriate during a release freeze.)
>>>
>>> Often, the files for i386 are actually generic for *old* ports and so if
>>> you're copying or including such a file (or one from another old
>>> architecture) you need to be particularly careful that it actually
>>> represents the desired way to do things now, rather than compatibility
>>> with old ABIs or old versions of the syscall interface.
>>
>> clone is a hodegepodge, but the clone(2) manpage documents it well.
>> There are two major camps, and risv implements on of those.  And then
>> there are various oddballs.
>>
>> So for now it might make sense to just duplicate the i386 file for
>> riscv, or follow the example of various forks to include it.  In the
>> long run having a generic implementation for the two common versions
>> might be useful.
>>
>
> Sometime ago I tried to check if it was worth to simplify the arch-fork.h
> by defining the supported kernel variations and adding a arch-specific
> define (maybe on kernel-features.h).  I did not follow up, but I think it
> might be feasible: afaik Linux defines 4 variants:
>
>   - CONFIG_CLONE_BACKWARDS
>   - CONFIG_CLONE_BACKWARDS2
>   - CONFIG_CLONE_BACKWARDS3
>   - And the generic one which I assume it is meant for newer ports.
>
> So I think we expand the arch-fork.h generic to issue the clone based on
> arch-specific flags with a generic one as default.  It will make unnecessary
> for newer ports to add a arch-fork.h implementation.

I asked on the Linux mailing list what the sane thing to do is here.  Thanks 
for bringing this up, but it might be too late to change anything on our end -- 
there's probably only 1 more Linux RC left, so unless there's a strong reason 
to prefer one argument ordering I think I'm just going to leave it alone.

Sorry we didn't get around to this sooner!
  
Adhemerval Zanella Jan. 9, 2018, 11:15 a.m. UTC | #9
On 08/01/2018 23:30, Palmer Dabbelt wrote:
> On Wed, 03 Jan 2018 07:56:32 PST (-0800), adhemerval.zanella@linaro.org wrote:
>>
>>
>> On 03/01/2018 11:43, Christoph Hellwig wrote:
>>> On Mon, Jan 01, 2018 at 12:56:14AM +0000, Joseph Myers wrote:
>>>> such case, whether a copy from another architecture or a #include from
>>>> another architecture, indicates a case where refactoring is needed to
>>>> avoid such duplication - if the code can be generic for all new ports it
>>>> should be in a generic location, while if it's generic for ports with a
>>>> particular property things should be factored so a port only needs to
>>>> declare that it has that property.  (Of course such refactoring is risky
>>>> so not typically appropriate during a release freeze.)
>>>>
>>>> Often, the files for i386 are actually generic for *old* ports and so if
>>>> you're copying or including such a file (or one from another old
>>>> architecture) you need to be particularly careful that it actually
>>>> represents the desired way to do things now, rather than compatibility
>>>> with old ABIs or old versions of the syscall interface.
>>>
>>> clone is a hodegepodge, but the clone(2) manpage documents it well.
>>> There are two major camps, and risv implements on of those.  And then
>>> there are various oddballs.
>>>
>>> So for now it might make sense to just duplicate the i386 file for
>>> riscv, or follow the example of various forks to include it.  In the
>>> long run having a generic implementation for the two common versions
>>> might be useful.
>>>
>>
>> Sometime ago I tried to check if it was worth to simplify the arch-fork.h
>> by defining the supported kernel variations and adding a arch-specific
>> define (maybe on kernel-features.h).  I did not follow up, but I think it
>> might be feasible: afaik Linux defines 4 variants:
>>
>>   - CONFIG_CLONE_BACKWARDS
>>   - CONFIG_CLONE_BACKWARDS2
>>   - CONFIG_CLONE_BACKWARDS3
>>   - And the generic one which I assume it is meant for newer ports.
>>
>> So I think we expand the arch-fork.h generic to issue the clone based on
>> arch-specific flags with a generic one as default.  It will make unnecessary
>> for newer ports to add a arch-fork.h implementation.
> 
> I asked on the Linux mailing list what the sane thing to do is here.  Thanks for bringing this up, but it might be too late to change anything on our end -- there's probably only 1 more Linux RC left, so unless there's a strong reason to prefer one argument ordering I think I'm just going to leave it alone.
> 
> Sorry we didn't get around to this sooner!

Indeed I also think it is late for this change and my questioning is more for
curiosity. From glibc end, my recent refactor patches are mainly to make glibc
follow what Linux generic api for newer ports intended to do, so new architecture
inclusion would require as less code as possible.

For this refactor in specific riscv will need to define an extra define.
  

Patch

diff --git a/sysdeps/riscv/nptl/nptl-sysdep.S b/sysdeps/riscv/nptl/nptl-sysdep.S
new file mode 100644
index 000000000000..3f5c2a364afd
--- /dev/null
+++ b/sysdeps/riscv/nptl/nptl-sysdep.S
@@ -0,0 +1,2 @@ 
+/* Pull in __syscall_error.  */
+#include <sysdep.S>
diff --git a/sysdeps/unix/sysv/linux/riscv/arch-fork.h b/sysdeps/unix/sysv/linux/riscv/arch-fork.h
new file mode 100644
index 000000000000..5f945378eec0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/arch-fork.h
@@ -0,0 +1 @@ 
+#include <sysdeps/unix/sysv/linux/i386/arch-fork.h>
diff --git a/sysdeps/unix/sysv/linux/riscv/clone.S b/sysdeps/unix/sysv/linux/riscv/clone.S
new file mode 100644
index 000000000000..4bfdc90702aa
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/clone.S
@@ -0,0 +1,85 @@ 
+/* Wrapper around clone system call.  RISC-V version.
+   Copyright (C) 1996-2017 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 <sys/asm.h>
+#include <sysdep.h>
+#define _ERRNO_H	1
+#include <bits/errno.h>
+#include <tls.h>
+#include "tcb-offsets.h"
+
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+	     void *parent_tidptr, void *tls, void *child_tidptr) */
+
+	.text
+LEAF(__clone)
+
+	/* Sanity check arguments.  */
+	beqz		a0,L(invalid)	/* No NULL function pointers.  */
+	beqz		a1,L(invalid)	/* No NULL stack pointers.  */
+
+	addi		a1,a1,-16	/* Reserve argument save space.  */
+	REG_S		a0,0(a1)	/* Save function pointer.  */
+	REG_S		a3,SZREG(a1)	/* Save argument pointer.  */
+
+	/* The syscall expects the args to be in different slots.  */
+	mv		a0,a2
+	mv		a2,a4
+	mv		a3,a5
+	mv		a4,a6
+
+	/* Do the system call */
+	li		a7,__NR_clone
+	scall
+
+	bltz		a0,L(error)
+	beqz		a0,L(thread_start)
+
+	/* Successful return from the parent */
+	ret
+
+L(invalid):
+	li		a0, -EINVAL
+	/* Something bad happened -- no child created */
+L(error):
+	j		__syscall_error
+	END(__clone)
+
+/* Load up the arguments to the function.  Put this block of code in
+   its own function so that we can terminate the stack trace with our
+   debug info.  */
+
+ENTRY(__thread_start)
+L(thread_start):
+	/* Restore the arg for user's function.  */
+	REG_L		a1,0(sp)	/* Function pointer.  */
+	REG_L		a0,SZREG(sp)	/* Argument pointer.  */
+
+	/* Call the user's function.  */
+	jalr		a1
+
+	/* Call _exit with the function's return value.  */
+	j		_exit
+
+	END(__thread_start)
+
+libc_hidden_def(__clone)
+weak_alias (__clone, clone)
diff --git a/sysdeps/unix/sysv/linux/riscv/getmsg.c b/sysdeps/unix/sysv/linux/riscv/getmsg.c
new file mode 100644
index 000000000000..3a1fa0852504
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/getmsg.c
@@ -0,0 +1 @@ 
+#include <sysdeps/unix/sysv/linux/i386/getmsg.c>
diff --git a/sysdeps/unix/sysv/linux/riscv/kernel-features.h b/sysdeps/unix/sysv/linux/riscv/kernel-features.h
new file mode 100644
index 000000000000..21f9600eda73
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/kernel-features.h
@@ -0,0 +1,23 @@ 
+/* RISC-V kernel features
+   Copyright (C) 2014-2017 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 __ASSUME_ACCEPT4_SYSCALL	1
+#define __ASSUME_RECVMMSG_SYSCALL	1
+#define __ASSUME_SENDMMSG_SYSCALL	1
+
+#include_next <kernel-features.h>
diff --git a/sysdeps/unix/sysv/linux/riscv/profil-counter.h b/sysdeps/unix/sysv/linux/riscv/profil-counter.h
new file mode 100644
index 000000000000..8a6a0bcf3d59
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/profil-counter.h
@@ -0,0 +1,2 @@ 
+/* We can use the ix86 version.  */
+#include <sysdeps/unix/sysv/linux/i386/profil-counter.h>
diff --git a/sysdeps/unix/sysv/linux/riscv/pt-vfork.S b/sysdeps/unix/sysv/linux/riscv/pt-vfork.S
new file mode 100644
index 000000000000..65cc3823ac87
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/pt-vfork.S
@@ -0,0 +1 @@ 
+#include <sysdeps/unix/sysv/linux/alpha/pt-vfork.S>
diff --git a/sysdeps/unix/sysv/linux/riscv/putmsg.c b/sysdeps/unix/sysv/linux/riscv/putmsg.c
new file mode 100644
index 000000000000..ebc1680ca7d1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/putmsg.c
@@ -0,0 +1 @@ 
+#include <sysdeps/unix/sysv/linux/i386/putmsg.c>
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c b/sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c
new file mode 100644
index 000000000000..a88f5a784a54
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/lockf64.c
@@ -0,0 +1 @@ 
+#include <sysdeps/unix/sysv/linux/i386/lockf64.c>
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c b/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
new file mode 100644
index 000000000000..80170c3e8a4d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/readahead.c
@@ -0,0 +1 @@ 
+#include <sysdeps/unix/sysv/linux/arm/readahead.c>
diff --git a/sysdeps/unix/sysv/linux/riscv/syscall.c b/sysdeps/unix/sysv/linux/riscv/syscall.c
new file mode 100644
index 000000000000..bce62ca06df7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/syscall.c
@@ -0,0 +1,38 @@ 
+/* system call interface.  Linux/RISC-V version.
+   Copyright (C) 2001-2017 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>
+
+long
+syscall (long syscall_number, long arg1, long arg2, long arg3, long arg4,
+	 long arg5, long arg6, long arg7)
+{
+  long ret;
+  INTERNAL_SYSCALL_DECL (err);
+
+  ret = INTERNAL_SYSCALL_NCS (syscall_number, err, 7, arg1, arg2, arg3, arg4,
+			      arg5, arg6, arg7);
+
+  if (INTERNAL_SYSCALL_ERROR_P (ret, err))
+    {
+      extern long __syscall_error (long neg_errno);
+      return __syscall_error (ret);
+    }
+
+  return ret;
+}
diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.S b/sysdeps/unix/sysv/linux/riscv/sysdep.S
new file mode 100644
index 000000000000..90da2daf7655
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/sysdep.S
@@ -0,0 +1,51 @@ 
+/* syscall error handlers
+   Copyright (C) 2011-2017 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>
+
+#if IS_IN (libc)
+# define errno __libc_errno
+#endif
+
+ENTRY (__syscall_error)
+	mv t0, ra
+	/* Fall through to __syscall_set_errno.  */
+END (__syscall_error)
+
+/* Non-standard calling convention: argument in a0, return address in t0,
+   and clobber only t1.  */
+ENTRY (__syscall_set_errno)
+	/* We got here because a0 < 0, but only codes in the range [-4095, -1]
+	  represent errors.  Otherwise, just return the result normally.  */
+	li t1, -4096
+	bleu a0, t1, 1f
+	neg a0, a0
+#if RTLD_PRIVATE_ERRNO
+	sw a0, rtld_errno, t1
+#elif defined(__PIC__)
+	la.tls.ie t1, errno
+	add t1, t1, tp
+	sw a0, 0(t1)
+#else
+	lui t1, %tprel_hi(errno)
+	add t1, t1, tp, %tprel_add(errno)
+	sw a0, %tprel_lo(errno)(t1)
+#endif
+	li a0, -1
+1:	jr t0
+END (__syscall_set_errno)
diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h
new file mode 100644
index 000000000000..56a6053d82a6
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h
@@ -0,0 +1,316 @@ 
+/* Assembly macros for RISC-V.
+   Copyright (C) 2011-2017
+   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_RISCV_SYSDEP_H
+#define _LINUX_RISCV_SYSDEP_H 1
+
+#include <sysdeps/unix/sysv/linux/generic/sysdep.h>
+#include <tls.h>
+
+#ifdef __ASSEMBLER__
+
+#include <sys/asm.h>
+
+#define ENTRY(name) LEAF(name)
+
+#define L(label) .L ## label
+
+/* Performs a system call, handling errors by setting errno.  Linux indicates
+ * errors by setting a0 to a value between -1 and -4095.  */
+#undef PSEUDO
+#define PSEUDO(name, syscall_name, args)			\
+  .text;							\
+  .align 2;							\
+  ENTRY (name);							\
+  li a7, SYS_ify(syscall_name);					\
+  scall;							\
+  li a7, -4096;							\
+  bgtu a0, a7, .Lsyscall_error ## name;
+
+#undef PSEUDO_END
+#define PSEUDO_END(sym) 					\
+  SYSCALL_ERROR_HANDLER(sym)					\
+  ret;								\
+  END(sym)
+
+# if !IS_IN (libc)
+#  if RTLD_PRIVATE_ERRNO
+#   define SYSCALL_ERROR_HANDLER(name)				\
+.Lsyscall_error ## name:					\
+	li t1, -4096;						\
+        sw a0, rtld_errno, t1;					\
+        li a0, -1;
+#  elif defined (__PIC__)
+#   define SYSCALL_ERROR_HANDLER(name)				\
+.Lsyscall_error ## name:					\
+        la.tls.ie t1, errno;					\
+	add t1, t1, tp;						\
+	sw a0, 0(t1);						\
+        li a0, -1;
+#  else
+#   define SYSCALL_ERROR_HANDLER(name)				\
+.Lsyscall_error ## name:					\
+        lui t1, %tprel_hi(errno);				\
+        add t1, t1, tp, %tprel_add(errno);			\
+        sw a0, %tprel_lo(errno)(t1);				\
+        li a0, -1;
+#  endif
+# else
+#  define SYSCALL_ERROR_HANDLER(name)				\
+.Lsyscall_error ## name:					\
+        j       __syscall_error;
+# endif
+
+/* Performs a system call, not setting errno.  */
+#undef PSEUDO_NEORRNO
+#define PSEUDO_NOERRNO(name, syscall_name, args)	\
+  .align 2;						\
+  ENTRY(name);						\
+  li a7, SYS_ify(syscall_name);				\
+  scall;
+
+#undef PSEUDO_END_NOERRNO
+#define PSEUDO_END_NOERRNO(name)			\
+  END (name)
+
+#undef ret_NOERRNO
+#define ret_NOERRNO ret
+
+/* 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 a0, a0;
+
+#undef PSEUDO_END_ERRVAL
+#define PSEUDO_END_ERRVAL(name)				\
+  END (name)
+
+#undef ret_ERRVAL
+#define ret_ERRVAL ret
+
+#endif /* __ASSEMBLER__ */
+
+/* In order to get __set_errno() definition in INLINE_SYSCALL.  */
+#ifndef __ASSEMBLER__
+#include <errno.h>
+#endif
+
+#include <sysdeps/unix/sysdep.h>
+
+#undef SYS_ify
+#define SYS_ify(syscall_name)	__NR_##syscall_name
+
+#ifndef __ASSEMBLER__
+
+/* List of system calls which are supported as vsyscalls.  */
+#define HAVE_CLOCK_GETRES_VSYSCALL	1
+#define HAVE_CLOCK_GETTIME_VSYSCALL	1
+#define HAVE_GETTIMEOFDAY_VSYSCALL	1
+#define HAVE_GETCPU_VSYSCALL		1
+
+/* 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 __sys_result = INTERNAL_SYSCALL (name, err, nr, args);	\
+     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P(__sys_result, ), 0)) \
+       {								\
+         __set_errno (INTERNAL_SYSCALL_ERRNO (__sys_result, ));		\
+	 __sys_result = (unsigned long) -1;				\
+       }								\
+     __sys_result; })
+
+#define INTERNAL_SYSCALL_DECL(err) do { } while (0)
+
+#define INTERNAL_SYSCALL_ERROR_P(val, err)   ((unsigned long) (val) > -4096UL)
+
+#define INTERNAL_SYSCALL_ERRNO(val, err)     (-val)
+
+#define INTERNAL_SYSCALL(name, err, nr, args...) \
+	internal_syscall##nr (SYS_ify (name), err, args)
+
+#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
+	internal_syscall##nr (number, err, args)
+
+#define internal_syscall0(number, err, dummy...)			\
+({ 									\
+	long _sys_result;						\
+									\
+	{								\
+	register long __a7 asm("a7") = number;				\
+	register long __a0 asm("a0");					\
+	__asm__ volatile ( 						\
+	"scall\n\t" 							\
+	: "=r" (__a0)							\
+	: "r" (__a7)							\
+	: __SYSCALL_CLOBBERS); 						\
+	_sys_result = __a0;						\
+	}								\
+	_sys_result;							\
+})
+
+#define internal_syscall1(number, err, arg0)				\
+({ 									\
+	long _sys_result;						\
+									\
+	{								\
+	register long __a7 asm("a7") = number;				\
+	register long __a0 asm("a0") = (long) (arg0);			\
+	__asm__ volatile ( 						\
+	"scall\n\t" 							\
+	: "+r" (__a0)							\
+	: "r" (__a7)							\
+	: __SYSCALL_CLOBBERS); 						\
+	_sys_result = __a0;						\
+	}								\
+	_sys_result;							\
+})
+
+#define internal_syscall2(number, err, arg0, arg1)	    		\
+({ 									\
+	long _sys_result;						\
+									\
+	{								\
+	register long __a7 asm("a7") = number;				\
+	register long __a0 asm("a0") = (long) (arg0);			\
+	register long __a1 asm("a1") = (long) (arg1);			\
+	__asm__ volatile ( 						\
+	"scall\n\t" 							\
+	: "+r" (__a0)							\
+	: "r" (__a7), "r"(__a1)						\
+	: __SYSCALL_CLOBBERS); 						\
+	_sys_result = __a0;						\
+	}								\
+	_sys_result;							\
+})
+
+#define internal_syscall3(number, err, arg0, arg1, arg2)      		\
+({ 									\
+	long _sys_result;						\
+									\
+	{								\
+	register long __a7 asm("a7") = number;				\
+	register long __a0 asm("a0") = (long) (arg0);			\
+	register long __a1 asm("a1") = (long) (arg1);			\
+	register long __a2 asm("a2") = (long) (arg2);			\
+	__asm__ volatile ( 						\
+	"scall\n\t" 							\
+	: "+r" (__a0)							\
+	: "r" (__a7), "r"(__a1), "r"(__a2)				\
+	: __SYSCALL_CLOBBERS); 						\
+	_sys_result = __a0;						\
+	}								\
+	_sys_result;							\
+})
+
+#define internal_syscall4(number, err, arg0, arg1, arg2, arg3)	  \
+({ 									\
+	long _sys_result;						\
+									\
+	{								\
+	register long __a7 asm("a7") = number;				\
+	register long __a0 asm("a0") = (long) (arg0);			\
+	register long __a1 asm("a1") = (long) (arg1);			\
+	register long __a2 asm("a2") = (long) (arg2);			\
+	register long __a3 asm("a3") = (long) (arg3);			\
+	__asm__ volatile ( 						\
+	"scall\n\t" 							\
+	: "+r" (__a0)							\
+	: "r" (__a7), "r"(__a1), "r"(__a2), "r"(__a3)			\
+	: __SYSCALL_CLOBBERS); 						\
+	_sys_result = __a0;						\
+	}								\
+	_sys_result;							\
+})
+
+#define internal_syscall5(number, err, arg0, arg1, arg2, arg3, arg4)    \
+({ 									\
+	long _sys_result;						\
+									\
+	{								\
+	register long __a7 asm("a7") = number;				\
+	register long __a0 asm("a0") = (long) (arg0);			\
+	register long __a1 asm("a1") = (long) (arg1);			\
+	register long __a2 asm("a2") = (long) (arg2);			\
+	register long __a3 asm("a3") = (long) (arg3);			\
+	register long __a4 asm("a4") = (long) (arg4);			\
+	__asm__ volatile ( 						\
+	"scall\n\t" 							\
+	: "+r" (__a0)							\
+	: "r" (__a7), "r"(__a1), "r"(__a2), "r"(__a3), "r"(__a4)	\
+	: __SYSCALL_CLOBBERS); 						\
+	_sys_result = __a0;						\
+	}								\
+	_sys_result;							\
+})
+
+#define internal_syscall6(number, err, arg0, arg1, arg2, arg3, arg4, arg5) \
+({ 									\
+	long _sys_result;						\
+									\
+	{								\
+	register long __a7 asm("a7") = number;				\
+	register long __a0 asm("a0") = (long) (arg0);			\
+	register long __a1 asm("a1") = (long) (arg1);			\
+	register long __a2 asm("a2") = (long) (arg2);			\
+	register long __a3 asm("a3") = (long) (arg3);			\
+	register long __a4 asm("a4") = (long) (arg4);			\
+	register long __a5 asm("a5") = (long) (arg5);			\
+	__asm__ volatile ( 						\
+	"scall\n\t" 							\
+	: "+r" (__a0)							\
+	: "r" (__a7), "r"(__a1), "r"(__a2), "r"(__a3), "r"(__a4), "r"(__a5)	\
+	: __SYSCALL_CLOBBERS); 						\
+	_sys_result = __a0;						\
+	}								\
+	_sys_result;							\
+})
+
+#define internal_syscall7(number, err, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \
+({ 									\
+	long _sys_result;						\
+									\
+	{								\
+	register long __a7 asm("a7") = number;				\
+	register long __a0 asm("a0") = (long) (arg0);			\
+	register long __a1 asm("a1") = (long) (arg1);			\
+	register long __a2 asm("a2") = (long) (arg2);			\
+	register long __a3 asm("a3") = (long) (arg3);			\
+	register long __a4 asm("a4") = (long) (arg4);			\
+	register long __a5 asm("a5") = (long) (arg5);			\
+	register long __a6 asm("a6") = (long) (arg6);			\
+	__asm__ volatile ( 						\
+	"scall\n\t" 							\
+	: "+r" (__a0)							\
+	: "r" (__a7), "r"(__a1), "r"(__a2), "r"(__a3), "r"(__a4), "r"(__a5), "r"(__a6)	\
+	: __SYSCALL_CLOBBERS); 						\
+	_sys_result = __a0;						\
+	}								\
+	_sys_result;							\
+})
+
+#define __SYSCALL_CLOBBERS "memory"
+#endif /* ! __ASSEMBLER__ */
+
+/* Pointer mangling is not supported.  */
+#define PTR_MANGLE(var) (void) (var)
+#define PTR_DEMANGLE(var) (void) (var)
+
+#endif /* linux/mips/sysdep.h */
diff --git a/sysdeps/unix/sysv/linux/riscv/vfork.S b/sysdeps/unix/sysv/linux/riscv/vfork.S
new file mode 100644
index 000000000000..9bddd8d1f4f9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/vfork.S
@@ -0,0 +1,44 @@ 
+/* vfork for Linux, RISC-V version.
+   Copyright (C) 2005-2017 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/>.  */
+
+/* vfork() is just a special case of clone().  */
+
+#include <sys/asm.h>
+#include <sysdep.h>
+#define __ASSEMBLY__
+#include <linux/sched.h>
+#include <asm/signal.h>
+
+	.text
+LEAF(__libc_vfork)
+
+	li	a0, (CLONE_VFORK | CLONE_VM | SIGCHLD)
+	mv	a1, sp
+
+	li	a7, __NR_clone
+	scall
+
+	bltz	a0, 1f
+	ret
+
+1:	j		__syscall_error
+END(__libc_vfork)
+
+weak_alias (__libc_vfork, vfork)
+strong_alias (__libc_vfork, __vfork)
+libc_hidden_def (__vfork)