Merge branch 'torvalds/master'
[firefly-linux-kernel-4.4.55.git] / arch / um / os-Linux / skas / process.c
index 4625949bf1e4cd4ee9c424aa3eab1bfec6458ff7..3dddedba3a07f6ca423d6b8e16d79189cbc799de 100644 (file)
 #include <kern_util.h>
 #include <mem.h>
 #include <os.h>
-#include <proc_mm.h>
 #include <ptrace_user.h>
 #include <registers.h>
 #include <skas.h>
-#include <skas_ptrace.h>
 #include <sysdep/stub.h>
 
 int is_skas_winch(int pid, int fd, void *data)
@@ -91,50 +89,33 @@ extern unsigned long current_stub_stack(void);
 static void get_skas_faultinfo(int pid, struct faultinfo *fi)
 {
        int err;
+       unsigned long fpregs[FP_SIZE];
 
-       if (ptrace_faultinfo) {
-               err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
-               if (err) {
-                       printk(UM_KERN_ERR "get_skas_faultinfo - "
-                              "PTRACE_FAULTINFO failed, errno = %d\n", errno);
-                       fatal_sigsegv();
-               }
-
-               /* Special handling for i386, which has different structs */
-               if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
-                       memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
-                              sizeof(struct faultinfo) -
-                              sizeof(struct ptrace_faultinfo));
+       err = get_fp_registers(pid, fpregs);
+       if (err < 0) {
+               printk(UM_KERN_ERR "save_fp_registers returned %d\n",
+                      err);
+               fatal_sigsegv();
        }
-       else {
-               unsigned long fpregs[FP_SIZE];
-
-               err = get_fp_registers(pid, fpregs);
-               if (err < 0) {
-                       printk(UM_KERN_ERR "save_fp_registers returned %d\n",
-                              err);
-                       fatal_sigsegv();
-               }
-               err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
-               if (err) {
-                       printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
-                              "errno = %d\n", pid, errno);
-                       fatal_sigsegv();
-               }
-               wait_stub_done(pid);
+       err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
+       if (err) {
+               printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
+                      "errno = %d\n", pid, errno);
+               fatal_sigsegv();
+       }
+       wait_stub_done(pid);
 
-               /*
-                * faultinfo is prepared by the stub-segv-handler at start of
-                * the stub stack page. We just have to copy it.
-                */
-               memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
+       /*
+        * faultinfo is prepared by the stub-segv-handler at start of
+        * the stub stack page. We just have to copy it.
+        */
+       memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
 
-               err = put_fp_registers(pid, fpregs);
-               if (err < 0) {
-                       printk(UM_KERN_ERR "put_fp_registers returned %d\n",
-                              err);
-                       fatal_sigsegv();
-               }
+       err = put_fp_registers(pid, fpregs);
+       if (err < 0) {
+               printk(UM_KERN_ERR "put_fp_registers returned %d\n",
+                      err);
+               fatal_sigsegv();
        }
 }
 
@@ -193,12 +174,13 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
        handle_syscall(regs);
 }
 
-extern int __syscall_stub_start;
+extern char __syscall_stub_start[];
 
 static int userspace_tramp(void *stack)
 {
        void *addr;
-       int err;
+       int err, fd;
+       unsigned long long offset;
 
        ptrace(PTRACE_TRACEME, 0, 0, 0);
 
@@ -211,41 +193,37 @@ static int userspace_tramp(void *stack)
                exit(1);
        }
 
