[klibc 33/43] s390 support for klibc

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The parts of klibc specific to the s390 architecture.

Signed-off-by: H. Peter Anvin <[email protected]>

---
commit 418ab99cc64fed344e2d3e446208f48655cccb31
tree 958352848ed34bcf1aacdf5357ba453f96e38cbb
parent 6db62c809bf46ac8a9f743513384d29fd339f877
author H. Peter Anvin <[email protected]> Sun, 25 Jun 2006 16:58:42 -0700
committer H. Peter Anvin <[email protected]> Sun, 25 Jun 2006 16:58:42 -0700

 usr/include/arch/s390/klibc/archconfig.h |   15 ++++++
 usr/include/arch/s390/klibc/archsetjmp.h |   26 ++++++++++
 usr/include/arch/s390/klibc/archsignal.h |   14 ++++++
 usr/include/arch/s390/klibc/archstat.h   |   56 ++++++++++++++++++++++
 usr/include/arch/s390/klibc/archsys.h    |   41 ++++++++++++++++
 usr/klibc/arch/s390/MCONFIG              |   23 +++++++++
 usr/klibc/arch/s390/Makefile.inc         |   39 ++++++++++++++++
 usr/klibc/arch/s390/crt0.S               |   35 ++++++++++++++
 usr/klibc/arch/s390/mmap.c               |   75 ++++++++++++++++++++++++++++++
 usr/klibc/arch/s390/setjmp.S             |   66 ++++++++++++++++++++++++++
 usr/klibc/arch/s390/syscall.c            |   16 ++++++
 usr/klibc/arch/s390/sysstub.ph           |   40 ++++++++++++++++
 12 files changed, 446 insertions(+), 0 deletions(-)

