aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2018-07-17 02:55:19 +0100
committerBen Hutchings <ben@decadent.org.uk>2019-01-02 03:08:04 +0000
commit9bfe94c405b6ae3f7a5c04c0d4cd539867ad2b85 (patch)
treea32210892fc28c6ba7358a3c642dd6a84c82e246
parentd8d26edbf94316286900ecf363382b0fcc2d76b2 (diff)
downloadklibc-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.h15
-rw-r--r--usr/include/arch/riscv64/klibc/archsetjmp.h27
-rw-r--r--usr/include/arch/riscv64/klibc/archsignal.h14
-rw-r--r--usr/include/arch/riscv64/klibc/archstat.h28
-rw-r--r--usr/include/arch/riscv64/machine/asm.h26
-rw-r--r--usr/klibc/SYSCALLS.def2
-rw-r--r--usr/klibc/arch/riscv64/Kbuild8
-rw-r--r--usr/klibc/arch/riscv64/MCONFIG22
-rw-r--r--usr/klibc/arch/riscv64/crt0.S22
-rw-r--r--usr/klibc/arch/riscv64/setjmp.S50
-rw-r--r--usr/klibc/arch/riscv64/syscall.S13
-rw-r--r--usr/klibc/arch/riscv64/sysstub.ph26
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;