summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/microblaze
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@uclibc-ng.org>2016-10-31 18:05:44 +0100
committerWaldemar Brodkorb <wbx@uclibc-ng.org>2016-11-03 20:37:48 +0100
commit191739597c6d380692885cfdd8dd8aa4f31f029d (patch)
treeb3f05ce72f7a87433905698dd58371048c904812 /libc/sysdeps/linux/microblaze
parent7825930078208462655e107677656c45014e91b4 (diff)
microblaze: add NPTL/TLS support from GNU libc
Not perfect, but a starting point. Some tests of the test suite are failing.
Diffstat (limited to 'libc/sysdeps/linux/microblaze')
-rw-r--r--libc/sysdeps/linux/microblaze/Makefile.arch2
-rw-r--r--libc/sysdeps/linux/microblaze/__syscall_error.c18
-rw-r--r--libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h3
-rw-r--r--libc/sysdeps/linux/microblaze/clone.S17
-rw-r--r--libc/sysdeps/linux/microblaze/jmpbuf-offsets.h6
-rw-r--r--libc/sysdeps/linux/microblaze/jmpbuf-unwind.h25
-rw-r--r--libc/sysdeps/linux/microblaze/sysdep.h83
-rw-r--r--libc/sysdeps/linux/microblaze/vfork.S58
8 files changed, 164 insertions, 48 deletions
diff --git a/libc/sysdeps/linux/microblaze/Makefile.arch b/libc/sysdeps/linux/microblaze/Makefile.arch
index e23515ed0..b89f7f945 100644
--- a/libc/sysdeps/linux/microblaze/Makefile.arch
+++ b/libc/sysdeps/linux/microblaze/Makefile.arch
@@ -5,5 +5,5 @@
#
# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
-CSRC-y :=
+CSRC-y := __syscall_error.c
SSRC-y := setjmp.S __longjmp.S vfork.S clone.S
diff --git a/libc/sysdeps/linux/microblaze/__syscall_error.c b/libc/sysdeps/linux/microblaze/__syscall_error.c
new file mode 100644
index 000000000..2b642e816
--- /dev/null
+++ b/libc/sysdeps/linux/microblaze/__syscall_error.c
@@ -0,0 +1,18 @@
+/* Wrapper for setting errno.
+ *
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <errno.h>
+#include <features.h>
+
+/* This routine is jumped to by all the syscall handlers, to stash
+ * an error number into errno. */
+int __syscall_error(int err_no) attribute_hidden;
+int __syscall_error(int err_no)
+{
+ __set_errno(-err_no);
+ return -1;
+}
diff --git a/libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h b/libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h
index ea767abbf..321d699b0 100644
--- a/libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h
+++ b/libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h
@@ -6,8 +6,7 @@
#define _BITS_UCLIBC_ARCH_FEATURES_H
/* instruction used when calling abort() to kill yourself */
-/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/
-#undef __UCLIBC_ABORT_INSTRUCTION__
+#define __UCLIBC_ABORT_INSTRUCTION__ "brki r0, -1"
/* can your target use syscall6() for mmap ? */
#define __UCLIBC_MMAP_HAS_6_ARGS__
diff --git a/libc/sysdeps/linux/microblaze/clone.S b/libc/sysdeps/linux/microblaze/clone.S
index 46d4fe6b4..69c20453f 100644
--- a/libc/sysdeps/linux/microblaze/clone.S
+++ b/libc/sysdeps/linux/microblaze/clone.S
@@ -23,6 +23,10 @@
#define _ERRNO_H 1
#include <bits/errno.h>
+#if defined __UCLIBC_HAS_THREADS__ && !defined __UCLIBC_HAS_LINUXTHREADS__
+#include <sysdep-cancel.h>
+#endif
+
/* int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg,
pid_t *ptid, struct user_desc *tls, pid_t *ctid);
@@ -39,8 +43,8 @@
.text
ENTRY (__clone)
addik r3,r0,-EINVAL
- beqi r5,1f ; // Invalid func
- beqi r6,1f ; // Invalid stack
+ beqi r5,SYSCALL_ERROR_LABEL ; // Invalid func
+ beqi r6,SYSCALL_ERROR_LABEL ; // Invalid stack
addik r6,r6,-8
swi r5,r6,0 ; // Push fn onto child's stack
swi r8,r6,4 ; // Push arg for child
@@ -53,7 +57,7 @@ ENTRY (__clone)
addk r0,r0,r0
addik r4,r0,-4095
cmpu r4,r4,r3
- bgei r4,1f
+ bgei r4,SYSCALL_ERROR_LABEL
beqi r3,L(thread_start)
rtsd r15,8
nop
@@ -67,12 +71,7 @@ L(thread_start):
addik r12,r0,SYS_ify(exit)
brki r14,8
nop
-
-1: rsubk r3,r3,r0
- rtsd r15,8
- addik r3,r0,-1 /* delay slot. */
-
-END(__clone)
+PSEUDO_END(__clone)
libc_hidden_def (__clone)
weak_alias (__clone,clone)
diff --git a/libc/sysdeps/linux/microblaze/jmpbuf-offsets.h b/libc/sysdeps/linux/microblaze/jmpbuf-offsets.h
deleted file mode 100644
index c6cccc739..000000000
--- a/libc/sysdeps/linux/microblaze/jmpbuf-offsets.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
- * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
-#define JB_SIZE (4 * 18)
diff --git a/libc/sysdeps/linux/microblaze/jmpbuf-unwind.h b/libc/sysdeps/linux/microblaze/jmpbuf-unwind.h
index 2c1c0793c..155792b37 100644
--- a/libc/sysdeps/linux/microblaze/jmpbuf-unwind.h
+++ b/libc/sysdeps/linux/microblaze/jmpbuf-unwind.h
@@ -10,3 +10,28 @@
containing a local variable at ADDRESS. */
#define _JMPBUF_UNWINDS(jmpbuf, address) \
((void *) (address) < (void *) (jmpbuf)[0].__sp)
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <stdint.h>
+#include <unwind.h>
+
+/* Test if longjmp to JMPBUF would unwind the frame
+ containing a local variable at ADDRESS. */
+#undef _JMPBUF_UNWINDS
+#define _JMPBUF_UNWINDS(jmpbuf, address) \
+ ((void *) (address) < (void *) (jmpbuf)[0].__sp)
+
+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+ _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+
+static inline uintptr_t __attribute__ ((unused))
+_jmpbuf_sp (__jmp_buf regs)
+{
+ void *sp = (void *) regs[0].__sp;
+ return (uintptr_t) sp;
+}
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+ ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
+
+#endif
diff --git a/libc/sysdeps/linux/microblaze/sysdep.h b/libc/sysdeps/linux/microblaze/sysdep.h
index 1f01a2a1d..a463d339e 100644
--- a/libc/sysdeps/linux/microblaze/sysdep.h
+++ b/libc/sysdeps/linux/microblaze/sysdep.h
@@ -1,9 +1,25 @@
+/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
#include <common/sysdep.h>
#ifdef __ASSEMBLER__
-/* Syntactic details of assembler. */
-
# define ALIGNARG(log2) log2
# define ASM_SIZE_DIRECTIVE(name) .size name,.-name
@@ -22,4 +38,67 @@
# define L(name) $L##name
# endif
+/* We don't want the label for the error handler to be visible in the symbol
+ table when we define it here. */
+# ifdef __PIC__
+# define SYSCALL_ERROR_LABEL 0f
+# else
+# define SYSCALL_ERROR_LABEL __syscall_error
+# endif
+
+# define DO_CALL(syscall_name, args) \
+ addik r12,r0,SYS_ify (syscall_name); \
+ brki r14,8; \
+ addk r0,r0,r0;
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+ .text; \
+ ENTRY (name) \
+ DO_CALL (syscall_name, args); \
+ addik r12,r0,-4095; \
+ cmpu r12,r12,r3; \
+ bgei r12,SYSCALL_ERROR_LABEL;
+
+# undef PSEUDO_END
+# define PSEUDO_END(name) \
+ SYSCALL_ERROR_HANDLER; \
+ END (name)
+
+#ifdef __PIC__
+# define SYSCALL_ERROR_LABEL_DCL 0
+# if defined _LIBC_REENTRANT
+# define SYSCALL_ERROR_HANDLER \
+SYSCALL_ERROR_LABEL_DCL: \
+ addik r1,r1,-16; \
+ swi r15,r1,0; \
+ swi r20,r1,8; \
+ rsubk r3,r3,r0; \
+ swi r3,r1,12; \
+ mfs r20,rpc; \
+ addik r20,r20,_GLOBAL_OFFSET_TABLE_+8; \
+ brlid r15,__errno_location@PLT; \
+ nop; \
+ lwi r4,r1,12; \
+ swi r4,r3,0; \
+ lwi r20,r1,8; \
+ lwi r15,r1,0; \
+ addik r1,r1,16; \
+ rtsd r15,8; \
+ addik r3,r0,-1;
+# else /* !_LIBC_REENTRANT. */
+# define SYSCALL_ERROR_HANDLER \
+SYSCALL_ERROR_LABEL_DCL: \
+ mfs r12,rpc; \
+ addik r12,r12,_GLOBAL_OFFSET_TABLE_+8; \
+ lwi r12,r12,errno@GOT; \
+ rsubk r3,r3,r0; \
+ swi r3,r12,0; \
+ rtsd r15,8; \
+ addik r3,r0,-1;
+# endif /* _LIBC_REENTRANT. */
+#else
+# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
+#endif /* PIC. */
+
#endif
diff --git a/libc/sysdeps/linux/microblaze/vfork.S b/libc/sysdeps/linux/microblaze/vfork.S
index cadd1167d..11b9e2758 100644
--- a/libc/sysdeps/linux/microblaze/vfork.S
+++ b/libc/sysdeps/linux/microblaze/vfork.S
@@ -1,42 +1,44 @@
-/*
- * libc/sysdeps/linux/microblaze/vfork.S -- `vfork' syscall for linux/microblaze
- *
- * Copyright (C) 2003 John Williams <jwilliams@itee.uq.edu.au>
- * Copyright (C) 2001 NEC Corporation
- * Copyright (C) 2001 Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU Lesser
- * General Public License. See the file COPYING.LIB in the main
- * directory of this archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- * Microblaze port by John Williams
- */
-
-#include <sys/syscall.h>
+/* Copyright (C) 2005-2016 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#define _ERRNO_H 1
+#include <bits/errno.h>
/* Clone the calling process, but without copying the whole address space.
The calling process is suspended until the new process exits or is
replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
and the process ID of the new process to the old process. */
- .globl __vfork
- .hidden __vfork
- .align 4
-__vfork:
- addi r12, r0, SYS_vfork
- brki r14, 0x08;
- addi r4, r3, 125 /* minimum err value */
- blti r4, 1f /* is r3 < -125? */
- bri 2f /* normal return */
+ENTRY(__vfork)
+
+ DO_CALL (vfork, 0)
+ addik r12,r0,-4095
+ cmpu r12,r12,r3
+ bgei r12,1f
+ rtsd r15,8
+ nop
1: rsubk r3,r3,r0
rtsd r15,8
addik r3,r0,-1 /* delay slot. */
-2: rtsd r15, 8 /* error return */
- nop
- .size __vfork, .-__vfork
+END(__vfork)
weak_alias(__vfork, vfork)
libc_hidden_def(vfork)