aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2006-09-26 02:32:59 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-26 11:49:05 -0400
commit13c06be399902c9ebda08e092edb1614bb4a3761 (patch)
treec67134cfb7efd23ab7017fde32657fa3a7e58154
parentc5c6ba4e08ab9c9e390a0f3a7d9a5c332f5cc6ef (diff)
[PATCH] uml: Use klibc setjmp/longjmp
This patch adds an implementation of setjmp and longjmp to UML, allowing access to the inside of a jmpbuf without needing the access macros formerly provided by libc. The implementation is stolen from klibc. I copy the relevant files into arch/um. I have another patch which avoids the copying, but requires klibc be in the tree. setjmp and longjmp users required some tweaking. Includes of <setjmp.h> were removed and includes of the UML longjmp.h were added where necessary. There are also replacements of siglongjmp with UML_LONGJMP which I somehow missed earlier. Signed-off-by: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/um/include/longjmp.h5
-rw-r--r--arch/um/include/sysdep-i386/archsetjmp.h19
-rw-r--r--arch/um/include/sysdep-x86_64/archsetjmp.h21
-rw-r--r--arch/um/os-Linux/process.c1
-rw-r--r--arch/um/os-Linux/skas/process.c3
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c10
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c10
-rw-r--r--arch/um/os-Linux/trap.c1
-rw-r--r--arch/um/os-Linux/uaccess.c3
-rw-r--r--arch/um/os-Linux/util.c5
-rw-r--r--arch/um/sys-i386/Makefile2
-rw-r--r--arch/um/sys-i386/setjmp.S58
-rw-r--r--arch/um/sys-x86_64/Makefile4
-rw-r--r--arch/um/sys-x86_64/setjmp.S54
14 files changed, 173 insertions, 23 deletions
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
index 1b5c0131a12e..e93c6d3e893b 100644
--- a/arch/um/include/longjmp.h
+++ b/arch/um/include/longjmp.h
@@ -1,9 +1,12 @@
1#ifndef __UML_LONGJMP_H 1#ifndef __UML_LONGJMP_H
2#define __UML_LONGJMP_H 2#define __UML_LONGJMP_H
3 3
4#include <setjmp.h> 4#include "sysdep/archsetjmp.h"
5#include "os.h" 5#include "os.h"
6 6
7extern int setjmp(jmp_buf);
8extern void longjmp(jmp_buf, int);
9
7#define UML_LONGJMP(buf, val) do { \ 10#define UML_LONGJMP(buf, val) do { \
8 longjmp(*buf, val); \ 11 longjmp(*buf, val); \
9} while(0) 12} 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 000000000000..ea1ba3d42aee
--- /dev/null
+++ b/arch/um/include/sysdep-i386/archsetjmp.h
@@ -0,0 +1,19 @@
1/*
2 * arch/i386/include/klibc/archsetjmp.h
3 */
4
5#ifndef _KLIBC_ARCHSETJMP_H
6#define _KLIBC_ARCHSETJMP_H
7
8struct __jmp_buf {
9 unsigned int __ebx;
10 unsigned int __esp;
11 unsigned int __ebp;
12 unsigned int __esi;
13 unsigned int __edi;
14 unsigned int __eip;
15};
16
17typedef struct __jmp_buf jmp_buf[1];
18
19#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 000000000000..454fc60aff6d
--- /dev/null
+++ b/arch/um/include/sysdep-x86_64/archsetjmp.h
@@ -0,0 +1,21 @@
1/*
2 * arch/x86_64/include/klibc/archsetjmp.h
3 */
4
5#ifndef _KLIBC_ARCHSETJMP_H
6#define _KLIBC_ARCHSETJMP_H
7
8struct __jmp_buf {
9 unsigned long __rbx;
10 unsigned long __rsp;
11 unsigned long __rbp;
12 unsigned long __r12;
13 unsigned long __r13;
14 unsigned long __r14;
15 unsigned long __r15;
16 unsigned long __rip;
17};
18
19typedef struct __jmp_buf jmp_buf[1];
20
21#endif /* _SETJMP_H */
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index b98d3ca2cd1b..3afde92ad2c0 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -7,7 +7,6 @@
7#include <stdio.h> 7#include <stdio.h>
8#include <errno.h> 8#include <errno.h>
9#include <signal.h> 9#include <signal.h>
10#include <setjmp.h>
11#include <linux/unistd.h> 10#include <linux/unistd.h>
12#include <sys/mman.h> 11#include <sys/mman.h>
13#include <sys/wait.h> 12#include <sys/wait.h>
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 7baf90fda58b..50418a5e7134 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -8,7 +8,6 @@
8#include <unistd.h> 8#include <unistd.h>
9#include <errno.h> 9#include <errno.h>
10#include <signal.h> 10#include <signal.h>
11#include <setjmp.h>
12#include <sched.h> 11#include <sched.h>
13#include "ptrace_user.h" 12#include "ptrace_user.h"
14#include <sys/wait.h> 13#include <sys/wait.h>
@@ -470,7 +469,7 @@ void thread_wait(void *sw, void *fb)
470 *switch_buf = &buf; 469 *switch_buf = &buf;
471 fork_buf = fb; 470 fork_buf = fb;
472 if(UML_SETJMP(&buf) == 0) 471 if(UML_SETJMP(&buf) == 0)
473 siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); 472 UML_LONGJMP(fork_buf, INIT_JMP_REMOVE_SIGSTACK);
474} 473}
475 474
476void switch_threads(void *me, void *next) 475void 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 516f66dd87e3..1f90a2d71386 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -5,12 +5,12 @@
5 5
6#include <errno.h> 6#include <errno.h>
7#include <string.h> 7#include <string.h>
8#include <setjmp.h>
9#include "sysdep/ptrace_user.h" 8#include "sysdep/ptrace_user.h"
10#include "sysdep/ptrace.h" 9#include "sysdep/ptrace.h"
11#include "uml-config.h" 10#include "uml-config.h"
12#include "skas_ptregs.h" 11#include "skas_ptregs.h"
13#include "registers.h" 12#include "registers.h"
13#include "longjmp.h"
14#include "user.h" 14#include "user.h"
15 15
16/* These are set once at boot time and not changed thereafter */ 16/* 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)
132 132
133void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) 133void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer)
134{ 134{
135 struct __jmp_buf_tag *jmpbuf = buffer; 135 struct __jmp_buf *jmpbuf = buffer;
136 136
137 UPT_SET(uml_regs, EIP, jmpbuf->__jmpbuf[JB_PC]); 137 UPT_SET(uml_regs, EIP, jmpbuf->__eip);
138 UPT_SET(uml_regs, UESP, jmpbuf->__jmpbuf[JB_SP]); 138 UPT_SET(uml_regs, UESP, jmpbuf->__esp);
139 UPT_SET(uml_regs, EBP, jmpbuf->__jmpbuf[JB_BP]); 139 UPT_SET(uml_regs, EBP, jmpbuf->__ebp);
140} 140}
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index becd898d9398..e730447d6c02 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 @@
5 5
6#include <errno.h> 6#include <errno.h>
7#include <string.h> 7#include <string.h>
8#include <setjmp.h>
9#include "ptrace_user.h" 8#include "ptrace_user.h"
10#include "uml-config.h" 9#include "uml-config.h"
11#include "skas_ptregs.h" 10#include "skas_ptregs.h"
12#include "registers.h" 11#include "registers.h"
12#include "longjmp.h"
13#include "user.h" 13#include "user.h"
14 14
15/* These are set once at boot time and not changed thereafter */ 15/* 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)
80 80
81void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) 81void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer)
82{ 82{
83 struct __jmp_buf_tag *jmpbuf = buffer; 83 struct __jmp_buf *jmpbuf = buffer;
84 84
85 UPT_SET(uml_regs, RIP, jmpbuf->__jmpbuf[JB_PC]); 85 UPT_SET(uml_regs, RIP, jmpbuf->__rip);
86 UPT_SET(uml_regs, RSP, jmpbuf->__jmpbuf[JB_RSP]); 86 UPT_SET(uml_regs, RSP, jmpbuf->__rsp);
87 UPT_SET(uml_regs, RBP, jmpbuf->__jmpbuf[JB_RBP]); 87 UPT_SET(uml_regs, RBP, jmpbuf->__rbp);
88} 88}
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index 90b29ae9af46..1df231a26244 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -5,7 +5,6 @@
5 5
6#include <stdlib.h> 6#include <stdlib.h>
7#include <signal.h> 7#include <signal.h>
8#include <setjmp.h>
9#include "kern_util.h" 8#include "kern_util.h"
10#include "user_util.h" 9#include "user_util.h"
11#include "os.h" 10#include "os.h"
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 865f6a6a2590..bbb73a650370 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -4,8 +4,7 @@
4 * Licensed under the GPL 4 * Licensed under the GPL
5 */ 5 */
6 6
7#include <setjmp.h> 7#include <stddef.h>
8#include <string.h>
9#include "longjmp.h" 8#include "longjmp.h"
10 9
11unsigned long __do_user_copy(void *to, const void *from, int n, 10unsigned 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 c47a2a7ce70e..3f5b1514e8a7 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -7,7 +7,6 @@
7#include <stdlib.h> 7#include <stdlib.h>
8#include <unistd.h> 8#include <unistd.h>
9#include <limits.h> 9#include <limits.h>
10#include <setjmp.h>
11#include <sys/mman.h> 10#include <sys/mman.h>
12#include <sys/stat.h> 11#include <sys/stat.h>
13#include <sys/utsname.h> 12#include <sys/utsname.h>
@@ -107,11 +106,11 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)
107 jmp_buf buf; 106 jmp_buf buf;
108 int n; 107 int n;
109 108
110 n = sigsetjmp(buf, 1); 109 n = UML_SETJMP(&buf);
111 if(n == 0){ 110 if(n == 0){
112 va_start(args, proc); 111 va_start(args, proc);
113 (*proc)(&buf, &args); 112 (*proc)(&buf, &args);
114 } 113 }
115 va_end(args); 114 va_end(args);
116 return(n); 115 return n;
117} 116}
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 374d61a19439..59cc70275754 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,5 +1,5 @@
1obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ 1obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
2 ptrace_user.o signal.o sigcontext.o syscalls.o sysrq.o \ 2 ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \
3 sys_call_table.o tls.o 3 sys_call_table.o tls.o
4 4
5obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o 5obj-$(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 000000000000..b766792c9933
--- /dev/null
+++ b/arch/um/sys-i386/setjmp.S
@@ -0,0 +1,58 @@
1#
2# arch/i386/setjmp.S
3#
4# setjmp/longjmp for the i386 architecture
5#
6
7#
8# The jmp_buf is assumed to contain the following, in order:
9# %ebx
10# %esp
11# %ebp
12# %esi
13# %edi
14# <return address>
15#
16
17 .text
18 .align 4
19 .globl setjmp
20 .type setjmp, @function
21setjmp:
22#ifdef _REGPARM
23 movl %eax,%edx
24#else
25 movl 4(%esp),%edx
26#endif
27 popl %ecx # Return address, and adjust the stack
28 xorl %eax,%eax # Return value
29 movl %ebx,(%edx)
30 movl %esp,4(%edx) # Post-return %esp!
31 pushl %ecx # Make the call/return stack happy
32 movl %ebp,8(%edx)
33 movl %esi,12(%edx)
34 movl %edi,16(%edx)
35 movl %ecx,20(%edx) # Return address
36 ret
37
38 .size setjmp,.-setjmp
39
40 .text
41 .align 4
42 .globl longjmp
43 .type longjmp, @function
44longjmp:
45#ifdef _REGPARM
46 xchgl %eax,%edx
47#else
48 movl 4(%esp),%edx # jmp_ptr address
49 movl 8(%esp),%eax # Return value
50#endif
51 movl (%edx),%ebx
52 movl 4(%edx),%esp
53 movl 8(%edx),%ebp
54 movl 12(%edx),%esi
55 movl 16(%edx),%edi
56 jmp *20(%edx)
57
58 .size longjmp,.-longjmp
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index c19794d435d6..f41768b8e25e 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -5,8 +5,8 @@
5# 5#
6 6
7obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ 7obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
8 sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o ksyms.o \ 8 setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \
9 tls.o 9 ksyms.o tls.o
10 10
11obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o 11obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
12obj-$(CONFIG_MODULES) += um_module.o 12obj-$(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 000000000000..45f547b4043e
--- /dev/null
+++ b/arch/um/sys-x86_64/setjmp.S
@@ -0,0 +1,54 @@
1#
2# arch/x86_64/setjmp.S
3#
4# setjmp/longjmp for the x86-64 architecture
5#
6
7#
8# The jmp_buf is assumed to contain the following, in order:
9# %rbx
10# %rsp (post-return)
11# %rbp
12# %r12
13# %r13
14# %r14
15# %r15
16# <return address>
17#
18
19 .text
20 .align 4
21 .globl setjmp
22 .type setjmp, @function
23setjmp:
24 pop %rsi # Return address, and adjust the stack
25 xorl %eax,%eax # Return value
26 movq %rbx,(%rdi)
27 movq %rsp,8(%rdi) # Post-return %rsp!
28 push %rsi # Make the call/return stack happy
29 movq %rbp,16(%rdi)
30 movq %r12,24(%rdi)
31 movq %r13,32(%rdi)
32 movq %r14,40(%rdi)
33 movq %r15,48(%rdi)
34 movq %rsi,56(%rdi) # Return address
35 ret
36
37 .size setjmp,.-setjmp
38
39 .text
40 .align 4
41 .globl longjmp
42 .type longjmp, @function
43longjmp:
44 movl %esi,%eax # Return value (int)
45 movq (%rdi),%rbx
46 movq 8(%rdi),%rsp
47 movq 16(%rdi),%rbp
48 movq 24(%rdi),%r12
49 movq 32(%rdi),%r13
50 movq 40(%rdi),%r14
51 movq 48(%rdi),%r15
52 jmp *56(%rdi)
53
54 .size longjmp,.-longjmp