summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@uclibc-ng.org>2017-12-16 21:01:39 +0100
committerWaldemar Brodkorb <wbx@uclibc-ng.org>2017-12-31 11:12:07 +0100
commit23bb649090ff588e8642f0c581cfe7ce2d29c757 (patch)
tree4a68d696415fce9f2dd50edf27a79bacbde3fc50 /libc
parent604781391549faafc59516700d9439ab1a7ec19b (diff)
m68k: add NPTL/TLS support
Port over NPTL/TLS support from GNU C Library. In the first step only the slower syscall is used for TLS access. The uClibc-ng testsuite shows 79 errors, so their is room for bugfixes and improvements.
Diffstat (limited to 'libc')
-rw-r--r--libc/sysdeps/linux/common/libgcc_s.h4
-rw-r--r--libc/sysdeps/linux/m68k/Makefile.arch3
-rw-r--r--libc/sysdeps/linux/m68k/clone.S108
-rw-r--r--libc/sysdeps/linux/m68k/jmpbuf-unwind.h39
-rw-r--r--libc/sysdeps/linux/m68k/m68k_read_tp.S1
-rw-r--r--libc/sysdeps/linux/m68k/sys/reg.h101
-rw-r--r--libc/sysdeps/linux/m68k/sysdep.h26
-rw-r--r--libc/sysdeps/linux/m68k/vfork.S30
8 files changed, 258 insertions, 54 deletions
diff --git a/libc/sysdeps/linux/common/libgcc_s.h b/libc/sysdeps/linux/common/libgcc_s.h
index e74a1034c..bf43d78a7 100644
--- a/libc/sysdeps/linux/common/libgcc_s.h
+++ b/libc/sysdeps/linux/common/libgcc_s.h
@@ -1,2 +1,6 @@
/* Name of libgcc_s library provided by gcc. */
+#if defined(__m68k__)
+#define LIBGCC_S_SO "libgcc_s.so.2"
+#else
#define LIBGCC_S_SO "libgcc_s.so.1"
+#endif
diff --git a/libc/sysdeps/linux/m68k/Makefile.arch b/libc/sysdeps/linux/m68k/Makefile.arch
index 88caa116f..191791aef 100644
--- a/libc/sysdeps/linux/m68k/Makefile.arch
+++ b/libc/sysdeps/linux/m68k/Makefile.arch
@@ -7,4 +7,5 @@
CSRC-y := brk.c __syscall_error.c
-SSRC-y := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S vfork.S
+SSRC-y := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S vfork.S \
+ m68k_read_tp.S
diff --git a/libc/sysdeps/linux/m68k/clone.S b/libc/sysdeps/linux/m68k/clone.S
index 7eddff10c..24071235b 100644
--- a/libc/sysdeps/linux/m68k/clone.S
+++ b/libc/sysdeps/linux/m68k/clone.S
@@ -1,54 +1,94 @@
-/* Adapted from glibc */
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. */
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+ Contributed by Andreas Schwab (schwab@issan.informatik.uni-dortmund.de)
+
+ 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/>. */
/* clone is even more special than fork as it mucks with stacks
and invokes a function in the right context after its all over. */
#define _ERRNO_H
+#include <sysdep.h>
#include <features.h>
#include <bits/errno.h>
#include <sys/syscall.h>
#include "m68k_pic.S"
-/* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+ void *parent_tidptr, void *tls, void *child_tidptr) */
-.text
-.align 4
-.type clone,@function
-.globl clone;
-clone:
+ .text
+ .align 4
+ .globl __clone
+ .type __clone,@function
+
+__clone:
/* Sanity check arguments. */
- movel #-EINVAL, %d0
- movel 4(%sp), %d1 /* no NULL function pointers */
- movel %d1, %a0
- tstl %d1
+ movel #-EINVAL, %d0
+ movel 4(%sp), %a0 /* no NULL function pointers */
+ tstl %a0
beq.w __syscall_error_trampoline
- movel 8(%sp), %d1 /* no NULL stack pointers */
- movel %d1, %a1
- tstl %d1
+ movel 8(%sp), %a1 /* no NULL stack pointers */
+ tstl %a1
beq.w __syscall_error_trampoline
/* Allocate space and copy the argument onto the new stack. */
movel 16(%sp), -(%a1)
/* Do the system call */
-#if 1 /* defined (CONFIG_COLDFIRE) */
- movel %d2, %d1 /* save %d2 and get stack pointer */
- movel %a1, %d2
- movel %d1, %a1
+ movel 12(%sp), %d1 /* get flags */
+ movel %d3, -(%a1) /* save %d3 and get parent_tidptr */
+ movel %d3, -(%sp)
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (%d3, 0)
+ movel 20+4(%sp), %d3
+ movel %d4, -(%a1) /* save %d4 and get child_tidptr */
+ movel %d4, -(%sp)
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (%d4, 0)
+ movel 28+8(%sp), %d4
+ movel %d5, -(%a1) /* save %d5 and get tls */
+ movel %d5, -(%sp)
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (%d5, 0)
+ movel 24+12(%sp), %d5
+ /* save %d2 and get stack pointer */
+#ifdef __mcoldfire__
+ movel %d2, -(%a1)
+ movel %d2, -(%sp)
+ cfi_adjust_cfa_offset (4)
+ cfi_rel_offset (%d2, 0)
+ movel %a1, %d2
#else
- exg %d2, %a1 /* save %d2 and get stack pointer */
+ exg %d2, %a1 /* save %d2 and get stack pointer */
+ cfi_register (%d2, %a1)
#endif
- movel 12(%sp), %d1 /* get flags */
movel #__NR_clone, %d0
+
+ /* End FDE now, because in the child the unwind info will be
+ wrong. */
+ cfi_endproc
+
trap #0
-#if 1 /* defined (CONFIG_COLDFIRE) */
- movel %d2, %d1 /* restore %d2 */
- movel %a1, %d2
- movel %d1, %a1
+#ifdef __mcoldfire__
+ movel (%sp)+, %d2
#else
- exg %d2, %a1 /* restore %d2 */
+ exg %d2, %a1 /* restore %d2 */
#endif
+ movel (%sp)+, %d5 /* restore %d5, %d4 and %d3 */
+ movel (%sp)+, %d4
+ movel (%sp)+, %d3
tstl %d0
bmi.w __syscall_error_trampoline
@@ -57,13 +97,21 @@ clone:
rts
thread_start:
- /*subl %fp, %fp*/ /* terminate the stack frame */
- jsr (%a0)
- movel %d0, -(%sp)
+ cfi_startproc
+ cfi_undefined (pc) /* Mark end of stack */
+ subl %fp, %fp /* terminate the stack frame */
+ jsr (%a0)
+ movel %d0, %d1
movel #__NR_exit, %d0
trap #0
- /*jsr exit*/
+ cfi_endproc
+
+ cfi_startproc
__syscall_error_trampoline:
JUMP __syscall_error,%a0
+.size __clone,.-__clone
+
+weak_alias(__clone,clone)
+libc_hidden_def(clone)
diff --git a/libc/sysdeps/linux/m68k/jmpbuf-unwind.h b/libc/sysdeps/linux/m68k/jmpbuf-unwind.h
index c5a8886e2..8744ec7e8 100644
--- a/libc/sysdeps/linux/m68k/jmpbuf-unwind.h
+++ b/libc/sysdeps/linux/m68k/jmpbuf-unwind.h
@@ -1,8 +1,19 @@
-/*
- * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
+/* Examine __jmp_buf for unwinding frames. m68k version.
+ Copyright (C) 2006-2017 Free Software Foundation, Inc.
+
+ 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 <setjmp.h>
@@ -10,3 +21,21 @@
containing a local variable at ADDRESS. */
#define _JMPBUF_UNWINDS(jmpbuf, address) \
((void *) (address) < (void *) (jmpbuf)->__aregs[5])
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <stdint.h>
+#include <unwind.h>
+
+#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)
+{
+ uintptr_t sp = (uintptr_t) regs[0].__sp;
+ return sp;
+}
+
+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+ ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
+#endif
diff --git a/libc/sysdeps/linux/m68k/m68k_read_tp.S b/libc/sysdeps/linux/m68k/m68k_read_tp.S
new file mode 100644
index 000000000..523e1b38a
--- /dev/null
+++ b/libc/sysdeps/linux/m68k/m68k_read_tp.S
@@ -0,0 +1 @@
+#include <ldso/ldso/m68k/m68k_read_tp.S>
diff --git a/libc/sysdeps/linux/m68k/sys/reg.h b/libc/sysdeps/linux/m68k/sys/reg.h
new file mode 100644
index 000000000..133c862b4
--- /dev/null
+++ b/libc/sysdeps/linux/m68k/sys/reg.h
@@ -0,0 +1,101 @@
+/* Copyright (C) 1998-2017 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/>. */
+
+#ifndef _SYS_REG_H
+#define _SYS_REG_H 1
+
+/* Index into an array of 4 byte integers returned from ptrace for
+ location of the users' stored general purpose registers. */
+
+enum
+{
+ PT_D1 = 0,
+#define PT_D1 PT_D1
+ PT_D2 = 1,
+#define PT_D2 PT_D2
+ PT_D3 = 2,
+#define PT_D3 PT_D3
+ PT_D4 = 3,
+#define PT_D4 PT_D4
+ PT_D5 = 4,
+#define PT_D5 PT_D5
+ PT_D6 = 5,
+#define PT_D6 PT_D6
+ PT_D7 = 6,
+#define PT_D7 PT_D7
+ PT_A0 = 7,
+#define PT_A0 PT_A0
+ PT_A1 = 8,
+#define PT_A1 PT_A1
+ PT_A2 = 9,
+#define PT_A2 PT_A2
+ PT_A3 = 10,
+#define PT_A3 PT_A3
+ PT_A4 = 11,
+#define PT_A4 PT_A4
+ PT_A5 = 12,
+#define PT_A5 PT_A5
+ PT_A6 = 13,
+#define PT_A6 PT_A6
+ PT_D0 = 14,
+#define PT_D0 PT_D0
+ PT_USP = 15,
+#define PT_USP PT_USP
+ PT_ORIG_D0 = 16,
+#define PT_ORIG_D0 PT_ORIG_D0
+ PT_SR = 17,
+#define PT_SR PT_SR
+ PT_PC = 18,
+#define PT_PC PT_PC
+
+#ifdef __mcoldfire__
+ PT_FP0 = 21,
+ PT_FP1 = 23,
+ PT_FP2 = 25,
+ PT_FP3 = 27,
+ PT_FP4 = 29,
+ PT_FP5 = 31,
+ PT_FP6 = 33,
+ PT_FP7 = 35,
+#else
+ PT_FP0 = 21,
+ PT_FP1 = 24,
+ PT_FP2 = 27,
+ PT_FP3 = 30,
+ PT_FP4 = 33,
+ PT_FP5 = 36,
+ PT_FP6 = 39,
+ PT_FP7 = 42,
+#endif
+#define PT_FP0 PT_FP0
+#define PT_FP1 PT_FP1
+#define PT_FP2 PT_FP2
+#define PT_FP3 PT_FP3
+#define PT_FP4 PT_FP4
+#define PT_FP5 PT_FP5
+#define PT_FP6 PT_FP6
+#define PT_FP7 PT_FP7
+
+ PT_FPCR = 45,
+#define PT_FPCR PT_FPCR
+ PT_FPSR = 46,
+#define PT_FPSR PT_FPSR
+ PT_FPIAR = 47
+#define PT_FPIAR PT_FPIAR
+};
+
+#endif /* _SYS_REG_H */
diff --git a/libc/sysdeps/linux/m68k/sysdep.h b/libc/sysdeps/linux/m68k/sysdep.h
new file mode 100644
index 000000000..9c18aae97
--- /dev/null
+++ b/libc/sysdeps/linux/m68k/sysdep.h
@@ -0,0 +1,26 @@
+#include <common/sysdep.h>
+
+#ifdef __ASSEMBLER__
+
+/* Define an entry point visible from C.
+
+ There is currently a bug in gdb which prevents us from specifying
+ incomplete stabs information. Fake some entries here which specify
+ the current source file. */
+# define ENTRY(name) \
+ .globl C_SYMBOL_NAME(name); \
+ .type C_SYMBOL_NAME(name),@function; \
+ .p2align 2; \
+ C_LABEL(name) \
+ cfi_startproc; \
+
+# undef END
+# define END(name) \
+ cfi_endproc; \
+ .size name,.-name
+
+/* Load the address of the GOT into register R. */
+# define LOAD_GOT(R) \
+ lea _GLOBAL_OFFSET_TABLE_@GOTPC (%pc), R
+
+#endif
diff --git a/libc/sysdeps/linux/m68k/vfork.S b/libc/sysdeps/linux/m68k/vfork.S
index bde9d5a3a..eb1639e37 100644
--- a/libc/sysdeps/linux/m68k/vfork.S
+++ b/libc/sysdeps/linux/m68k/vfork.S
@@ -10,8 +10,6 @@
#define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */
#endif
-#define IMM #
-
.text
.align 2
.globl __vfork
@@ -19,26 +17,22 @@
.type __vfork,@function
__vfork:
- movl %sp@+, %a1 /* save the return address for later */
- movl IMM __NR_vfork,%d0
+ /* Pop the return PC value into A0. */
+ movel %sp@+, %a0
+
+ /* Stuff the syscall number in D0 and trap into the kernel. */
+ movel #SYS_ify (vfork), %d0
trap #0
- movl %a1, -(%sp)
- cmpil #-4096,%d0
- blss 1f
+ tstl %d0
+ jmi .Lerror /* Branch forward if it failed. */
- neg.l %d0
-#ifndef __PIC__ /* needs handling as the other archs */
- movl errno, %a0
-#else
- movl errno@GOT(%a5), %a0
-#endif
- movl %d0, %a0@
- move.l #-1, %d0
+ /* Jump to the return PC. */
+ jmp %a0@
-1:
- move.l %d0, %a0
- rts
+.Lerror:
+ /* Push back the return PC. */
+ movel %a0,%sp@-
.size __vfork,.-__vfork
weak_alias(__vfork,vfork)