summaryrefslogtreecommitdiff
path: root/arch/um/sys-x86_64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/sys-x86_64')
-rw-r--r--arch/um/sys-x86_64/Makefile12
-rw-r--r--arch/um/sys-x86_64/stub.S15
-rw-r--r--arch/um/sys-x86_64/stub_segv.c31
3 files changed, 56 insertions, 2 deletions
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index 2bc6f6849010..7488206ce6f4 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -6,8 +6,8 @@
#XXX: why into lib-y?
lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \
- ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o \
- syscalls.o sysrq.o thunk.o syscall_table.o
+ ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o stub.o \
+ stub_segv.o syscalls.o syscall_table.o sysrq.o thunk.o
obj-y := ksyms.o
obj-$(CONFIG_MODULES) += module.o um_module.o
@@ -28,6 +28,14 @@ semaphore.c-dir = kernel
thunk.S-dir = lib
module.c-dir = kernel
+STUB_CFLAGS = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
+
+# _cflags works with kernel files, not with userspace ones, but c_flags does,
+# why ask why?
+$(obj)/stub_segv.o : c_flags = $(STUB_CFLAGS)
+
+$(obj)/stub.o : a_flags = $(STUB_CFLAGS)
+
subdir- := util
include arch/um/scripts/Makefile.unmap
diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S
new file mode 100644
index 000000000000..31c14925716b
--- /dev/null
+++ b/arch/um/sys-x86_64/stub.S
@@ -0,0 +1,15 @@
+#include "uml-config.h"
+
+ .globl syscall_stub
+.section .__syscall_stub, "x"
+syscall_stub:
+ syscall
+ /* We don't have 64-bit constants, so this constructs the address
+ * we need.
+ */
+ movq $(UML_CONFIG_STUB_DATA >> 32), %rbx
+ salq $32, %rbx
+ movq $(UML_CONFIG_STUB_DATA & 0xffffffff), %rcx
+ or %rcx, %rbx
+ movq %rax, (%rbx)
+ int3
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
new file mode 100644
index 000000000000..161d1fe9c034
--- /dev/null
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+#include <linux/compiler.h>
+#include <asm/unistd.h>
+#include "uml-config.h"
+#include "sysdep/sigcontext.h"
+#include "sysdep/faultinfo.h"
+
+void __attribute__ ((__section__ (".__syscall_stub")))
+stub_segv_handler(int sig)
+{
+ struct ucontext *uc;
+
+ __asm__("movq %%rdx, %0" : "=g" (uc) :);
+ GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
+ &uc->uc_mcontext);
+
+ __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.
+ */
+ __asm__("popq %%rax ; popq %%rax ; movq %0, %%rax ; syscall" : : "g"
+ (__NR_rt_sigreturn));
+}