diff --git a/usr/include/arch/s390/klibc/archconfig.h b/usr/include/arch/s390/klibc/archconfig.h
new file mode 100644
index 0000000..d7a71a4
--- /dev/null
+++ b/usr/include/arch/s390/klibc/archconfig.h
@@ -0,0 +1,15 @@
+/*
+ * include/arch/s390/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
+
+/* Both s390 and s390x use the "32-bit" version of this structure */
+#define _KLIBC_STATFS_F_TYPE_64 0
+
+#endif				/* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/s390/klibc/archsetjmp.h b/usr/include/arch/s390/klibc/archsetjmp.h
new file mode 100644
index 0000000..728780a
--- /dev/null
+++ b/usr/include/arch/s390/klibc/archsetjmp.h
@@ -0,0 +1,26 @@
+/*
+ * arch/s390/include/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+#ifndef __s390x__
+
+struct __jmp_buf {
+	uint32_t __gregs[10];	/* general registers r6-r15 */
+	uint64_t __fpregs[2];	/* fp registers f4 and f6   */
+};
+
+#else /* __s390x__ */
+
+struct __jmp_buf {
+	uint64_t __gregs[10]; /* general registers r6-r15 */
+	uint64_t __fpregs[4]; /* fp registers f1, f3, f5, f7 */
+};
+
+#endif /* __s390x__ */
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#endif				/* _SETJMP_H */
diff --git a/usr/include/arch/s390/klibc/archsignal.h b/usr/include/arch/s390/klibc/archsignal.h
new file mode 100644
index 0000000..a16b977
--- /dev/null
+++ b/usr/include/arch/s390/klibc/archsignal.h
@@ -0,0 +1,14 @@
+/*
+ * arch/s390/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/s390/klibc/archstat.h b/usr/include/arch/s390/klibc/archstat.h
new file mode 100644
index 0000000..de3a9da
--- /dev/null
+++ b/usr/include/arch/s390/klibc/archstat.h
@@ -0,0 +1,56 @@
+#ifndef _KLIBC_ARCHSTAT_H
+#define _KLIBC_ARCHSTAT_H
+
+#include <klibc/stathelp.h>
+
+#define _STATBUF_ST_NSEC
+
+#ifndef __s390x__
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat {
+	__stdev64	(st_dev);
+        unsigned int    __pad1;
+#define STAT64_HAS_BROKEN_ST_INO        1
+        unsigned long   __st_ino;
+        unsigned int    st_mode;
+        unsigned int    st_nlink;
+        unsigned long   st_uid;
+        unsigned long   st_gid;
+	__stdev64	(st_rdev);
+        unsigned int    __pad3;
+        long long	st_size;
+        unsigned long   st_blksize;
+        unsigned char   __pad4[4];
+        unsigned long   __pad5;     /* future possible st_blocks high bits */
+        unsigned long   st_blocks;  /* Number 512-byte blocks allocated. */
+	struct timespec st_atim;
+	struct timespec st_mtim;
+	struct timespec st_ctim;
+        unsigned long long	st_ino;
+};
+
+#else /* __s390x__ */
+
+struct stat {
+	__stdev64	(st_dev);
+	unsigned long	st_ino;
+	unsigned long	st_nlink;
+	unsigned int	st_mode;
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+	unsigned int	__pad1;
+	__stdev64	(st_rdev);
+	unsigned long	st_size;
+	struct timespec	st_atim;
+	struct timespec	st_mtim;
+	struct timespec	st_ctim;
+	unsigned long	st_blksize;
+	long		st_blocks;
+	unsigned long	__unused[3];
+};
+
+#endif /* __s390x__ */
+#endif
diff --git a/usr/include/arch/s390/klibc/archsys.h b/usr/include/arch/s390/klibc/archsys.h
new file mode 100644
index 0000000..63079b4
--- /dev/null
+++ b/usr/include/arch/s390/klibc/archsys.h
@@ -0,0 +1,41 @@
+/*
+ * arch/s390/include/klibc/archsys.h
+ *
+ * Architecture-specific syscall definitions
+ */
+
+#ifndef _KLIBC_ARCHSYS_H
+#define _KLIBC_ARCHSYS_H
+
+/* S/390 only has five syscall parameters, and uses a structure for
+   6-argument syscalls. */
+
+#ifndef _syscall6
+
+#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,\
+                  type4,arg4,type5,arg5,type6,arg6)          \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4,    \
+          type5 arg5, type6 arg6) {			     \
+	unsigned long  __arg[6] = {			     \
+		(unsigned long) arg1, 			     \
+		(unsigned long) arg2, 			     \
+		(unsigned long) arg3, 			     \
+		(unsigned long) arg4, 			     \
+		(unsigned long) arg5,			     \
+		(unsigned long) arg6 			     \
+	};						     \
+	register void *__argp asm("2") = &__arg;	     \
+	long __res;					     \
+	__asm__ __volatile__ (               	             \
+                "    svc %b1\n"                              \
+                "    la  %0,2"                               \
+                : "=d" (__res)                               \
+                : "i" (__NR_##name),                         \
+                  "d" (__argp)				     \
+		: _svc_clobber);			     \
+	__syscall_return(type, __res);			     \
+}
+
+#endif				/* _syscall6() missing */
+
+#endif				/* _KLIBC_ARCHSYS_H */
diff --git a/usr/klibc/arch/s390/MCONFIG b/usr/klibc/arch/s390/MCONFIG
new file mode 100644
index 0000000..dd4495a
--- /dev/null
+++ b/usr/klibc/arch/s390/MCONFIG
@@ -0,0 +1,23 @@
+# -*- makefile -*-
+#
+# arch/s390/MCONFIG
+#
+# Special rules for this architecture.  Note that this is actually
+# included from the main Makefile, and that pathnames should be
+# accordingly.
+#
+
+KLIBCOPTFLAGS = -Os
+
+ifneq ("$(KLIBCARCH)", "s390x")
+	KLIBCBITSIZE	= 32
+	KLIBCCFLAGS	+= -m31
+	KLIBCLDFLAGS	+= -m elf_s390
+else
+	KLIBCBITSIZE	= 64
+	KLIBCCFLAGS	+= -m64
+	KLIBCLDFLAGS	+= -m elf64_s390
+endif
+
+KLIBCASMARCH		= s390
+KLIBCSHAREDFLAGS	= -Ttext 0x40000200
diff --git a/usr/klibc/arch/s390/Makefile.inc b/usr/klibc/arch/s390/Makefile.inc
new file mode 100644
index 0000000..7c1cb42
--- /dev/null
+++ b/usr/klibc/arch/s390/Makefile.inc
@@ -0,0 +1,39 @@
+# -*- makefile -*-
+#
+# arch/s390/Makefile.inc
+#
+# Special rules for this architecture.  Note that this is actually
+# included from the main Makefile, and that pathnames should be
+# accordingly.
+#
+
+ifneq ("$(KLIBCARCH)", "s390x")
+
+KLIBCARCHOBJS = \
+	arch/$(KLIBCARCHDIR)/setjmp.o \
+	arch/$(KLIBCARCHDIR)/mmap.o \
+	arch/$(KLIBCARCHDIR)/syscall.o \
+	libgcc/__clzsi2.o \
+	libgcc/__clzdi2.o \
+	libgcc/__ashldi3.o \
+	libgcc/__ashrdi3.o \
+	libgcc/__lshrdi3.o \
+	libgcc/__divdi3.o \
+	libgcc/__moddi3.o \
+	libgcc/__udivdi3.o \
+	libgcc/__umoddi3.o \
+	libgcc/__udivmoddi4.o
+
+else
+
+KLIBCARCHOBJS = \
+	arch/$(KLIBCARCHDIR)/setjmp.o \
+	arch/$(KLIBCARCHDIR)/mmap.o \
+	arch/$(KLIBCARCHDIR)/syscall.o
+
+endif
+
+KLIBCARCHSOOBJS = $(patsubst %.o,%.lo,$(KLIBCARCHOBJS))
+
+
+archclean:
diff --git a/usr/klibc/arch/s390/crt0.S b/usr/klibc/arch/s390/crt0.S
new file mode 100644
index 0000000..fd9237e
--- /dev/null
+++ b/usr/klibc/arch/s390/crt0.S
@@ -0,0 +1,35 @@
+#
+# arch/s390/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.
+#
+	.text
+	.align 4
+	.type _start,@function
+	.globl _start
+
+#ifndef __s390x__
+
+_start:
+	lr	%r2,%r15
+	lhi	%r3,0
+	ahi	%r15,-96
+	bras	%r1,.L0
+.L0:
+	l	%r1,.L1-.L0(%r1)
+	br	%r1
+.L1:
+	.long	__libc_init
+#else
+
+_start:
+	lgr	%r2,%r15
+	lghi	%r3,0
+	aghi	%r15,-160
+	jg	__libc_init
+#endif
+	.size _start,.-_start
diff --git a/usr/klibc/arch/s390/mmap.c b/usr/klibc/arch/s390/mmap.c
new file mode 100644
index 0000000..4c43779
--- /dev/null
+++ b/usr/klibc/arch/s390/mmap.c
@@ -0,0 +1,75 @@
+#include <errno.h>
+#include <sys/types.h>
+#include <linux/unistd.h>
+
+struct mmap_arg_struct {
+	unsigned long addr;
+	unsigned long len;
+	unsigned long prot;
+	unsigned long flags;
+	unsigned long fd;
+	unsigned long offset;
+};
+
+#ifndef __s390x__
+
+void *__mmap2(void *addr, size_t len, int prot, int flags, int fd, long offset)
+{
+	struct mmap_arg_struct args = {
+		(unsigned long)addr,
+		(unsigned long)len,
+		(unsigned long)prot,
+		(unsigned long)flags,
+		(unsigned long)fd,
+		(unsigned long)offset,
+	};
+
+	register struct mmap_arg_struct *__arg1 asm("2") = &args;
+	register long __svcres asm("2");
+	unsigned long __res;
+
+	__asm__ __volatile__("    svc %b1\n"
+			     : "=d"(__svcres)
+			     : "i"(__NR_mmap2), "0"(__arg1)
+			     : "1", "cc", "memory");
+	__res = __svcres;
+	if (__res >= (unsigned long)-4095) {
+		errno = -__res;
+		__res = -1;
+	}
+	return (void *)__res;
+}
+
+#else /* __s390x__ */
+
+void * mmap(void * addr, size_t len, int prot, int flags,
+						 int fd, off_t offset)
+{
+	struct mmap_arg_struct args = {
+		(unsigned long) addr,
+		(unsigned long) len,
+		(unsigned long) prot,
+		(unsigned long) flags,
+		(unsigned long) fd,
+		(unsigned long) offset,
+	};
+
+	register struct mmap_arg_struct *__arg1 asm("2") = &args;
+	register long __svcres asm("2");
+	unsigned long __res;
+
+	__asm__ __volatile__ (
+		"    svc %b1\n"
+		: "=d" (__svcres)
+		: "i" (__NR_mmap),
+		  "0" (__arg1)
+		: "1", "cc", "memory");
+	__res = __svcres;
+	if (__res >= (unsigned long)-4095) {
+		errno = -__res;
+		__res = -1;
+	}
+	return (void *)__res;
+}
+
+#endif /* __s390x__ */
diff --git a/usr/klibc/arch/s390/setjmp.S b/usr/klibc/arch/s390/setjmp.S
new file mode 100644
index 0000000..c36a051
--- /dev/null
+++ b/usr/klibc/arch/s390/setjmp.S
@@ -0,0 +1,66 @@
+#
+# arch/s390/setjmp.S
+#
+# setjmp/longjmp for the s390 architecture
+#
+
+	.text
+	.align 4
+	.globl setjmp
+	.type setjmp, @function
+
+#ifndef __s390x__
+
+setjmp:
+	stm	%r6,%r15,0(%r2)		# save all general registers
+	std	%f4,40(%r2)		# save fp registers f4 and f6
+	std	%f6,48(%r2)
+	lhi	%r2,0			# return 0
+	br	%r14
+
+	.size setjmp,.-setjmp
+
+	.text
+	.align 4
+	.globl longjmp
+	.type longjmp, @function
+longjmp:
+	lr	%r1,%r2			# jmp_buf
+	lr	%r2,%r3			# return value
+	ld	%f6,48(%r1)		# restore all saved registers
+	ld	%f4,40(%r1)
+	lm	%r6,%r15,0(%r1)
+	br	%r14			# return to restored address
+
+	.size longjmp,.-longjmp
+
+#else
+
+setjmp:
+	stmg	%r6,%r15,0(%r2)		# save all general registers
+	std	%f1,80(%r2)		# save fp registers f4 and f6
+	std	%f3,88(%r2)
+	std	%f5,96(%r2)
+	std	%f7,104(%r2)
+	lghi	%r2,0			# return 0
+	br	%r14
+
+	.size setjmp,.-setjmp
+
+	.text
+	.align 4
+	.globl longjmp
+	.type longjmp, @function
+longjmp:
+	lgr	%r1,%r2			# jmp_buf
+	lgr	%r2,%r3			# return value
+	ld	%f7,104(%r1)		# restore all saved registers
+	ld	%f5,96(%r1)
+	ld	%f3,88(%r1)
+	ld	%f1,80(%r1)
+	lmg	%r6,%r15,0(%r1)
+	br	%r14			# return to restored address
+
+	.size longjmp,.-longjmp
+
+#endif
diff --git a/usr/klibc/arch/s390/syscall.c b/usr/klibc/arch/s390/syscall.c
new file mode 100644
index 0000000..e1d201d
--- /dev/null
+++ b/usr/klibc/arch/s390/syscall.c
@@ -0,0 +1,16 @@
+/*
+ * arch/s390/syscall.c
+ *
+ * Common error-handling path for system calls.
+ * The return value from __syscall_common becomes the
+ * return value from the system call.
+ */
+#include <errno.h>
+
+unsigned long __syscall_common(unsigned long err)
+{
+	if (err < -4095UL)
+		return err;
+	errno = -err;
+	return -1;
+}
diff --git a/usr/klibc/arch/s390/sysstub.ph b/usr/klibc/arch/s390/sysstub.ph
new file mode 100644
index 0000000..880a0da
--- /dev/null
+++ b/usr/klibc/arch/s390/sysstub.ph
@@ -0,0 +1,40 @@
+# -*- perl -*-
+#
+# arch/s390/sysstub.ph
+#
+# Script to generate system call stubs
+#
+
+sub make_sysstub($$$$$@) {
+    my($outputdir, $fname, $type, $sname, $stype, @args) = @_;
+
+    open(OUT, '>', "${outputdir}/${fname}.S");
+    print OUT "#include <asm/unistd.h>\n";
+    print OUT "\n";
+    print OUT "\t.type ${fname},\@function\n";
+    print OUT "\t.globl ${fname}\n";
+    print OUT "${fname}:\n";
+    print OUT ".if __NR_${sname} < 256\n";
+    print OUT "\tsvc __NR_${sname}\n";
+    print OUT ".else\n";
+    print OUT "\tla %r1,__NR_${sname}\n";
+    print OUT "\tsvc 0\n";
+    print OUT ".endif\n";
+
+    print OUT "#ifndef __s390x__\n";
+
+    print OUT "\tbras %r3,1f\n";
+    print OUT "\t.long __syscall_common\n";
+    print OUT "1:\tl %r3,0(%r3)\n";
+    print OUT "\tbr %r3\n";
+
+    print OUT "#else\n";
+
+    print OUT "\tbrasl %r3,__syscall_common\n";
+
+    print OUT "#endif\n";
+    print OUT "\t.size ${fname},.-${fname}\n";
+    close(OUT);
+}
+
+1;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux