diff options
author | Jeff Dike <jdike@addtoit.com> | 2005-11-22 00:32:09 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-22 12:13:41 -0500 |
commit | 17d469715c6453e4994e6617e8f644bf10f38584 (patch) | |
tree | 0bfc17100309b888315c3cae02adfd1783c04774 | |
parent | e23181deec0d2a8be576faf9d71211abb84d5ccc (diff) |
[PATCH] uml: properly invoke x86_64 system calls
This patch makes stub_segv use the stub_syscall macros. This was needed
anyway, but the bug that prompted this was the discovery that gcc was storing
stuff in RCX, which is trashed across a system call. This is exactly the sort
of problem that the new macros fix.
There is a stub_syscall0 for getpid. stub_segv was changed to be a libc file,
and that caused some include changes.
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/sysdep-i386/stub.h | 9 | ||||
-rw-r--r-- | arch/um/include/sysdep-x86_64/stub.h | 12 | ||||
-rw-r--r-- | arch/um/sys-i386/Makefile | 2 | ||||
-rw-r--r-- | arch/um/sys-i386/stub_segv.c | 11 | ||||
-rw-r--r-- | arch/um/sys-x86_64/Makefile | 2 | ||||
-rw-r--r-- | arch/um/sys-x86_64/stub_segv.c | 20 |
6 files changed, 39 insertions, 17 deletions
diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h index a49ceb199ee5..6ba8cbbe0d36 100644 --- a/arch/um/include/sysdep-i386/stub.h +++ b/arch/um/include/sysdep-i386/stub.h | |||
@@ -16,6 +16,15 @@ extern void stub_clone_handler(void); | |||
16 | #define STUB_MMAP_NR __NR_mmap2 | 16 | #define STUB_MMAP_NR __NR_mmap2 |
17 | #define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT) | 17 | #define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT) |
18 | 18 | ||
19 | static inline long stub_syscall0(long syscall) | ||
20 | { | ||
21 | long ret; | ||
22 | |||
23 | __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall)); | ||
24 | |||
25 | return ret; | ||
26 | } | ||
27 | |||
19 | static inline long stub_syscall1(long syscall, long arg1) | 28 | static inline long stub_syscall1(long syscall, long arg1) |
20 | { | 29 | { |
21 | long ret; | 30 | long ret; |
diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h index 2bd6e7a97286..c41689c13dc9 100644 --- a/arch/um/include/sysdep-x86_64/stub.h +++ b/arch/um/include/sysdep-x86_64/stub.h | |||
@@ -6,7 +6,6 @@ | |||
6 | #ifndef __SYSDEP_STUB_H | 6 | #ifndef __SYSDEP_STUB_H |
7 | #define __SYSDEP_STUB_H | 7 | #define __SYSDEP_STUB_H |
8 | 8 | ||
9 | #include <asm/ptrace.h> | ||
10 | #include <asm/unistd.h> | 9 | #include <asm/unistd.h> |
11 | #include <sysdep/ptrace_user.h> | 10 | #include <sysdep/ptrace_user.h> |
12 | 11 | ||
@@ -20,6 +19,17 @@ extern void stub_clone_handler(void); | |||
20 | #define __syscall_clobber "r11","rcx","memory" | 19 | #define __syscall_clobber "r11","rcx","memory" |
21 | #define __syscall "syscall" | 20 | #define __syscall "syscall" |
22 | 21 | ||
22 | static inline long stub_syscall0(long syscall) | ||
23 | { | ||
24 | long ret; | ||
25 | |||
26 | __asm__ volatile (__syscall | ||
27 | : "=a" (ret) | ||
28 | : "0" (syscall) : __syscall_clobber ); | ||
29 | |||
30 | return ret; | ||
31 | } | ||
32 | |||
23 | static inline long stub_syscall2(long syscall, long arg1, long arg2) | 33 | static inline long stub_syscall2(long syscall, long arg1, long arg2) |
24 | { | 34 | { |
25 | long ret; | 35 | long ret; |
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 6dfeb70f6957..150059dbee12 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile | |||
@@ -5,7 +5,7 @@ obj-y = bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ | |||
5 | obj-$(CONFIG_HIGHMEM) += highmem.o | 5 | obj-$(CONFIG_HIGHMEM) += highmem.o |
6 | obj-$(CONFIG_MODULES) += module.o | 6 | obj-$(CONFIG_MODULES) += module.o |
7 | 7 | ||
8 | USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o | 8 | USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o stub_segv.o |
9 | 9 | ||
10 | SYMLINKS = bitops.c semaphore.c highmem.c module.c | 10 | SYMLINKS = bitops.c semaphore.c highmem.c module.c |
11 | 11 | ||
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c index 1e88b275edac..a37f672ec964 100644 --- a/arch/um/sys-i386/stub_segv.c +++ b/arch/um/sys-i386/stub_segv.c | |||
@@ -3,9 +3,11 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <asm/signal.h> | 6 | #include <signal.h> |
7 | #include <sys/select.h> /* The only way I can see to get sigset_t */ | ||
7 | #include <asm/unistd.h> | 8 | #include <asm/unistd.h> |
8 | #include "uml-config.h" | 9 | #include "uml-config.h" |
10 | #include "sysdep/stub.h" | ||
9 | #include "sysdep/sigcontext.h" | 11 | #include "sysdep/sigcontext.h" |
10 | #include "sysdep/faultinfo.h" | 12 | #include "sysdep/faultinfo.h" |
11 | 13 | ||
@@ -13,13 +15,14 @@ void __attribute__ ((__section__ (".__syscall_stub"))) | |||
13 | stub_segv_handler(int sig) | 15 | stub_segv_handler(int sig) |
14 | { | 16 | { |
15 | struct sigcontext *sc = (struct sigcontext *) (&sig + 1); | 17 | struct sigcontext *sc = (struct sigcontext *) (&sig + 1); |
18 | int pid; | ||
16 | 19 | ||
17 | GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), | 20 | GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), |
18 | sc); | 21 | sc); |
19 | 22 | ||
20 | __asm__("movl %0, %%eax ; int $0x80": : "g" (__NR_getpid)); | 23 | pid = stub_syscall0(__NR_getpid); |
21 | __asm__("movl %%eax, %%ebx ; movl %0, %%eax ; movl %1, %%ecx ;" | 24 | stub_syscall2(__NR_kill, pid, SIGUSR1); |
22 | "int $0x80": : "g" (__NR_kill), "g" (SIGUSR1)); | 25 | |
23 | /* Load pointer to sigcontext into esp, since we need to leave | 26 | /* Load pointer to sigcontext into esp, since we need to leave |
24 | * the stack in its original form when we do the sigreturn here, by | 27 | * the stack in its original form when we do the sigreturn here, by |
25 | * hand. | 28 | * hand. |
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index ea977df395a1..00b2025427df 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile | |||
@@ -12,7 +12,7 @@ lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o ldt.o mem.o memcpy.o \ | |||
12 | obj-y := ksyms.o | 12 | obj-y := ksyms.o |
13 | obj-$(CONFIG_MODULES) += module.o um_module.o | 13 | obj-$(CONFIG_MODULES) += module.o um_module.o |
14 | 14 | ||
15 | USER_OBJS := ptrace_user.o sigcontext.o | 15 | USER_OBJS := ptrace_user.o sigcontext.o stub_segv.o |
16 | 16 | ||
17 | SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c ldt.c memcpy.S \ | 17 | SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c ldt.c memcpy.S \ |
18 | thunk.S module.c | 18 | thunk.S module.c |
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c index d1e53bdf2e85..a27099533198 100644 --- a/arch/um/sys-x86_64/stub_segv.c +++ b/arch/um/sys-x86_64/stub_segv.c | |||
@@ -3,14 +3,14 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <asm/signal.h> | 6 | #include <stddef.h> |
7 | #include <signal.h> | ||
7 | #include <linux/compiler.h> | 8 | #include <linux/compiler.h> |
8 | #include <asm/unistd.h> | 9 | #include <asm/unistd.h> |
9 | #include <asm/ucontext.h> | ||
10 | #include "uml-config.h" | 10 | #include "uml-config.h" |
11 | #include "sysdep/sigcontext.h" | 11 | #include "sysdep/sigcontext.h" |
12 | #include "sysdep/faultinfo.h" | 12 | #include "sysdep/faultinfo.h" |
13 | #include <stddef.h> | 13 | #include "sysdep/stub.h" |
14 | 14 | ||
15 | /* Copied from sys-x86_64/signal.c - Can't find an equivalent definition | 15 | /* Copied from sys-x86_64/signal.c - Can't find an equivalent definition |
16 | * in the libc headers anywhere. | 16 | * in the libc headers anywhere. |
@@ -31,21 +31,21 @@ void __attribute__ ((__section__ (".__syscall_stub"))) | |||
31 | stub_segv_handler(int sig) | 31 | stub_segv_handler(int sig) |
32 | { | 32 | { |
33 | struct ucontext *uc; | 33 | struct ucontext *uc; |
34 | int pid; | ||
34 | 35 | ||
35 | __asm__("movq %%rdx, %0" : "=g" (uc) :); | 36 | __asm__("movq %%rdx, %0" : "=g" (uc) :); |
36 | GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), | 37 | GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), |
37 | &uc->uc_mcontext); | 38 | &uc->uc_mcontext); |
38 | 39 | ||
39 | __asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid)); | 40 | pid = stub_syscall0(__NR_getpid); |
40 | __asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;" | 41 | stub_syscall2(__NR_kill, pid, SIGUSR1); |
41 | "syscall": : "g" (__NR_kill), "g" (SIGUSR1) : | 42 | |
42 | "%rdi", "%rax", "%rsi"); | ||
43 | /* sys_sigreturn expects that the stack pointer will be 8 bytes into | 43 | /* sys_sigreturn expects that the stack pointer will be 8 bytes into |
44 | * the signal frame. So, we use the ucontext pointer, which we know | 44 | * the signal frame. So, we use the ucontext pointer, which we know |
45 | * already, to get the signal frame pointer, and add 8 to that. | 45 | * already, to get the signal frame pointer, and add 8 to that. |
46 | */ | 46 | */ |
47 | __asm__("movq %0, %%rsp": : | 47 | __asm__("movq %0, %%rsp; movq %1, %%rax ; syscall": : |
48 | "g" ((unsigned long) container_of(uc, struct rt_sigframe, | 48 | "g" ((unsigned long) container_of(uc, struct rt_sigframe, |
49 | uc) + 8)); | 49 | uc) + 8), |
50 | __asm__("movq %0, %%rax ; syscall" : : "g" (__NR_rt_sigreturn)); | 50 | "g" (__NR_rt_sigreturn)); |
51 | } | 51 | } |