-       if (!proc_mm) {
-               /*
-                * This has a pte, but it can't be mapped in with the usual
-                * tlb_flush mechanism because this is part of that mechanism
-                */
-               int fd;
-               unsigned long long offset;
-               fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
-               addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE,
-                             PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
+       /*
+        * This has a pte, but it can't be mapped in with the usual
+        * tlb_flush mechanism because this is part of that mechanism
+        */
+       fd = phys_mapping(to_phys(__syscall_stub_start), &offset);
+       addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE,
+                     PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
+       if (addr == MAP_FAILED) {
+               printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, "
+                      "errno = %d\n", STUB_CODE, errno);
+               exit(1);
+       }
+
+       if (stack != NULL) {
+               fd = phys_mapping(to_phys(stack), &offset);
+               addr = mmap((void *) STUB_DATA,
+                           UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
+                           MAP_FIXED | MAP_SHARED, fd, offset);
                if (addr == MAP_FAILED) {
-                       printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, "
-                              "errno = %d\n", STUB_CODE, errno);
+                       printk(UM_KERN_ERR "mapping segfault stack "
+                              "at 0x%lx failed, errno = %d\n",
+                              STUB_DATA, errno);
                        exit(1);
                }
-
-               if (stack != NULL) {
-                       fd = phys_mapping(to_phys(stack), &offset);
-                       addr = mmap((void *) STUB_DATA,
-                                   UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
-                                   MAP_FIXED | MAP_SHARED, fd, offset);
-                       if (addr == MAP_FAILED) {
-                               printk(UM_KERN_ERR "mapping segfault stack "
-                                      "at 0x%lx failed, errno = %d\n",
-                                      STUB_DATA, errno);
-                               exit(1);
-                       }
-               }
        }
