klibc-bot for Ben Hutchings
2019-Jan-18 16:42 UTC
[klibc] [klibc:master] Add RISC-V (RV64) port
Commit-ID: f1c1f4f99e60ac0f855a0582b4aebebfbb0804dc Gitweb: http://git.kernel.org/?p=libs/klibc/klibc.git;a=commit;h=f1c1f4f99e60ac0f855a0582b4aebebfbb0804dc Author: Ben Hutchings <ben at decadent.org.uk> AuthorDate: Tue, 17 Jul 2018 02:55:19 +0100 Committer: Ben Hutchings <ben at decadent.org.uk> CommitDate: Fri, 18 Jan 2019 03:10:14 +0000 [klibc] Add RISC-V (RV64) port RISC-V is pretty boring. I've cribbed most of this from the MIPS and AArch64 ports. I ran into difficulty with initialisation of the gp,register, which I think has to be process-global - the psABI says that signal handlers can rely on it, and they could come from any module. This means that klibc.so and the executable using it need to agree on a single value. Currently they don't, and this causes gp-relative addressing to go wrong. gp-relative addressing is introduced by "relaxation" in the linker, so I've disabled that for now. Link: https://www.zytor.com/pipermail/klibc/2018-July/003997.html Signed-off-by: Ben Hutchings <ben at decadent.org.uk> --- .../arch/{arm64 => riscv64}/klibc/archconfig.h | 6 +-- .../arch/{mips64 => riscv64}/klibc/archsetjmp.h | 14 +++--- .../arch/{cris => riscv64}/klibc/archsignal.h | 2 +- .../arch/{arm64 => riscv64}/klibc/archstat.h | 0 usr/include/arch/riscv64/machine/asm.h | 26 +++++++++++ usr/klibc/SYSCALLS.def | 2 +- usr/klibc/arch/{ppc64 => riscv64}/Kbuild | 8 ++-- usr/klibc/arch/riscv64/MCONFIG | 22 ++++++++++ usr/klibc/arch/riscv64/crt0.S | 22 ++++++++++ usr/klibc/arch/riscv64/setjmp.S | 50 ++++++++++++++++++++++ usr/klibc/arch/riscv64/syscall.S | 13 ++++++ usr/klibc/arch/{mips => riscv64}/sysstub.ph | 15 +++---- 12 files changed, 155 insertions(+), 25 deletions(-) diff --git a/usr/include/arch/arm64/klibc/archconfig.h b/usr/include/arch/riscv64/klibc/archconfig.h similarity index 64% copy from usr/include/arch/arm64/klibc/archconfig.h copy to usr/include/arch/riscv64/klibc/archconfig.h index 5e2004b..e85a69c 100644 --- a/usr/include/arch/arm64/klibc/archconfig.h +++ b/usr/include/arch/riscv64/klibc/archconfig.h @@ -1,5 +1,5 @@ /* - * include/arch/arm64/klibc/archconfig.h + * include/arch/riscv64/klibc/archconfig.h * * See include/klibc/sysconfig.h for the options that can be set in * this file. @@ -9,9 +9,7 @@ #ifndef _KLIBC_ARCHCONFIG_H #define _KLIBC_ARCHCONFIG_H -/* Use rt_* signals */ -#define _KLIBC_USE_RT_SIG 1 +/* We have an MMU but no fork() syscall */ #define _KLIBC_NO_MMU 0 -#define _KLIBC_REAL_VFORK 1 #endif /* _KLIBC_ARCHCONFIG_H */ diff --git a/usr/include/arch/mips64/klibc/archsetjmp.h b/usr/include/arch/riscv64/klibc/archsetjmp.h similarity index 67% copy from usr/include/arch/mips64/klibc/archsetjmp.h copy to usr/include/arch/riscv64/klibc/archsetjmp.h index bfca777..97d6b6b 100644 --- a/usr/include/arch/mips64/klibc/archsetjmp.h +++ b/usr/include/arch/riscv64/klibc/archsetjmp.h @@ -1,11 +1,12 @@ /* - * arch/mips64/include/klibc/archsetjmp.h + * arch/riscv64/include/klibc/archsetjmp.h */ #ifndef _KLIBC_ARCHSETJMP_H #define _KLIBC_ARCHSETJMP_H struct __jmp_buf { + unsigned long __pc; unsigned long __s0; unsigned long __s1; unsigned long __s2; @@ -14,12 +15,13 @@ struct __jmp_buf { unsigned long __s5; unsigned long __s6; unsigned long __s7; - unsigned long __gp; - unsigned long __sp; unsigned long __s8; - unsigned long __ra; -} __attribute__ ((aligned(8))); + unsigned long __s9; + unsigned long __s10; + unsigned long __s11; + unsigned long __sp; +}; typedef struct __jmp_buf jmp_buf[1]; -#endif /* _KLIBC_ARCHSETJMP_H */ +#endif /* _SETJMP_H */ diff --git a/usr/include/arch/cris/klibc/archsignal.h b/usr/include/arch/riscv64/klibc/archsignal.h similarity index 82% copy from usr/include/arch/cris/klibc/archsignal.h copy to usr/include/arch/riscv64/klibc/archsignal.h index 7fa7454..560a951 100644 --- a/usr/include/arch/cris/klibc/archsignal.h +++ b/usr/include/arch/riscv64/klibc/archsignal.h @@ -1,5 +1,5 @@ /* - * arch/cris/include/klibc/archsignal.h + * arch/riscv/include/klibc/archsignal.h * * Architecture-specific signal definitions * diff --git a/usr/include/arch/arm64/klibc/archstat.h b/usr/include/arch/riscv64/klibc/archstat.h similarity index 100% copy from usr/include/arch/arm64/klibc/archstat.h copy to usr/include/arch/riscv64/klibc/archstat.h diff --git a/usr/include/arch/riscv64/machine/asm.h b/usr/include/arch/riscv64/machine/asm.h new file mode 100644 index 0000000..9effc93 --- /dev/null +++ b/usr/include/arch/riscv64/machine/asm.h @@ -0,0 +1,26 @@ +/* + * arch/riscv64/include/machine/asm.h + * + * Mostly cribbed from mips. + */ + +#ifndef _MACHINE_ASM_H +#define _MACHINE_ASM_H + +/* + * ENTRY - declare entry point + */ +#define ENTRY(symbol) \ + .globl symbol; \ + .align 2; \ + .type symbol, @function; \ +symbol: + +/* + * END - mark end of function + */ +#define END(function) \ + .size function, . - function + + +#endif /* _MACHINE_ASM_H */ diff --git a/usr/klibc/SYSCALLS.def b/usr/klibc/SYSCALLS.def index 64d7b0c..8ebe835 100644 --- a/usr/klibc/SYSCALLS.def +++ b/usr/klibc/SYSCALLS.def @@ -21,7 +21,7 @@ void _exit,exit::_exit(int); <?!ia64> pid_t clone::__clone(unsigned long, void *); <?ia64> pid_t clone::__clone2(unsigned long, void *, void *); # if ! _KLIBC_NO_MMU -<!sparc,sparc64,ia64,arm64> pid_t fork(); +<!sparc,sparc64,ia64,arm64,riscv64> pid_t fork(); <sparc,sparc64> pid_t fork at forkish(); #endif #if _KLIBC_REAL_VFORK diff --git a/usr/klibc/arch/ppc64/Kbuild b/usr/klibc/arch/riscv64/Kbuild similarity index 60% copy from usr/klibc/arch/ppc64/Kbuild copy to usr/klibc/arch/riscv64/Kbuild index a39e91f..242ac5b 100644 --- a/usr/klibc/arch/ppc64/Kbuild +++ b/usr/klibc/arch/riscv64/Kbuild @@ -1,8 +1,8 @@ +# -*- makefile -*- # -# klibc files for ppc64 -# - -klib-y := setjmp.o syscall.o +# klibc files for riscv64 always := crt0.o targets := crt0.o + +klib-y := setjmp.o syscall.o diff --git a/usr/klibc/arch/riscv64/MCONFIG b/usr/klibc/arch/riscv64/MCONFIG new file mode 100644 index 0000000..38703d9 --- /dev/null +++ b/usr/klibc/arch/riscv64/MCONFIG @@ -0,0 +1,22 @@ +# -*- makefile -*- +# +# arch/riscv64/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +# We should get klibc.so and the executables to agree on what gp +# should be. For now, disable gp-relative addressing. +KLIBCLDFLAGS = --no-relax +KLIBCOPTFLAGS += -Os -fomit-frame-pointer +ifeq ($(DEBUG),y) +KLIBCOPTFLAGS += -g +endif +KLIBCBITSIZE = 64 + +# Normal binaries start at 64 KB, so start the libary at 2 MB. +KLIBCSHAREDFLAGS =-Ttext 0x00200200 + +KLIBCARCHINCFLAGS = -I$(KLIBCKERNELOBJ)/arch/riscv/include diff --git a/usr/klibc/arch/riscv64/crt0.S b/usr/klibc/arch/riscv64/crt0.S new file mode 100644 index 0000000..76fa3c2 --- /dev/null +++ b/usr/klibc/arch/riscv64/crt0.S @@ -0,0 +1,22 @@ +# +# arch/riscv64/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + +#include <machine/asm.h> + +ENTRY(_start) + .option push + .option norelax + lla gp, __global_pointer$ + .option pop + + mv a0, sp # Pointer to ELF entry structure + mv a1, zero # No onexit pointer + jal __libc_init +END(_start) diff --git a/usr/klibc/arch/riscv64/setjmp.S b/usr/klibc/arch/riscv64/setjmp.S new file mode 100644 index 0000000..66e009e --- /dev/null +++ b/usr/klibc/arch/riscv64/setjmp.S @@ -0,0 +1,50 @@ +/* + * arch/riscv64/setjmp.S + * + * setjmp/longjmp for the RISC-V (RV64) architecture + * + * The jmp_buf is assumed to contain the following, in order: + * pc (ra) + * s0..s11 + * sp + */ + +#include <machine/asm.h> + +ENTRY(setjmp) + sd ra, 0(a0) + sd s0, 8(a0) + sd s1, 16(a0) + sd s2, 24(a0) + sd s3, 32(a0) + sd s4, 40(a0) + sd s5, 48(a0) + sd s6, 56(a0) + sd s7, 64(a0) + sd s8, 72(a0) + sd s9, 80(a0) + sd s10, 88(a0) + sd s11, 96(a0) + sd sp, 104(a0) + mv a0, zero + jr ra +END(setjmp) + +ENTRY(longjmp) + ld ra, 0(a0) + ld s0, 8(a0) + ld s1, 16(a0) + ld s2, 24(a0) + ld s3, 32(a0) + ld s4, 40(a0) + ld s5, 48(a0) + ld s6, 56(a0) + ld s7, 64(a0) + ld s8, 72(a0) + ld s9, 80(a0) + ld s10, 88(a0) + ld s11, 96(a0) + ld sp, 104(a0) + mv a0, a1 + jr ra +END(longjmp) diff --git a/usr/klibc/arch/riscv64/syscall.S b/usr/klibc/arch/riscv64/syscall.S new file mode 100644 index 0000000..89d9bd2 --- /dev/null +++ b/usr/klibc/arch/riscv64/syscall.S @@ -0,0 +1,13 @@ +#include <machine/asm.h> +#include <asm/unistd.h> + +ENTRY(__syscall_common) + scall + li t0, -4096 + bleu a0, t0, 1f + neg a0, a0 + lui t0, %hi(errno) + sw a0, %lo(errno)(t0) + li a0, -1 +1: jr ra +END(__syscall_common) diff --git a/usr/klibc/arch/mips/sysstub.ph b/usr/klibc/arch/riscv64/sysstub.ph similarity index 52% copy from usr/klibc/arch/mips/sysstub.ph copy to usr/klibc/arch/riscv64/sysstub.ph index 3689529..85c1beb 100644 --- a/usr/klibc/arch/mips/sysstub.ph +++ b/usr/klibc/arch/riscv64/sysstub.ph @@ -1,13 +1,12 @@ # -*- perl -*- # -# arch/mips/sysstub.ph +# arch/riscv/sysstub.ph # # Script to generate system call stubs # -# On MIPS, most system calls follow the standard convention, with the -# system call number in r0 (v0), return an error value in r19 (a3) as -# well as the return value in r0 (v0). +# On RISC-V, most system calls follow the standard convention, with the +# system call number in x17 (a7) and the return value in x10 (a0). sub make_sysstub($$$$$@) { my($outputdir, $fname, $type, $sname, $stype, @args) = @_; @@ -17,12 +16,10 @@ sub make_sysstub($$$$$@) { print OUT "#include <machine/asm.h>\n"; print OUT "#include <asm/unistd.h>\n"; print OUT "\n"; - print OUT "\t.set noreorder\n"; - print OUT "\n"; - print OUT "LEAF(${fname})\n"; + print OUT "ENTRY(${fname})\n"; + print OUT "\tli\ta7, __NR_${sname}\n"; print OUT "\tj\t__syscall_${stype}\n"; - print OUT "\t li\tv0, __NR_${sname}\n"; - print OUT "\tEND(${fname})\n"; + print OUT "END(${fname})\n"; close(OUT); }