diff options
Diffstat (limited to 'libc/sysdeps/linux')
| -rw-r--r-- | libc/sysdeps/linux/hppa/Makefile.arch | 2 | ||||
| -rw-r--r-- | libc/sysdeps/linux/hppa/bits/ioctls.h | 35 | ||||
| -rw-r--r-- | libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h | 2 | ||||
| -rw-r--r-- | libc/sysdeps/linux/hppa/clone.S | 154 | ||||
| -rw-r--r-- | libc/sysdeps/linux/hppa/sysdep.h | 356 | ||||
| -rw-r--r-- | libc/sysdeps/linux/hppa/vfork.S | 82 | 
6 files changed, 566 insertions, 65 deletions
diff --git a/libc/sysdeps/linux/hppa/Makefile.arch b/libc/sysdeps/linux/hppa/Makefile.arch index 621a5b314..90cf5a4bc 100644 --- a/libc/sysdeps/linux/hppa/Makefile.arch +++ b/libc/sysdeps/linux/hppa/Makefile.arch @@ -8,4 +8,4 @@  CSRC-y := __syscall_error.c brk.c syscall.c  SSRC-y := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S \ -	add_n.s lshift.s rshift.s sub_n.s udiv_qrnnd.s +	add_n.s lshift.s rshift.s sub_n.s udiv_qrnnd.s vfork.S diff --git a/libc/sysdeps/linux/hppa/bits/ioctls.h b/libc/sysdeps/linux/hppa/bits/ioctls.h new file mode 100644 index 000000000..99ecb0ff1 --- /dev/null +++ b/libc/sysdeps/linux/hppa/bits/ioctls.h @@ -0,0 +1,35 @@ +/* Copyright (C) 1996-2018 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/>.  */ + +#ifndef _SYS_IOCTL_H +# error "Never use <bits/ioctls.h> directly; include <sys/ioctl.h> instead." +#endif + +/* Use the definitions from the kernel header files.  */ +#include <asm/ioctls.h> + +/* Oh well, this is necessary since the kernel data structure is +   different from the user-level version.  */ +#undef  TCGETS +#undef  TCSETS +#undef  TCSETSW +#undef  TCSETSF +#define TCGETS	_IOR ('T', 16, char[36]) +#define TCSETS	_IOW ('T', 17, char[36]) +#define TCSETSW	_IOW ('T', 18, char[36]) +#define TCSETSF	_IOW ('T', 19, char[36]) + +#include <linux/sockios.h> diff --git a/libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h b/libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h index 19fa05109..1c096bd17 100644 --- a/libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h +++ b/libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h @@ -30,7 +30,7 @@  #undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__  /* define if target supports CFI pseudo ops */ -#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ +#define __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__  /* define if target supports IEEE signed zero floats */  #define __UCLIBC_HAVE_SIGNED_ZERO__ diff --git a/libc/sysdeps/linux/hppa/clone.S b/libc/sysdeps/linux/hppa/clone.S index f6c153b01..8356d9a74 100644 --- a/libc/sysdeps/linux/hppa/clone.S +++ b/libc/sysdeps/linux/hppa/clone.S @@ -1,5 +1,4 @@ -/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. -   This file is part of the GNU C Library. +/* Copyright (C) 1996-2018 Free Software Foundation, Inc.     Contributed by David Huggins-Daines <dhd@debian.org>, 2000.     Based on the Alpha version by Richard Henderson <rth@tamu.edu>, 1996. @@ -14,27 +13,35 @@     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 +   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.  */  #include <asm/unistd.h> +#include <sysdep.h>  #define _ERRNO_H	1  #include <bits/errno.h> -#include <sys/syscall.h>  /* Non-thread code calls __clone with the following parameters: -   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) +     NPTL Code will call __clone with the following parameters: -   int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, -	     int *parent_tidptr, struct user_desc *newtls, int *child_pidptr) -	 +   int clone(int (*fn)(void *arg), +	     void *child_stack, +	     int flags, +	     void *arg, +	     int *parent_tidptr, +	     struct user_desc *newtls, +	     int *child_pidptr) +     The code should not mangle the extra input registers.     Syscall expects:				Input to __clone: -	4(r25) - function pointer 		(r26, arg0)  +	4(r25) - function pointer 		(r26, arg0)  	0(r25) - argument			(r23, arg3)  	r26 - clone flags.			(r24, arg2)  	r25+64 - user stack pointer.		(r25, arg1) @@ -42,93 +49,114 @@  	r23 - struct user_desc newtls pointer.	(stack - 56)  	r22 - child tid pointer.		(stack - 60)  	r20 - clone syscall number		(constant) + +   Return: + +	On success the thread ID of the child process is returend in +	the callers context. +	On error return -1, and set errno to the value returned by +	the syscall.   */ -.text -.global __clone -.type   __clone,%function -__clone: +        .text +ENTRY(__clone) +	/* Prologue */ +	stwm	%r4, 64(%sp) +	.cfi_def_cfa_offset -64 +	.cfi_offset 4, 0 +	stw	%sp, -4(%sp) +#ifdef __PIC__ +	stw	%r19, -32(%sp) +	.cfi_offset 19, 32 +#endif  	/* Sanity check arguments.  */ -	ldi     -EINVAL,%ret0 -	comib,=,n  0,%arg0,.Lerror        /* no NULL function pointers */ -	comib,=,n  0,%arg1,.Lerror        /* no NULL stack pointers */ +	comib,=,n  0, %arg0, .LerrorSanity        /* no NULL function pointers */ +	comib,=,n  0, %arg1, .LerrorSanity        /* no NULL stack pointers */ -	/* Save the fn ptr and arg on the new stack.  */ -	stwm    %r26,64(%r25) -	stw	%r23,-60(%r25) +	/* Save the function pointer, arg, and flags on the new stack.  */ +	stwm    %r26, 64(%r25) +	stw	%r23, -60(%r25) +	stw     %r24, -56(%r25)  	/* Clone arguments are (int flags, void * child_stack) */ -	copy	%r24,%r26	/* flags are first */ +	copy	%r24, %r26		/* flags are first */  	/* User stack pointer is in the correct register already */  	/* Load args from stack... */ -	ldw	-52(%sp), %r24	/* Load parent_tidptr */ -	ldw	-56(%sp), %r23 	/* Load newtls */ -	ldw	-60(%sp), %r22	/* Load child_tidptr */ - -	/* Create frame to get r3 free */ -	copy	%sp, %r21 -	stwm	%r3, 64(%sp) -	stw	%r21, -4(%sp) +	ldw	-116(%sp), %r24		/* Load parent_tidptr */ +	ldw	-120(%sp), %r23 	/* Load newtls */ +	ldw	-124(%sp), %r22		/* Load child_tidptr */  	/* Save the PIC register. */  #ifdef __PIC__ -	copy	%r19, %r3		/* parent */ +	copy	%r19, %r4		/* parent */  #endif  	/* Do the system call */ -	ble     0x100(%sr2,%r0) -	ldi	__NR_clone,%r20 +	ble     0x100(%sr2, %r0) +	ldi	__NR_clone, %r20 -	ldi	-4096,%r1 -	comclr,>>= %r1,%ret0,%r0	/* Note: unsigned compare. */ +	ldi	-4096, %r1 +	comclr,>>= %r1, %ret0, %r0	/* Note: unsigned compare. */  	b,n	.LerrorRest -	comib,=,n 0,%ret0,thread_start +	/* Restore the PIC register.  */ +#ifdef __PIC__ +	copy	%r4, %r19		/* parent */ +#endif + +	comib,=,n 0, %ret0, .LthreadStart  	/* Successful return from the parent -	   No need to restore the PIC register,  +	   No need to restore the PIC register,  	   since we return immediately. */ +	ldw	-84(%sp), %rp  	bv	%r0(%rp) -	ldwm	-64(%sp), %r3 +	ldwm	-64(%sp), %r4  .LerrorRest: -	/* Restore the PIC register on error */ -#ifdef __PIC__ -	copy	%r3, %r19		/* parent */  -#endif -  	/* Something bad happened -- no child created */ -.Lerror: - -	/* Set errno, save ret0 so we return with that value. */ -	copy	%ret0, %r3 -	b	__syscall_error -	sub     %r0,%ret0,%arg0 -	copy	%r3, %ret0 -	/* Return after setting errno, and restoring ret0 */ +	bl	__syscall_error, %rp +	sub     %r0, %ret0, %arg0 +	ldw	-84(%sp), %rp +	/* Return after setting errno, ret0 is set to -1 by __syscall_error. */  	bv	%r0(%rp) -	ldwm	-64(%sp), %r3 +	ldwm	-64(%sp), %r4 -thread_start: +.LerrorSanity: +	/* Sanity checks failed, return -1, and set errno to EINVAL. */ +	bl	__syscall_error, %rp +	ldi     EINVAL, %arg0 +	ldw	-84(%sp), %rp +	bv	%r0(%rp) +	ldwm	-64(%sp), %r4 +.LthreadStart:  	/* Load up the arguments.  */ -	ldw	-60(%sr0, %sp),%arg0 -	ldw     -64(%sr0, %sp),%r22 +	ldw	-60(%sp), %arg0 +	ldw     -64(%sp), %r22 -	/* $$dyncall fixes childs PIC register */ +	/* $$dyncall fixes child's PIC register */  	/* Call the user's function */ -	bl	$$dyncall,%r31 -	copy	%r31,%rp - -	bl	HIDDEN_JUMPTARGET(_exit),%rp -	copy	%ret0,%arg0 +#ifdef __PIC__ +	copy	%r19, %r4 +#endif +	bl	$$dyncall, %r31 +	copy	%r31, %rp +#ifdef __PIC__ +	copy	%r4, %r19 +#endif +	copy	%r28, %r26 +	ble     0x100(%sr2, %r0) +	ldi	__NR_exit, %r20 -	/* Die horribly.  */ -	iitlbp	%r0,(%sr0,%r0) +	/* We should not return from exit. +           We do not restore r4, or the stack state.  */ +	iitlbp	%r0, (%sr0, %r0) -.size clone,.-clone +PSEUDO_END(__clone) +libc_hidden_def (__clone)  weak_alias (__clone, clone) diff --git a/libc/sysdeps/linux/hppa/sysdep.h b/libc/sysdeps/linux/hppa/sysdep.h new file mode 100644 index 000000000..57b0cba9b --- /dev/null +++ b/libc/sysdeps/linux/hppa/sysdep.h @@ -0,0 +1,356 @@ +/* Assembler macros for PA-RISC. +   Copyright (C) 1999-2018 Free Software Foundation, Inc. +   Contributed by Ulrich Drepper, <drepper@cygnus.com>, August 1999. +   Linux/PA-RISC changes by Philipp Rumpf, <prumpf@tux.org>, March 2000. + +   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 _LINUX_HPPA_SYSDEP_H +#define _LINUX_HPPA_SYSDEP_H 1 + +#include <common/sysdep.h> +#include <sys/syscall.h> + +/* In order to get __set_errno() definition in INLINE_SYSCALL.  */ +#ifndef __ASSEMBLER__ +#include <errno.h> +#endif + +#undef ASM_LINE_SEP +#define ASM_LINE_SEP ! + +#undef SYS_ify +#define SYS_ify(syscall_name)	(__NR_##syscall_name) + +/* The vfork, fork, and clone syscalls clobber r19 + * and r21. We list r21 as either clobbered or as an + * input to a 6-argument syscall. We must save and + * restore r19 in both PIC and non-PIC cases. + */ +/* WARNING: TREG must be a callee saves register so +   that it doesn't have to be restored after a call +   to another function */ +#define TREG 4 +#define SAVE_PIC(SREG) \ +	copy %r19, SREG +#define LOAD_PIC(LREG) \ +	copy LREG , %r19 +/* Inline assembly defines */ +#define TREG_ASM "%r4" /* Cant clobber r3, it holds framemarker */ +#define SAVE_ASM_PIC	"       copy %%r19, %" TREG_ASM "\n" +#define LOAD_ASM_PIC	"       copy %" TREG_ASM ", %%r19\n" +#define CLOB_TREG	TREG_ASM , +#define PIC_REG_DEF	register unsigned long __r19 asm("r19"); +#define PIC_REG_USE	, "r" (__r19) + +#ifdef __ASSEMBLER__ + +/* Syntactic details of assembler.  */ + +#define ALIGNARG(log2) log2 + +/* For Linux we can use the system call table in the header file +	/usr/include/asm/unistd.h +   of the kernel.  But these symbols do not follow the SYS_* syntax +   so we have to redefine the `SYS_ify' macro here.  */ +#undef SYS_ify +#define SYS_ify(syscall_name)	__NR_##syscall_name + +/* ELF-like local names start with `.L'.  */ +#undef L +#define L(name)	.L##name + +/* Linux uses a negative return value to indicate syscall errors, +   unlike most Unices, which use the condition codes' carry flag. + +   Since version 2.1 the return value of a system call might be +   negative even if the call succeeded.  E.g., the `lseek' system call +   might return a large offset.  Therefore we must not anymore test +   for < 0, but test for a real error by making sure the value in %eax +   is a real error number.  Linus said he will make sure the no syscall +   returns a value in -1 .. -4095 as a valid result so we can safely +   test with -4095.  */ + +/* We don't want the label for the error handle to be global when we define +   it here.  */ +/*#ifdef PIC +# define SYSCALL_ERROR_LABEL 0f +#else +# define SYSCALL_ERROR_LABEL syscall_error +#endif*/ + +/* Argument manipulation from the stack for preparing to +   make a syscall */ + +#define DOARGS_0 /* nothing */ +#define DOARGS_1 /* nothing */ +#define DOARGS_2 /* nothing */ +#define DOARGS_3 /* nothing */ +#define DOARGS_4 /* nothing */ +#define DOARGS_5 ldw -52(%sp), %r22		ASM_LINE_SEP +#define DOARGS_6 DOARGS_5 ldw -56(%sp), %r21	ASM_LINE_SEP + +#define UNDOARGS_0 /* nothing */ +#define UNDOARGS_1 /* nothing */ +#define UNDOARGS_2 /* nothing */ +#define UNDOARGS_3 /* nothing */ +#define UNDOARGS_4 /* nothing */ +#define UNDOARGS_5 /* nothing */ +#define UNDOARGS_6 /* nothing */ + +/* 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.  */ +#undef ENTRY +#define	ENTRY(name)							\ +	.text						ASM_LINE_SEP	\ +	.align ALIGNARG(4)				ASM_LINE_SEP	\ +	.export C_SYMBOL_NAME(name)			ASM_LINE_SEP	\ +	.type	C_SYMBOL_NAME(name),@function		ASM_LINE_SEP	\ +	cfi_startproc					ASM_LINE_SEP	\ +	C_LABEL(name)					ASM_LINE_SEP	\ +	.PROC						ASM_LINE_SEP	\ +	.CALLINFO FRAME=64,CALLS,SAVE_RP,ENTRY_GR=3	ASM_LINE_SEP	\ +	.ENTRY						ASM_LINE_SEP	\ +	/* SAVE_RP says we do */			ASM_LINE_SEP	\ +	stw %rp, -20(%sr0,%sp)				ASM_LINE_SEP	\ +	.cfi_offset 2, -20				ASM_LINE_SEP	\ +	/*FIXME: Call mcount? (carefull with stack!) */ + +/* Some syscall wrappers do not call other functions, and +   hence are classified as leaf, so add NO_CALLS for gdb */ +#define	ENTRY_LEAF(name)						\ +	.text						ASM_LINE_SEP	\ +	.align ALIGNARG(4)				ASM_LINE_SEP	\ +	.export C_SYMBOL_NAME(name)			ASM_LINE_SEP	\ +	.type	C_SYMBOL_NAME(name),@function		ASM_LINE_SEP	\ +	cfi_startproc					ASM_LINE_SEP	\ +	C_LABEL(name)					ASM_LINE_SEP	\ +	.PROC						ASM_LINE_SEP	\ +	.CALLINFO FRAME=64,NO_CALLS,SAVE_RP,ENTRY_GR=3	ASM_LINE_SEP	\ +	.ENTRY						ASM_LINE_SEP	\ +	/* SAVE_RP says we do */			ASM_LINE_SEP	\ +	stw %rp, -20(%sr0,%sp)				ASM_LINE_SEP	\ +	.cfi_offset 2, -20				ASM_LINE_SEP	\ +	/*FIXME: Call mcount? (carefull with stack!) */ + +#undef	END +#define END(name)							\ +	.EXIT						ASM_LINE_SEP	\ +	.PROCEND					ASM_LINE_SEP	\ +	cfi_endproc					ASM_LINE_SEP	\ +.size	C_SYMBOL_NAME(name), .-C_SYMBOL_NAME(name)	ASM_LINE_SEP + +/* If compiled for profiling, call `mcount' at the start +   of each function. No, don't bother.  gcc will put the +   call in for us.  */ +#define CALL_MCOUNT		/* Do nothing.  */ + +/* syscall wrappers consist of +	#include <sysdep.h> +	PSEUDO(...) +	ret +	PSEUDO_END(...) + +   which means +	ENTRY(name) +	DO_CALL(...) +	bv,n 0(2) +*/ + +#undef PSEUDO +#define	PSEUDO(name, syscall_name, args)			\ +  ENTRY (name)					ASM_LINE_SEP	\ +  /* If necc. load args from stack */		ASM_LINE_SEP	\ +  DOARGS_##args					ASM_LINE_SEP	\ +  DO_CALL (syscall_name, args)			ASM_LINE_SEP	\ +  UNDOARGS_##args				ASM_LINE_SEP + +#define ret \ +  /* Return value set by ERRNO code */		ASM_LINE_SEP	\ +  bv,n 0(2)					ASM_LINE_SEP + +#undef	PSEUDO_END +#define	PSEUDO_END(name)					\ +  END (name) + +/* We don't set the errno on the return from the syscall */ +#define	PSEUDO_NOERRNO(name, syscall_name, args)		\ +  ENTRY_LEAF (name)				ASM_LINE_SEP	\ +  DOARGS_##args					ASM_LINE_SEP	\ +  DO_CALL_NOERRNO (syscall_name, args)		ASM_LINE_SEP	\ +  UNDOARGS_##args				ASM_LINE_SEP + +#define ret_NOERRNO ret + +#undef	PSEUDO_END_NOERRNO +#define	PSEUDO_END_NOERRNO(name)				\ +  END (name) + +/* This has to return the error value */ +#undef  PSEUDO_ERRVAL +#define PSEUDO_ERRVAL(name, syscall_name, args)			\ +  ENTRY_LEAF (name)				ASM_LINE_SEP	\ +  DOARGS_##args					ASM_LINE_SEP	\ +  DO_CALL_ERRVAL (syscall_name, args)		ASM_LINE_SEP	\ +  UNDOARGS_##args				ASM_LINE_SEP + +#define ret_ERRVAL ret + +#undef	PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name)					\ +	END(name) + +#undef JUMPTARGET +#define JUMPTARGET(name)	name +#define SYSCALL_PIC_SETUP	/* Nothing.  */ + + +/* FIXME: This comment is not true. + * All the syscall assembly macros rely on finding the appropriate +   SYSCALL_ERROR_LABEL or rather HANDLER. */ + +/* int * __errno_location(void) so you have to store your value +   into the return address! */ +#define DEFAULT_SYSCALL_ERROR_HANDLER			\ +	.import __errno_location,code	ASM_LINE_SEP	\ +	/* branch to errno handler */	ASM_LINE_SEP	\ +	bl __errno_location,%rp		ASM_LINE_SEP + +/* Here are the myriad of configuration options that the above can +   work for... what we've done is provide the framework for future +   changes if required to each section */ + +#ifdef __PIC__ +#  if defined _LIBC_REENTRANT +#   define SYSCALL_ERROR_HANDLER DEFAULT_SYSCALL_ERROR_HANDLER +#  else /* !_LIBC_REENTRANT */ +#   define SYSCALL_ERROR_HANDLER DEFAULT_SYSCALL_ERROR_HANDLER +#  endif /* _LIBC_REENTRANT */ +#else +# ifndef _LIBC_REENTRANT +#  define SYSCALL_ERROR_HANDLER DEFAULT_SYSCALL_ERROR_HANDLER +# else +#  define SYSCALL_ERROR_HANDLER DEFAULT_SYSCALL_ERROR_HANDLER +# endif +#endif + + +/* Linux takes system call arguments in registers: +	syscall number	gr20 +	arg 1		gr26 +	arg 2		gr25 +	arg 3		gr24 +	arg 4		gr23 +	arg 5		gr22 +	arg 6		gr21 + +   The compiler calls us by the C convention: +	syscall number	in the DO_CALL macro +	arg 1		gr26 +	arg 2		gr25 +	arg 3		gr24 +	arg 4		gr23 +	arg 5		-52(sp) +	arg 6		-56(sp) + +   gr22 and gr21 are caller-saves, so we can just load the arguments +   there and generally be happy. */ + +/* the cmpb...no_error code below inside DO_CALL + * is intended to mimic the if (__sys_res...) + * code inside INLINE_SYSCALL + */ +#define NO_ERROR -0x1000 + +#undef	DO_CALL +#define DO_CALL(syscall_name, args)				\ +	/* Create a frame */			ASM_LINE_SEP	\ +	stwm TREG, 64(%sp)			ASM_LINE_SEP	\ +	.cfi_def_cfa_offset -64			ASM_LINE_SEP	\ +	.cfi_offset TREG, 0			ASM_LINE_SEP	\ +	stw %sp, -4(%sp)			ASM_LINE_SEP	\ +	stw %r19, -32(%sp)			ASM_LINE_SEP	\ +	.cfi_offset 19, 32			ASM_LINE_SEP	\ +	/* Save r19 */				ASM_LINE_SEP	\ +	SAVE_PIC(TREG)				ASM_LINE_SEP	\ +	/* Do syscall, delay loads # */		ASM_LINE_SEP	\ +	ble  0x100(%sr2,%r0)			ASM_LINE_SEP	\ +	ldi SYS_ify (syscall_name), %r20	ASM_LINE_SEP	\ +	ldi NO_ERROR,%r1			ASM_LINE_SEP	\ +	cmpb,>>=,n %r1,%ret0,L(pre_end)		ASM_LINE_SEP	\ +	/* Restore r19 from TREG */		ASM_LINE_SEP	\ +	LOAD_PIC(TREG) /* delay */		ASM_LINE_SEP	\ +	SYSCALL_ERROR_HANDLER			ASM_LINE_SEP	\ +	/* Use TREG for temp storage */		ASM_LINE_SEP	\ +	copy %ret0, TREG /* delay */		ASM_LINE_SEP	\ +	/* OPTIMIZE: Don't reload r19 */	ASM_LINE_SEP	\ +	/* do a -1*syscall_ret0 */		ASM_LINE_SEP	\ +	sub %r0, TREG, TREG			ASM_LINE_SEP	\ +	/* Store into errno location */		ASM_LINE_SEP	\ +	stw TREG, 0(%sr0,%ret0)			ASM_LINE_SEP	\ +	/* return -1 as error */		ASM_LINE_SEP	\ +	ldo -1(%r0), %ret0			ASM_LINE_SEP	\ +L(pre_end):					ASM_LINE_SEP	\ +	/* Restore our frame, restoring TREG */	ASM_LINE_SEP	\ +	ldwm -64(%sp), TREG			ASM_LINE_SEP	\ +	/* Restore return pointer */		ASM_LINE_SEP	\ +	ldw -20(%sp),%rp			ASM_LINE_SEP + +/* We do nothing with the return, except hand it back to someone else */ +#undef  DO_CALL_NOERRNO +#define DO_CALL_NOERRNO(syscall_name, args)			\ +	/* No need to store r19 */		ASM_LINE_SEP	\ +	ble  0x100(%sr2,%r0)                    ASM_LINE_SEP    \ +	ldi SYS_ify (syscall_name), %r20        ASM_LINE_SEP    \ +	/* Caller will restore r19 */		ASM_LINE_SEP + +/* Here, we return the ERRVAL in assembly, note we don't call the +   error handler function, but we do 'negate' the return _IF_ +   it's an error. Not sure if this is the right semantic. */ + +#undef	DO_CALL_ERRVAL +#define DO_CALL_ERRVAL(syscall_name, args)			\ +	/* No need to store r19 */		ASM_LINE_SEP	\ +	ble  0x100(%sr2,%r0)			ASM_LINE_SEP	\ +	ldi SYS_ify (syscall_name), %r20	ASM_LINE_SEP	\ +	/* Caller will restore r19 */		ASM_LINE_SEP	\ +	ldi NO_ERROR,%r1			ASM_LINE_SEP	\ +	cmpb,>>=,n %r1,%ret0,0f			ASM_LINE_SEP	\ +	sub %r0, %ret0, %ret0			ASM_LINE_SEP	\ +0:						ASM_LINE_SEP + + +#else + +/* GCC has to be warned that a syscall may clobber all the ABI +   registers listed as "caller-saves", see page 8, Table 2 +   in section 2.2.6 of the PA-RISC RUN-TIME architecture +   document. However! r28 is the result and will conflict with +   the clobber list so it is left out. Also the input arguments +   registers r20 -> r26 will conflict with the list so they +   are treated specially. Although r19 is clobbered by the syscall +   we cannot say this because it would violate ABI, thus we say +   TREG is clobbered and use that register to save/restore r19 +   across the syscall. */ + +#define CALL_CLOB_REGS	"%r1", "%r2", CLOB_TREG \ +			"%r20", "%r29", "%r31" + +#endif	/* __ASSEMBLER__ */ + +#endif /* _LINUX_HPPA_SYSDEP_H */ diff --git a/libc/sysdeps/linux/hppa/vfork.S b/libc/sysdeps/linux/hppa/vfork.S new file mode 100644 index 000000000..9d0706361 --- /dev/null +++ b/libc/sysdeps/linux/hppa/vfork.S @@ -0,0 +1,82 @@ +/* Copyright (C) 2005-2018 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 <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.  */ + +.Lthread_start:						ASM_LINE_SEP + +	/* r26, r25, r24, r23 are free since vfork has no arguments */ +ENTRY(__vfork) +	/* We must not create a frame. When the child unwinds to call +	   exec it will clobber the same frame that the parent +	   needs to unwind.  */ + +	/* Save the PIC register. */ +#ifdef __PIC__ +	copy	%r19, %r25	/* parent */ +#endif + +	/* Syscall saves and restores all register states */ +	ble	0x100(%sr2,%r0) +	ldi	__NR_vfork,%r20 + +	/* Check for error */ +	ldi	-4096,%r1 +	comclr,>>= %r1,%ret0,%r0        /* Note: unsigned compare. */ +	b,n	.Lerror + +	/* Return, and DO NOT restore rp. The child may have called +	   functions that updated the frame's rp. This works because +	   the kernel ensures rp is preserved across the vfork +	   syscall.  */ +	bv,n	%r0(%rp) + +.Lerror: +	/* Now we need a stack to call a function. We are assured +	   that there is no child now, so it's safe to create +	   a frame.  */ +	stw	%rp, -20(%sp) +	.cfi_offset 2, -20 +	stwm	%r3, 64(%sp) +	.cfi_def_cfa_offset -64 +	.cfi_offset 3, 0 +	stw	%sp, -4(%sp) + +	sub	%r0,%ret0,%r3 +	SYSCALL_ERROR_HANDLER +	/* Restore the PIC register (in delay slot) on error */ +#ifdef __PIC__ +	copy	%r25, %r19    /* parent */ +#else +	nop +#endif +	/* Write syscall return into errno location */ +	stw	%r3, 0(%ret0) +	ldw	-84(%sp), %rp +	bv	%r0(%rp) +	ldwm	-64(%sp), %r3 + +PSEUDO_END (__vfork) +libc_hidden_def(vfork) + +weak_alias (__vfork, vfork)  | 