-       if (!ptrace_faultinfo && (stack != NULL)) {
+       if (stack != NULL) {
                struct sigaction sa;
 
                unsigned long v = STUB_CODE +
                                  (unsigned long) stub_segv_handler -
-                                 (unsigned long) &__syscall_stub_start;
+                                 (unsigned long) __syscall_stub_start;
 
                set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
                sigemptyset(&sa.sa_mask);
@@ -286,11 +264,7 @@ int start_userspace(unsigned long stub_stack)
 
        sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
 
-       flags = CLONE_FILES;
-       if (proc_mm)
-               flags |= CLONE_VM;
-       else
-               flags |= SIGCHLD;
+       flags = CLONE_FILES | SIGCHLD;
 
        pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
        if (pid < 0) {
@@ -409,15 +383,14 @@ void userspace(struct uml_pt_regs *regs)
                if (WIFSTOPPED(status)) {
                        int sig = WSTOPSIG(status);
 
-                       ptrace(PTRACE_GETSIGINFO, pid, 0, &si);
+                       ptrace(PTRACE_GETSIGINFO, pid, 0, (struct siginfo *)&si);
 
                        switch (sig) {
                        case SIGSEGV:
-                               if (PTRACE_FULL_FAULTINFO ||
-                                   !ptrace_faultinfo) {
+                               if (PTRACE_FULL_FAULTINFO) {
                                        get_skas_faultinfo(pid,
                                                           &regs->faultinfo);
-                                       (*sig_info[SIGSEGV])(SIGSEGV, &si,
+                                       (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si,
                                                             regs);
                                }
                                else handle_segv(pid, regs);
@@ -426,14 +399,14 @@ void userspace(struct uml_pt_regs *regs)
                                handle_trap(pid, regs, local_using_sysemu);
                                break;
                        case SIGTRAP:
-                               relay_signal(SIGTRAP, &si, regs);
+                               relay_signal(SIGTRAP, (struct siginfo *)&si, regs);
                                break;
                        case SIGVTALRM:
                                now = os_nsecs();
                                if (now < nsecs)
                                        break;
                                block_signals();
-                               (*sig_info[sig])(sig, &si, regs);
+                               (*sig_info[sig])(sig, (struct siginfo *)&si, regs);
                                unblock_signals();
                                nsecs = timer.it_value.tv_sec *
                                        UM_NSEC_PER_SEC +
@@ -447,7 +420,7 @@ void userspace(struct uml_pt_regs *regs)
                        case SIGFPE:
                        case SIGWINCH:
                                block_signals();
-                               (*sig_info[sig])(sig, &si, regs);
+                               (*sig_info[sig])(sig, (struct siginfo *)&si, regs);
                                unblock_signals();
                                break;
                        default:
@@ -474,7 +447,7 @@ static int __init init_thread_regs(void)
        /* Set parent's instruction pointer to start of clone-stub */
        thread_regs[REGS_IP_INDEX] = STUB_CODE +
                                (unsigned long) stub_clone_handler -
-                               (unsigned long) &__syscall_stub_start;
+                               (unsigned long) __syscall_stub_start;
        thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE -
                sizeof(void *);
 #ifdef __SIGNAL_FRAMESIZE
@@ -571,67 +544,6 @@ int copy_context_skas0(unsigned long new_stack, int pid)
        return err;
 }
 
-/*
- * This is used only, if stub pages are needed, while proc_mm is
- * available. Opening /proc/mm creates a new mm_context, which lacks
- * the stub-pages. Thus, we map them using /proc/mm-fd
- */
-int map_stub_pages(int fd, unsigned long code, unsigned long data,
-                  unsigned long stack)
-{
-       struct proc_mm_op mmop;
-       int n;
-       unsigned long long code_offset;
-       int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start),
-                                  &code_offset);
-
-       mmop = ((struct proc_mm_op) { .op        = MM_MMAP,
-                                     .u         =
-                                     { .mmap    =
-                                       { .addr    = code,
-                                         .len     = UM_KERN_PAGE_SIZE,
-                                         .prot    = PROT_EXEC,
-                                         .flags   = MAP_FIXED | MAP_PRIVATE,
-                                         .fd      = code_fd,
-                                         .offset  = code_offset
-       } } });
-       CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
-       if (n != sizeof(mmop)) {
-               n = errno;
-               printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, "
-                      "offset = %llx\n", code, code_fd,
-                      (unsigned long long) code_offset);
-               printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for code "
-                      "failed, err = %d\n", n);
-               return -n;
-       }
-
-       if (stack) {
-               unsigned long long map_offset;
-               int map_fd = phys_mapping(to_phys((void *)stack), &map_offset);
-               mmop = ((struct proc_mm_op)
-                               { .op        = MM_MMAP,
-                                 .u         =
-                                 { .mmap    =
-                                   { .addr    = data,
-                                     .len     = UM_KERN_PAGE_SIZE,
-                                     .prot    = PROT_READ | PROT_WRITE,
-                                     .flags   = MAP_FIXED | MAP_SHARED,
-                                     .fd      = map_fd,
-                                     .offset  = map_offset
-               } } });
-               CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
-               if (n != sizeof(mmop)) {
-                       n = errno;
-                       printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for "
-                              "data failed, err = %d\n", n);
-                       return -n;
-               }
-       }
-
-       return 0;
-}
-
 void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
 {
        (*buf)[0].JB_IP = (unsigned long) handler;
@@ -674,7 +586,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
        n = setjmp(initial_jmpbuf);
        switch (n) {
        case INIT_JMP_NEW_THREAD:
-               (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
+               (*switch_buf)[0].JB_IP = (unsigned long) uml_finishsetup;
                (*switch_buf)[0].JB_SP = (unsigned long) stack +
                        UM_THREAD_SIZE - sizeof(void *);
                break;
@@ -728,17 +640,5 @@ void reboot_skas(void)
 
 void __switch_mm(struct mm_id *mm_idp)
 {
-       int err;
-
-       /* FIXME: need cpu pid in __switch_mm */
-       if (proc_mm) {
-               err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
-                            mm_idp->u.mm_fd);
-               if (err) {
-                       printk(UM_KERN_ERR "__switch_mm - PTRACE_SWITCH_MM "
-                              "failed, errno = %d\n", errno);
-                       fatal_sigsegv();
-               }
-       }
-       else userspace_pid[0] = mm_idp->u.pid;
+       userspace_pid[0] = mm_idp->u.pid;
 }