diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2018-07-17 02:55:19 +0100 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2019-01-02 03:08:04 +0000 |
commit | 9bfe94c405b6ae3f7a5c04c0d4cd539867ad2b85 (patch) | |
tree | a32210892fc28c6ba7358a3c642dd6a84c82e246 | |
parent | d8d26edbf94316286900ecf363382b0fcc2d76b2 (diff) | |
download | klibc-9bfe94c405b6ae3f7a5c04c0d4cd539867ad2b85.tar.gz |
[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@decadent.org.uk>
-rw-r--r-- | usr/include/arch/riscv64/klibc/archconfig.h | 15 | ||||
-rw-r--r-- | usr/include/arch/riscv64/klibc/archsetjmp.h | 27 | ||||
-rw-r--r-- | usr/include/arch/riscv64/klibc/archsignal.h | 14 | ||||
-rw-r--r-- | usr/include/arch/riscv64/klibc/archstat.h | 28 | ||||
-rw-r--r-- | usr/include/arch/riscv64/machine/asm.h | 26 | ||||
-rw-r--r-- | usr/klibc/SYSCALLS.def | 2 | ||||
-rw-r--r-- | usr/klibc/arch/riscv64/Kbuild | 8 | ||||
-rw-r--r-- | usr/klibc/arch/riscv64/MCONFIG | 22 | ||||
-rw-r--r-- | usr/klibc/arch/riscv64/crt0.S | 22 | ||||
-rw-r--r-- | usr/klibc/arch/riscv64/setjmp.S | 50 | ||||
-rw-r--r-- | usr/klibc/arch/riscv64/syscall.S | 13 | ||||
-rw-r--r-- | usr/klibc/arch/riscv64/sysstub.ph | 26 |
12 files changed, 252 insertions, 1 deletions
diff --git a/usr/include/arch/riscv64/klibc/archconfig.h b/usr/include/arch/riscv64/klibc/archconfig.h new file mode 100644 index 00000000000000..e85a69c003d421 --- /dev/null +++ b/usr/include/arch/riscv64/klibc/archconfig.h @@ -0,0 +1,15 @@ +/* + * include/arch/riscv64/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* We have an MMU but no fork() syscall */ +#define _KLIBC_NO_MMU 0 + +#endif /* _KLIBC_ARCHCONFIG_H */ diff --git a/usr/include/arch/riscv64/klibc/archsetjmp.h b/usr/include/arch/riscv64/klibc/archsetjmp.h new file mode 100644 index 00000000000000..97d6b6bead8e00 --- /dev/null +++ b/usr/include/arch/riscv64/klibc/archsetjmp.h @@ -0,0 +1,27 @@ +/* + * 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; + unsigned long __s3; + unsigned long __s4; + unsigned long __s5; + unsigned long __s6; + unsigned long __s7; + unsigned long __s8; + unsigned long __s9; + unsigned long __s10; + unsigned long __s11; + unsigned long __sp; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/usr/include/arch/riscv64/klibc/archsignal.h b/usr/include/arch/riscv64/klibc/archsignal.h new file mode 100644 index 00000000000000..560a951247a466 --- /dev/null +++ b/usr/include/arch/riscv64/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/riscv/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include <asm/signal.h> +/* No special stuff for this architecture */ + +#endif diff --git a/usr/include/arch/riscv64/klibc/archstat.h b/usr/include/arch/riscv64/klibc/archstat.h new file mode 100644 index 00000000000000..f5bfa80a5d4cef --- /dev/null +++ b/usr/include/arch/riscv64/klibc/archstat.h @@ -0,0 +1,28 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include <klibc/stathelp.h> + +#define _STATBUF_ST_NSEC + +struct stat { + __stdev64 (st_dev); /* Device */ + unsigned long st_ino; /* File serial number */ + unsigned int st_mode; /* File mode */ + unsigned int st_nlink; /* Link count */ + unsigned int st_uid; /* User ID of the file's owner */ + unsigned int st_gid; /* Group ID of the file's group */ + __stdev64 (st_rdev); /* Device number, if device */ + unsigned long __pad1; + long st_size; /* Size of file, in bytes */ + int st_blksize; /* Optimal block size for I/O */ + int __pad2; + long st_blocks; /* Number 512-byte blocks allocated */ + struct timespec st_atim; /* Time of last access */ + struct timespec st_mtim; /* Time of last modification */ + struct timespec st_ctim; /* Time of last status change */ + unsigned int __unused4; + unsigned int __unused5; +}; + +#endif diff --git a/usr/include/arch/riscv64/machine/asm.h b/usr/include/arch/riscv64/machine/asm.h new file mode 100644 index 00000000000000..9effc935652ff6 --- /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 64d7b0c1376665..8ebe8359a6c8f8 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@forkish(); #endif #if _KLIBC_REAL_VFORK diff --git a/usr/klibc/arch/riscv64/Kbuild b/usr/klibc/arch/riscv64/Kbuild new file mode 100644 index 00000000000000..242ac5bbc6abee --- /dev/null +++ b/usr/klibc/arch/riscv64/Kbuild @@ -0,0 +1,8 @@ +# -*- makefile -*- +# +# 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 00000000000000..38703d937e49d2 --- /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 00000000000000..76fa3c2876f9a6 --- /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 00000000000000..66e009efa890e0 --- /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 00000000000000..89d9bd2f923f29 --- /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/riscv64/sysstub.ph b/usr/klibc/arch/riscv64/sysstub.ph new file mode 100644 index 00000000000000..85c1beb89e92c1 --- /dev/null +++ b/usr/klibc/arch/riscv64/sysstub.ph @@ -0,0 +1,26 @@ +# -*- perl -*- +# +# arch/riscv/sysstub.ph +# +# Script to generate system call stubs +# + +# 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) = @_; + + $stype = $stype || 'common'; + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include <machine/asm.h>\n"; + print OUT "#include <asm/unistd.h>\n"; + print OUT "\n"; + print OUT "ENTRY(${fname})\n"; + print OUT "\tli\ta7, __NR_${sname}\n"; + print OUT "\tj\t__syscall_${stype}\n"; + print OUT "END(${fname})\n"; + close(OUT); +} + +1; |