From 23bb649090ff588e8642f0c581cfe7ce2d29c757 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Sat, 16 Dec 2017 21:01:39 +0100 Subject: 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. --- libc/sysdeps/linux/common/libgcc_s.h | 4 ++ libc/sysdeps/linux/m68k/Makefile.arch | 3 +- libc/sysdeps/linux/m68k/clone.S | 108 +++++++++++++++++++++++--------- libc/sysdeps/linux/m68k/jmpbuf-unwind.h | 39 ++++++++++-- libc/sysdeps/linux/m68k/m68k_read_tp.S | 1 + libc/sysdeps/linux/m68k/sys/reg.h | 101 +++++++++++++++++++++++++++++ libc/sysdeps/linux/m68k/sysdep.h | 26 ++++++++ libc/sysdeps/linux/m68k/vfork.S | 30 ++++----- 8 files changed, 258 insertions(+), 54 deletions(-) create mode 100644 libc/sysdeps/linux/m68k/m68k_read_tp.S create mode 100644 libc/sysdeps/linux/m68k/sys/reg.h create mode 100644 libc/sysdeps/linux/m68k/sysdep.h (limited to 'libc') 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 + . */ /* 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 #include #include #include #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 - * - * 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 + . */ #include @@ -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 +#include + +#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 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 + . */ + +#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 + +#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) -- cgit v1.2.3