From: Feiyang Chen <chenfeiyang at loongson.cn>
Add LoongArch64 support. I've cribbed most of this from the
RISC-V and MIPS ports.
Signed-off-by: Feiyang Chen <chenfeiyang at loongson.cn>
---
.../arch/loongarch64/klibc/archconfig.h | 15 ++++++
.../arch/loongarch64/klibc/archsetjmp.h | 26 ++++++++++
.../arch/loongarch64/klibc/archsignal.h | 14 ++++++
usr/include/arch/loongarch64/machine/asm.h | 24 +++++++++
usr/klibc/SYSCALLS.def | 2 +-
usr/klibc/arch/loongarch64/Kbuild | 7 +++
usr/klibc/arch/loongarch64/MCONFIG | 23 +++++++++
usr/klibc/arch/loongarch64/crt0.S | 18 +++++++
usr/klibc/arch/loongarch64/setjmp.S | 50 +++++++++++++++++++
usr/klibc/arch/loongarch64/syscall.S | 13 +++++
usr/klibc/arch/loongarch64/sysstub.ph | 26 ++++++++++
11 files changed, 217 insertions(+), 1 deletion(-)
create mode 100644 usr/include/arch/loongarch64/klibc/archconfig.h
create mode 100644 usr/include/arch/loongarch64/klibc/archsetjmp.h
create mode 100644 usr/include/arch/loongarch64/klibc/archsignal.h
create mode 100644 usr/include/arch/loongarch64/machine/asm.h
create mode 100644 usr/klibc/arch/loongarch64/Kbuild
create mode 100644 usr/klibc/arch/loongarch64/MCONFIG
create mode 100644 usr/klibc/arch/loongarch64/crt0.S
create mode 100644 usr/klibc/arch/loongarch64/setjmp.S
create mode 100644 usr/klibc/arch/loongarch64/syscall.S
create mode 100644 usr/klibc/arch/loongarch64/sysstub.ph
diff --git a/usr/include/arch/loongarch64/klibc/archconfig.h
b/usr/include/arch/loongarch64/klibc/archconfig.h
new file mode 100644
index 00000000..7a47b915
--- /dev/null
+++ b/usr/include/arch/loongarch64/klibc/archconfig.h
@@ -0,0 +1,15 @@
+/*
+ * include/arch/loongarch64/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/loongarch64/klibc/archsetjmp.h
b/usr/include/arch/loongarch64/klibc/archsetjmp.h
new file mode 100644
index 00000000..939c0f5f
--- /dev/null
+++ b/usr/include/arch/loongarch64/klibc/archsetjmp.h
@@ -0,0 +1,26 @@
+/*
+ * include/arch/loongarch64/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+ unsigned long __ra;
+ unsigned long __sp;
+ unsigned long __r21;
+ unsigned long __fp;
+ 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;
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#endif /* _SETJMP_H */
diff --git a/usr/include/arch/loongarch64/klibc/archsignal.h
b/usr/include/arch/loongarch64/klibc/archsignal.h
new file mode 100644
index 00000000..c22a5d7c
--- /dev/null
+++ b/usr/include/arch/loongarch64/klibc/archsignal.h
@@ -0,0 +1,14 @@
+/*
+ * include/arch/loongarch64/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/loongarch64/machine/asm.h
b/usr/include/arch/loongarch64/machine/asm.h
new file mode 100644
index 00000000..6fe5dba2
--- /dev/null
+++ b/usr/include/arch/loongarch64/machine/asm.h
@@ -0,0 +1,24 @@
+/*
+ * include/arch/loongarch64/machine/asm.h
+ */
+
+#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 660efc66..9b6b1127 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,riscv64> pid_t fork();
+<!sparc,sparc64,ia64,arm64,riscv64,loongarch64> pid_t fork();
<sparc,sparc64> pid_t fork at forkish();
#endif
#if _KLIBC_REAL_VFORK
diff --git a/usr/klibc/arch/loongarch64/Kbuild
b/usr/klibc/arch/loongarch64/Kbuild
new file mode 100644
index 00000000..60c7660c
--- /dev/null
+++ b/usr/klibc/arch/loongarch64/Kbuild
@@ -0,0 +1,7 @@
+#
+# klibc files for LoongArch64
+#
+
+klib-y := setjmp.o syscall.o
+always := crt0.o
+targets := crt0.o
diff --git a/usr/klibc/arch/loongarch64/MCONFIG
b/usr/klibc/arch/loongarch64/MCONFIG
new file mode 100644
index 00000000..0ef5eae8
--- /dev/null
+++ b/usr/klibc/arch/loongarch64/MCONFIG
@@ -0,0 +1,23 @@
+# -*- makefile -*-
+#
+# arch/loongarch64/MCONFIG
+#
+# Special rules for this architecture. Note that this is actually
+# included from the main Makefile, and that pathnames should be
+# accordingly.
+#
+
+KLIBCOPTFLAGS += -Os -fomit-frame-pointer
+KLIBCBITSIZE = 64
+
+# Extra linkflags when building the shared version of the library
+# This address needs to be reachable using normal inter-module
+# calls, and work on the memory models for this architecture
+# 4862 MB - normal binaries start at 4608 MB. Non-PIC jumps usually
+# use the BL instruction which requires a destination between -128M
+# to 128M. Since we can't put ourselves below the normal load
+# address, use the very top of the 128M region (minus 2MB)
+KLIBCSHAREDFLAGS = $(LD_IMAGE_BASE_OPT) 0x127E00000
+
+# Kernel has never used stack trampolines
+KLIBCEXECSTACK := n
diff --git a/usr/klibc/arch/loongarch64/crt0.S
b/usr/klibc/arch/loongarch64/crt0.S
new file mode 100644
index 00000000..cb3da669
--- /dev/null
+++ b/usr/klibc/arch/loongarch64/crt0.S
@@ -0,0 +1,18 @@
+#
+# arch/loongarch64/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)
+ move $a0, $sp # Pointer to ELF entry structure
+ move $a1, $zero # No onexit pointer
+ bstrins.d $sp, $zero, 3, 0 # Align stack to 16 bytes
+ bl __libc_init
+END(_start)
diff --git a/usr/klibc/arch/loongarch64/setjmp.S
b/usr/klibc/arch/loongarch64/setjmp.S
new file mode 100644
index 00000000..11779885
--- /dev/null
+++ b/usr/klibc/arch/loongarch64/setjmp.S
@@ -0,0 +1,50 @@
+/*
+ * arch/loongarch64/setjmp.S
+ *
+ * setjmp/longjmp for the LoongArch64 architecture
+ *
+ * The jmp_buf is assumed to contain the following, in order:
+ * pc (ra)
+ * sp
+ * r21
+ * fp
+ * s0..s8
+ */
+
+#include <machine/asm.h>
+
+ENTRY(setjmp)
+ st.d $ra, $a0, 0
+ st.d $sp, $a0, 8
+ st.d $r21, $a0, 16
+ st.d $fp, $a0, 24
+ st.d $s0, $a0, 32
+ st.d $s1, $a0, 40
+ st.d $s2, $a0, 48
+ st.d $s3, $a0, 56
+ st.d $s4, $a0, 64
+ st.d $s5, $a0, 72
+ st.d $s6, $a0, 80
+ st.d $s7, $a0, 88
+ st.d $s8, $a0, 96
+ move $a0, $zero
+ jr $ra
+END(setjmp)
+
+ENTRY(longjmp)
+ ld.d $ra, $a0, 0
+ ld.d $sp, $a0, 8
+ ld.d $r21, $a0, 16
+ ld.d $fp, $a0, 24
+ ld.d $s0, $a0, 32
+ ld.d $s1, $a0, 40
+ ld.d $s2, $a0, 48
+ ld.d $s3, $a0, 56
+ ld.d $s4, $a0, 64
+ ld.d $s5, $a0, 72
+ ld.d $s6, $a0, 80
+ ld.d $s7, $a0, 88
+ ld.d $s8, $a0, 96
+ move $a0, $a1
+ jr $ra
+END(longjmp)
diff --git a/usr/klibc/arch/loongarch64/syscall.S
b/usr/klibc/arch/loongarch64/syscall.S
new file mode 100644
index 00000000..9a2ed469
--- /dev/null
+++ b/usr/klibc/arch/loongarch64/syscall.S
@@ -0,0 +1,13 @@
+#include <machine/asm.h>
+#include <asm/unistd.h>
+
+ENTRY(__syscall_common)
+ syscall 0
+ li.w $t0, -4096
+ bleu $a0, $t0, 1f
+ sub.d $a0, $zero, $a0
+ la $t0, errno
+ st.d $a0, $t0, 0
+ li.w $a0, -1
+1: jr $ra
+END(__syscall_common)
diff --git a/usr/klibc/arch/loongarch64/sysstub.ph
b/usr/klibc/arch/loongarch64/sysstub.ph
new file mode 100644
index 00000000..699bdc2f
--- /dev/null
+++ b/usr/klibc/arch/loongarch64/sysstub.ph
@@ -0,0 +1,26 @@
+# -*- perl -*-
+#
+# arch/loongarch64/sysstub.ph
+#
+# Script to generate system call stubs
+#
+
+# On LoongArch64, most system calls follow the standard convention, with
+# the system call number in a7 and the return value in 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.w\t\$a7, __NR_${sname}\n";
+ print OUT "\tb\t__syscall_${stype}\n";
+ print OUT "END(${fname})\n";
+ close(OUT);
+}
+
+1;
--
2.39.1