new file mode 100644
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <kern_util.h>
+#include <sysdep/syscalls.h>
+#include <os.h>
+
+__visible void do_syscall_64(struct pt_regs *regs)
+{
+ int syscall;
+
+ syscall = PT_SYSCALL_NR(regs->regs.gp);
+ UPT_SYSCALL_NR(®s->regs) = syscall;
+
+ pr_debug("syscall(%d) (current=%lx) (fn=%lx)\n",
+ syscall, (unsigned long)current,
+ (unsigned long)sys_call_table[syscall]);
+
+ if (likely(syscall < NR_syscalls)) {
+ PT_REGS_SET_SYSCALL_RETURN(regs,
+ EXECUTE_SYSCALL(syscall, regs));
+ }
+
+ pr_debug("syscall(%d) --> %lx\n", syscall,
+ regs->regs.gp[HOST_AX]);
+
+ PT_REGS_SYSCALL_RET(regs) = regs->regs.gp[HOST_AX];
+
+ /* force do_signal() --> is_syscall() */
+ set_thread_flag(TIF_SIGPENDING);
+ interrupt_end();
+
+ /* execve succeeded */
+ if (syscall == __NR_execve && regs->regs.gp[HOST_AX] == 0)
+ userspace(¤t->thread.regs.regs);
+}
new file mode 100644
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <asm/errno.h>
+
+#include <linux/linkage.h>
+#include <asm/percpu.h>
+#include <asm/desc.h>
+
+#include "../entry/calling.h"
+
+#ifdef CONFIG_SMP
+#error need to stash these variables somewhere else
+#endif
+
+#define UM_GLOBAL_VAR(x) .data; .align 8; .globl x; x:; .long 0
+
+UM_GLOBAL_VAR(current_top_of_stack)
+UM_GLOBAL_VAR(current_ptregs)
+
+.code64
+.section .entry.text, "ax"
+
+.align 8
+#undef ENTRY
+#define ENTRY(x) .text; .globl x; .type x,%function; x:
+#undef END
+#define END(x) .size x, . - x
+
+/*
+ * %rcx has the return address (we set it like that in zpoline trampoline).
+ *
+ * Registers on entry:
+ * rax system call number
+ * rcx return address
+ * rdi arg0
+ * rsi arg1
+ * rdx arg2
+ * r10 arg3
+ * r8 arg4
+ * r9 arg5
+ *
+ * (note: we are allowed to mess with r11: r11 is callee-clobbered
+ * register in C ABI)
+ */
+ENTRY(__kernel_vsyscall)
+
+ movq %rsp, %r11
+
+ /* Point rsp to the top of the ptregs array, so we can
+ just fill it with a bunch of push'es. */
+ movq current_ptregs, %rsp
+
+ /* 8 bytes * 20 registers (plus 8 for the push) */
+ addq $168, %rsp
+
+ /* Construct struct pt_regs on stack */
+ pushq $0 /* pt_regs->ss (index 20) */
+ pushq %r11 /* pt_regs->sp */
+ pushfq /* pt_regs->flags */
+ pushq $0 /* pt_regs->cs */
+ pushq %rcx /* pt_regs->ip */
+ pushq %rax /* pt_regs->orig_ax */
+
+ PUSH_AND_CLEAR_REGS rax=$-ENOSYS
+
+ mov %rsp, %rdi
+
+ /*
+ * Switch to current top of stack, so "current->" points
+ * to the right task.
+ */
+ movq current_top_of_stack, %rsp
+
+ call do_syscall_64
+
+ movq current_ptregs, %rsp
+
+ POP_REGS
+
+ addq $8, %rsp /* skip orig_ax */
+ addq $8, %rsp /* skip ip */
+ addq $8, %rsp /* skip cs */
+ addq $8, %rsp /* skip flags */
+ popq %rsp
+
+ ret
+
+END(__kernel_vsyscall)
@@ -25,4 +25,10 @@ extern syscall_handler_t *sys_call_table[];
extern syscall_handler_t sys_modify_ldt;
extern syscall_handler_t sys_arch_prctl;
+#ifndef CONFIG_MMU
+__visible void do_syscall_64(struct pt_regs *regs);
+extern long __kernel_vsyscall(int64_t a0, int64_t a1, int64_t a2, int64_t a3,
+ int64_t a4, int64_t a5, int64_t a6);
+#endif
+
#endif