diff options
| -rw-r--r-- | arch/um/include/longjmp.h | 5 | ||||
| -rw-r--r-- | arch/um/include/sysdep-i386/archsetjmp.h | 19 | ||||
| -rw-r--r-- | arch/um/include/sysdep-x86_64/archsetjmp.h | 21 | ||||
| -rw-r--r-- | arch/um/os-Linux/process.c | 1 | ||||
| -rw-r--r-- | arch/um/os-Linux/skas/process.c | 3 | ||||
| -rw-r--r-- | arch/um/os-Linux/sys-i386/registers.c | 10 | ||||
| -rw-r--r-- | arch/um/os-Linux/sys-x86_64/registers.c | 10 | ||||
| -rw-r--r-- | arch/um/os-Linux/trap.c | 1 | ||||
| -rw-r--r-- | arch/um/os-Linux/uaccess.c | 3 | ||||
| -rw-r--r-- | arch/um/os-Linux/util.c | 5 | ||||
| -rw-r--r-- | arch/um/sys-i386/Makefile | 2 | ||||
| -rw-r--r-- | arch/um/sys-i386/setjmp.S | 58 | ||||
| -rw-r--r-- | arch/um/sys-x86_64/Makefile | 4 | ||||
| -rw-r--r-- | arch/um/sys-x86_64/setjmp.S | 54 | 
14 files changed, 173 insertions, 23 deletions
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h index 1b5c0131a12..e93c6d3e893 100644 --- a/arch/um/include/longjmp.h +++ b/arch/um/include/longjmp.h @@ -1,9 +1,12 @@  #ifndef __UML_LONGJMP_H  #define __UML_LONGJMP_H -#include <setjmp.h> +#include "sysdep/archsetjmp.h"  #include "os.h" +extern int setjmp(jmp_buf); +extern void longjmp(jmp_buf, int); +  #define UML_LONGJMP(buf, val) do { \  	longjmp(*buf, val);	\  } while(0) diff --git a/arch/um/include/sysdep-i386/archsetjmp.h b/arch/um/include/sysdep-i386/archsetjmp.h new file mode 100644 index 00000000000..ea1ba3d42ae --- /dev/null +++ b/arch/um/include/sysdep-i386/archsetjmp.h @@ -0,0 +1,19 @@ +/* + * arch/i386/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { +	unsigned int __ebx; +	unsigned int __esp; +	unsigned int __ebp; +	unsigned int __esi; +	unsigned int __edi; +	unsigned int __eip; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif				/* _SETJMP_H */ diff --git a/arch/um/include/sysdep-x86_64/archsetjmp.h b/arch/um/include/sysdep-x86_64/archsetjmp.h new file mode 100644 index 00000000000..454fc60aff6 --- /dev/null +++ b/arch/um/include/sysdep-x86_64/archsetjmp.h @@ -0,0 +1,21 @@ +/* + * arch/x86_64/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { +	unsigned long __rbx; +	unsigned long __rsp; +	unsigned long __rbp; +	unsigned long __r12; +	unsigned long __r13; +	unsigned long __r14; +	unsigned long __r15; +	unsigned long __rip; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif				/* _SETJMP_H */ diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index b98d3ca2cd1..3afde92ad2c 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -7,7 +7,6 @@  #include <stdio.h>  #include <errno.h>  #include <signal.h> -#include <setjmp.h>  #include <linux/unistd.h>  #include <sys/mman.h>  #include <sys/wait.h> diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 7baf90fda58..50418a5e713 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -8,7 +8,6 @@  #include <unistd.h>  #include <errno.h>  #include <signal.h> -#include <setjmp.h>  #include <sched.h>  #include "ptrace_user.h"  #include <sys/wait.h> @@ -470,7 +469,7 @@ void thread_wait(void *sw, void *fb)  	*switch_buf = &buf;  	fork_buf = fb;  	if(UML_SETJMP(&buf) == 0) -		siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); +		UML_LONGJMP(fork_buf, INIT_JMP_REMOVE_SIGSTACK);  }  void switch_threads(void *me, void *next) diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index 516f66dd87e..1f90a2d7138 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -5,12 +5,12 @@  #include <errno.h>  #include <string.h> -#include <setjmp.h>  #include "sysdep/ptrace_user.h"  #include "sysdep/ptrace.h"  #include "uml-config.h"  #include "skas_ptregs.h"  #include "registers.h" +#include "longjmp.h"  #include "user.h"  /* These are set once at boot time and not changed thereafter */ @@ -132,9 +132,9 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)  void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer)  { -	struct __jmp_buf_tag *jmpbuf = buffer; +	struct __jmp_buf *jmpbuf = buffer; -	UPT_SET(uml_regs, EIP, jmpbuf->__jmpbuf[JB_PC]); -	UPT_SET(uml_regs, UESP, jmpbuf->__jmpbuf[JB_SP]); -	UPT_SET(uml_regs, EBP, jmpbuf->__jmpbuf[JB_BP]); +	UPT_SET(uml_regs, EIP, jmpbuf->__eip); +	UPT_SET(uml_regs, UESP, jmpbuf->__esp); +	UPT_SET(uml_regs, EBP, jmpbuf->__ebp);  } diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c index becd898d939..e730447d6c0 100644 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ b/arch/um/os-Linux/sys-x86_64/registers.c @@ -5,11 +5,11 @@  #include <errno.h>  #include <string.h> -#include <setjmp.h>  #include "ptrace_user.h"  #include "uml-config.h"  #include "skas_ptregs.h"  #include "registers.h" +#include "longjmp.h"  #include "user.h"  /* These are set once at boot time and not changed thereafter */ @@ -80,9 +80,9 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)  void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer)  { -	struct __jmp_buf_tag *jmpbuf = buffer; +	struct __jmp_buf *jmpbuf = buffer; -	UPT_SET(uml_regs, RIP, jmpbuf->__jmpbuf[JB_PC]); -	UPT_SET(uml_regs, RSP, jmpbuf->__jmpbuf[JB_RSP]); -	UPT_SET(uml_regs, RBP, jmpbuf->__jmpbuf[JB_RBP]); +	UPT_SET(uml_regs, RIP, jmpbuf->__rip); +	UPT_SET(uml_regs, RSP, jmpbuf->__rsp); +	UPT_SET(uml_regs, RBP, jmpbuf->__rbp);  } diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c index 90b29ae9af4..1df231a2624 100644 --- a/arch/um/os-Linux/trap.c +++ b/arch/um/os-Linux/trap.c @@ -5,7 +5,6 @@  #include <stdlib.h>  #include <signal.h> -#include <setjmp.h>  #include "kern_util.h"  #include "user_util.h"  #include "os.h" diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c index 865f6a6a259..bbb73a65037 100644 --- a/arch/um/os-Linux/uaccess.c +++ b/arch/um/os-Linux/uaccess.c @@ -4,8 +4,7 @@   * Licensed under the GPL   */ -#include <setjmp.h> -#include <string.h> +#include <stddef.h>  #include "longjmp.h"  unsigned long __do_user_copy(void *to, const void *from, int n, diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index c47a2a7ce70..3f5b1514e8a 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c @@ -7,7 +7,6 @@  #include <stdlib.h>  #include <unistd.h>  #include <limits.h> -#include <setjmp.h>  #include <sys/mman.h>  #include <sys/stat.h>  #include <sys/utsname.h> @@ -107,11 +106,11 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)  	jmp_buf buf;  	int n; -	n = sigsetjmp(buf, 1); +	n = UML_SETJMP(&buf);  	if(n == 0){  		va_start(args, proc);  		(*proc)(&buf, &args);  	}  	va_end(args); -	return(n); +	return n;  } diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 374d61a1943..59cc7027575 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile @@ -1,5 +1,5 @@  obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ -	ptrace_user.o signal.o sigcontext.o syscalls.o sysrq.o \ +	ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \  	sys_call_table.o tls.o  obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o diff --git a/arch/um/sys-i386/setjmp.S b/arch/um/sys-i386/setjmp.S new file mode 100644 index 00000000000..b766792c993 --- /dev/null +++ b/arch/um/sys-i386/setjmp.S @@ -0,0 +1,58 @@ +# +# arch/i386/setjmp.S +# +# setjmp/longjmp for the i386 architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +#	%ebx +#	%esp +#	%ebp +#	%esi +#	%edi +#	<return address> +# + +	.text +	.align 4 +	.globl setjmp +	.type setjmp, @function +setjmp: +#ifdef _REGPARM +	movl %eax,%edx +#else +	movl 4(%esp),%edx +#endif +	popl %ecx			# Return address, and adjust the stack +	xorl %eax,%eax			# Return value +	movl %ebx,(%edx) +	movl %esp,4(%edx)		# Post-return %esp! +	pushl %ecx			# Make the call/return stack happy +	movl %ebp,8(%edx) +	movl %esi,12(%edx) +	movl %edi,16(%edx) +	movl %ecx,20(%edx)		# Return address +	ret + +	.size setjmp,.-setjmp + +	.text +	.align 4 +	.globl longjmp +	.type longjmp, @function +longjmp: +#ifdef _REGPARM +	xchgl %eax,%edx +#else +	movl 4(%esp),%edx		# jmp_ptr address +	movl 8(%esp),%eax		# Return value +#endif +	movl (%edx),%ebx +	movl 4(%edx),%esp +	movl 8(%edx),%ebp +	movl 12(%edx),%esi +	movl 16(%edx),%edi +	jmp *20(%edx) + +	.size longjmp,.-longjmp diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index c19794d435d..f41768b8e25 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile @@ -5,8 +5,8 @@  #  obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ -	sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o ksyms.o \ -	tls.o +	setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \ +	ksyms.o tls.o  obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o  obj-$(CONFIG_MODULES) += um_module.o diff --git a/arch/um/sys-x86_64/setjmp.S b/arch/um/sys-x86_64/setjmp.S new file mode 100644 index 00000000000..45f547b4043 --- /dev/null +++ b/arch/um/sys-x86_64/setjmp.S @@ -0,0 +1,54 @@ +# +# arch/x86_64/setjmp.S +# +# setjmp/longjmp for the x86-64 architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +#	%rbx +#	%rsp (post-return) +#	%rbp +#	%r12 +#	%r13 +#	%r14 +#	%r15 +#	<return address> +# + +	.text +	.align 4 +	.globl setjmp +	.type setjmp, @function +setjmp: +	pop  %rsi			# Return address, and adjust the stack +	xorl %eax,%eax			# Return value +	movq %rbx,(%rdi) +	movq %rsp,8(%rdi)		# Post-return %rsp! +	push %rsi			# Make the call/return stack happy +	movq %rbp,16(%rdi) +	movq %r12,24(%rdi) +	movq %r13,32(%rdi) +	movq %r14,40(%rdi) +	movq %r15,48(%rdi) +	movq %rsi,56(%rdi)		# Return address +	ret + +	.size setjmp,.-setjmp + +	.text +	.align 4 +	.globl longjmp +	.type longjmp, @function +longjmp: +	movl %esi,%eax			# Return value (int) +	movq (%rdi),%rbx +	movq 8(%rdi),%rsp +	movq 16(%rdi),%rbp +	movq 24(%rdi),%r12 +	movq 32(%rdi),%r13 +	movq 40(%rdi),%r14 +	movq 48(%rdi),%r15 +	jmp *56(%rdi) + +	.size longjmp,.-longjmp  |