diff options
| -rw-r--r-- | arch/um/sys-x86_64/stub_segv.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c index 65a131b362b6..d1e53bdf2e85 100644 --- a/arch/um/sys-x86_64/stub_segv.c +++ b/arch/um/sys-x86_64/stub_segv.c | |||
| @@ -10,6 +10,22 @@ | |||
| 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> | ||
| 14 | |||
| 15 | /* Copied from sys-x86_64/signal.c - Can't find an equivalent definition | ||
| 16 | * in the libc headers anywhere. | ||
| 17 | */ | ||
| 18 | struct rt_sigframe | ||
| 19 | { | ||
| 20 | char *pretcode; | ||
| 21 | struct ucontext uc; | ||
| 22 | struct siginfo info; | ||
| 23 | }; | ||
| 24 | |||
| 25 | /* Copied here from <linux/kernel.h> - we're userspace. */ | ||
| 26 | #define container_of(ptr, type, member) ({ \ | ||
| 27 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ | ||
| 28 | (type *)( (char *)__mptr - offsetof(type,member) );}) | ||
| 13 | 29 | ||
| 14 | void __attribute__ ((__section__ (".__syscall_stub"))) | 30 | void __attribute__ ((__section__ (".__syscall_stub"))) |
| 15 | stub_segv_handler(int sig) | 31 | stub_segv_handler(int sig) |
| @@ -17,16 +33,19 @@ stub_segv_handler(int sig) | |||
| 17 | struct ucontext *uc; | 33 | struct ucontext *uc; |
| 18 | 34 | ||
| 19 | __asm__("movq %%rdx, %0" : "=g" (uc) :); | 35 | __asm__("movq %%rdx, %0" : "=g" (uc) :); |
| 20 | GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), | 36 | GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), |
| 21 | &uc->uc_mcontext); | 37 | &uc->uc_mcontext); |
| 22 | 38 | ||
| 23 | __asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid)); | 39 | __asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid)); |
| 24 | __asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;" | 40 | __asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;" |
| 25 | "syscall": : "g" (__NR_kill), "g" (SIGUSR1)); | 41 | "syscall": : "g" (__NR_kill), "g" (SIGUSR1) : |
| 26 | /* Two popqs to restore the stack to the state just before entering | 42 | "%rdi", "%rax", "%rsi"); |
| 27 | * the handler, one pops the return address, the other pops the frame | 43 | /* sys_sigreturn expects that the stack pointer will be 8 bytes into |
| 28 | * pointer. | 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. | ||
| 29 | */ | 46 | */ |
| 30 | __asm__("popq %%rax ; popq %%rax ; movq %0, %%rax ; syscall" : : "g" | 47 | __asm__("movq %0, %%rsp": : |
| 31 | (__NR_rt_sigreturn)); | 48 | "g" ((unsigned long) container_of(uc, struct rt_sigframe, |
| 49 | uc) + 8)); | ||
| 50 | __asm__("movq %0, %%rax ; syscall" : : "g" (__NR_rt_sigreturn)); | ||
| 32 | } | 51 | } |
