From 191739597c6d380692885cfdd8dd8aa4f31f029d Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Mon, 31 Oct 2016 18:05:44 +0100 Subject: microblaze: add NPTL/TLS support from GNU libc Not perfect, but a starting point. Some tests of the test suite are failing. --- libc/sysdeps/linux/microblaze/Makefile.arch | 2 +- libc/sysdeps/linux/microblaze/__syscall_error.c | 18 +++++ .../linux/microblaze/bits/uClibc_arch_features.h | 3 +- libc/sysdeps/linux/microblaze/clone.S | 17 +++-- libc/sysdeps/linux/microblaze/jmpbuf-offsets.h | 6 -- libc/sysdeps/linux/microblaze/jmpbuf-unwind.h | 25 +++++++ libc/sysdeps/linux/microblaze/sysdep.h | 83 +++++++++++++++++++++- libc/sysdeps/linux/microblaze/vfork.S | 58 +++++++-------- 8 files changed, 164 insertions(+), 48 deletions(-) create mode 100644 libc/sysdeps/linux/microblaze/__syscall_error.c delete mode 100644 libc/sysdeps/linux/microblaze/jmpbuf-offsets.h (limited to 'libc') 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 + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* 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 +#if defined __UCLIBC_HAS_THREADS__ && !defined __UCLIBC_HAS_LINUXTHREADS__ +#include +#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 - * - * 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 +#include + +/* 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 + . */ + #include #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 - * Copyright (C) 2001 NEC Corporation - * Copyright (C) 2001 Miles Bader - * - * 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 - * Microblaze port by John Williams - */ - -#include +/* 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 + . */ + +#include +#define _ERRNO_H 1 +#include /* 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) -- cgit v1.2.3