X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=arch%2Fum%2Fsys-x86_64%2Fstub_segv.c;h=1c967026c957dd08e4b81406a82712b60ada8ee6;hb=4e8f10b7ccf1c3c53a818a157962074a7340732e;hp=65a131b362b689b634608f0ae83ddbc6ebf5e029;hpb=1e231efe50ffe4d291be24d2fe393188de9c4b08;p=pandora-kernel.git diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c index 65a131b362b6..1c967026c957 100644 --- a/arch/um/sys-x86_64/stub_segv.c +++ b/arch/um/sys-x86_64/stub_segv.c @@ -3,30 +3,49 @@ * Licensed under the GPL */ -#include +#include +#include #include #include -#include #include "uml-config.h" #include "sysdep/sigcontext.h" #include "sysdep/faultinfo.h" +#include "sysdep/stub.h" + +/* Copied from sys-x86_64/signal.c - Can't find an equivalent definition + * in the libc headers anywhere. + */ +struct rt_sigframe +{ + char *pretcode; + struct ucontext uc; + struct siginfo info; +}; + +/* Copied here from - we're userspace. */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) void __attribute__ ((__section__ (".__syscall_stub"))) stub_segv_handler(int sig) { struct ucontext *uc; + int pid; + + __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :); + GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), + &uc->uc_mcontext); - __asm__("movq %%rdx, %0" : "=g" (uc) :); - GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), - &uc->uc_mcontext); + pid = stub_syscall0(__NR_getpid); + stub_syscall2(__NR_kill, pid, SIGUSR1); - __asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid)); - __asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;" - "syscall": : "g" (__NR_kill), "g" (SIGUSR1)); - /* Two popqs to restore the stack to the state just before entering - * the handler, one pops the return address, the other pops the frame - * pointer. + /* sys_sigreturn expects that the stack pointer will be 8 bytes into + * the signal frame. So, we use the ucontext pointer, which we know + * already, to get the signal frame pointer, and add 8 to that. */ - __asm__("popq %%rax ; popq %%rax ; movq %0, %%rax ; syscall" : : "g" - (__NR_rt_sigreturn)); + __asm__ __volatile__("movq %0, %%rsp; movq %1, %%rax ; syscall": : + "g" ((unsigned long) + container_of(uc, struct rt_sigframe, uc) + 8), + "g" (__NR_rt_sigreturn)); }