Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
0004  * Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
0005  */
0006 
0007 #include <stdlib.h>
0008 #include <stdbool.h>
0009 #include <unistd.h>
0010 #include <sched.h>
0011 #include <errno.h>
0012 #include <string.h>
0013 #include <sys/mman.h>
0014 #include <sys/wait.h>
0015 #include <asm/unistd.h>
0016 #include <as-layout.h>
0017 #include <init.h>
0018 #include <kern_util.h>
0019 #include <mem.h>
0020 #include <os.h>
0021 #include <ptrace_user.h>
0022 #include <registers.h>
0023 #include <skas.h>
0024 #include <sysdep/stub.h>
0025 #include <linux/threads.h>
0026 
0027 int is_skas_winch(int pid, int fd, void *data)
0028 {
0029     return pid == getpgrp();
0030 }
0031 
0032 static const char *ptrace_reg_name(int idx)
0033 {
0034 #define R(n) case HOST_##n: return #n
0035 
0036     switch (idx) {
0037 #ifdef __x86_64__
0038     R(BX);
0039     R(CX);
0040     R(DI);
0041     R(SI);
0042     R(DX);
0043     R(BP);
0044     R(AX);
0045     R(R8);
0046     R(R9);
0047     R(R10);
0048     R(R11);
0049     R(R12);
0050     R(R13);
0051     R(R14);
0052     R(R15);
0053     R(ORIG_AX);
0054     R(CS);
0055     R(SS);
0056     R(EFLAGS);
0057 #elif defined(__i386__)
0058     R(IP);
0059     R(SP);
0060     R(EFLAGS);
0061     R(AX);
0062     R(BX);
0063     R(CX);
0064     R(DX);
0065     R(SI);
0066     R(DI);
0067     R(BP);
0068     R(CS);
0069     R(SS);
0070     R(DS);
0071     R(FS);
0072     R(ES);
0073     R(GS);
0074     R(ORIG_AX);
0075 #endif
0076     }
0077     return "";
0078 }
0079 
0080 static int ptrace_dump_regs(int pid)
0081 {
0082     unsigned long regs[MAX_REG_NR];
0083     int i;
0084 
0085     if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
0086         return -errno;
0087 
0088     printk(UM_KERN_ERR "Stub registers -\n");
0089     for (i = 0; i < ARRAY_SIZE(regs); i++) {
0090         const char *regname = ptrace_reg_name(i);
0091 
0092         printk(UM_KERN_ERR "\t%s\t(%2d): %lx\n", regname, i, regs[i]);
0093     }
0094 
0095     return 0;
0096 }
0097 
0098 /*
0099  * Signals that are OK to receive in the stub - we'll just continue it.
0100  * SIGWINCH will happen when UML is inside a detached screen.
0101  */
0102 #define STUB_SIG_MASK ((1 << SIGALRM) | (1 << SIGWINCH))
0103 
0104 /* Signals that the stub will finish with - anything else is an error */
0105 #define STUB_DONE_MASK (1 << SIGTRAP)
0106 
0107 void wait_stub_done(int pid)
0108 {
0109     int n, status, err;
0110 
0111     while (1) {
0112         CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
0113         if ((n < 0) || !WIFSTOPPED(status))
0114             goto bad_wait;
0115 
0116         if (((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0)
0117             break;
0118 
0119         err = ptrace(PTRACE_CONT, pid, 0, 0);
0120         if (err) {
0121             printk(UM_KERN_ERR "wait_stub_done : continue failed, "
0122                    "errno = %d\n", errno);
0123             fatal_sigsegv();
0124         }
0125     }
0126 
0127     if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
0128         return;
0129 
0130 bad_wait:
0131     err = ptrace_dump_regs(pid);
0132     if (err)
0133         printk(UM_KERN_ERR "Failed to get registers from stub, "
0134                "errno = %d\n", -err);
0135     printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, "
0136            "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno,
0137            status);
0138     fatal_sigsegv();
0139 }
0140 
0141 extern unsigned long current_stub_stack(void);
0142 
0143 static void get_skas_faultinfo(int pid, struct faultinfo *fi, unsigned long *aux_fp_regs)
0144 {
0145     int err;
0146 
0147     err = get_fp_registers(pid, aux_fp_regs);
0148     if (err < 0) {
0149         printk(UM_KERN_ERR "save_fp_registers returned %d\n",
0150                err);
0151         fatal_sigsegv();
0152     }
0153     err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
0154     if (err) {
0155         printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
0156                "errno = %d\n", pid, errno);
0157         fatal_sigsegv();
0158     }
0159     wait_stub_done(pid);
0160 
0161     /*
0162      * faultinfo is prepared by the stub_segv_handler at start of
0163      * the stub stack page. We just have to copy it.
0164      */
0165     memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
0166 
0167     err = put_fp_registers(pid, aux_fp_regs);
0168     if (err < 0) {
0169         printk(UM_KERN_ERR "put_fp_registers returned %d\n",
0170                err);
0171         fatal_sigsegv();
0172     }
0173 }
0174 
0175 static void handle_segv(int pid, struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
0176 {
0177     get_skas_faultinfo(pid, &regs->faultinfo, aux_fp_regs);
0178     segv(regs->faultinfo, 0, 1, NULL);
0179 }
0180 
0181 /*
0182  * To use the same value of using_sysemu as the caller, ask it that value
0183  * (in local_using_sysemu
0184  */
0185 static void handle_trap(int pid, struct uml_pt_regs *regs,
0186             int local_using_sysemu)
0187 {
0188     int err, status;
0189 
0190     if ((UPT_IP(regs) >= STUB_START) && (UPT_IP(regs) < STUB_END))
0191         fatal_sigsegv();
0192 
0193     if (!local_using_sysemu)
0194     {
0195         err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
0196                  __NR_getpid);
0197         if (err < 0) {
0198             printk(UM_KERN_ERR "handle_trap - nullifying syscall "
0199                    "failed, errno = %d\n", errno);
0200             fatal_sigsegv();
0201         }
0202 
0203         err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
0204         if (err < 0) {
0205             printk(UM_KERN_ERR "handle_trap - continuing to end of "
0206                    "syscall failed, errno = %d\n", errno);
0207             fatal_sigsegv();
0208         }
0209 
0210         CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
0211         if ((err < 0) || !WIFSTOPPED(status) ||
0212             (WSTOPSIG(status) != SIGTRAP + 0x80)) {
0213             err = ptrace_dump_regs(pid);
0214             if (err)
0215                 printk(UM_KERN_ERR "Failed to get registers "
0216                        "from process, errno = %d\n", -err);
0217             printk(UM_KERN_ERR "handle_trap - failed to wait at "
0218                    "end of syscall, errno = %d, status = %d\n",
0219                    errno, status);
0220             fatal_sigsegv();
0221         }
0222     }
0223 
0224     handle_syscall(regs);
0225 }
0226 
0227 extern char __syscall_stub_start[];
0228 
0229 /**
0230  * userspace_tramp() - userspace trampoline
0231  * @stack:  pointer to the new userspace stack page, can be NULL, if? FIXME:
0232  *
0233  * The userspace trampoline is used to setup a new userspace process in start_userspace() after it was clone()'ed.
0234  * This function will run on a temporary stack page.
0235  * It ptrace()'es itself, then
0236  * Two pages are mapped into the userspace address space:
0237  * - STUB_CODE (with EXEC), which contains the skas stub code
0238  * - STUB_DATA (with R/W), which contains a data page that is used to transfer certain data between the UML userspace process and the UML kernel.
0239  * Also for the userspace process a SIGSEGV handler is installed to catch pagefaults in the userspace process.
0240  * And last the process stops itself to give control to the UML kernel for this userspace process.
0241  *
0242  * Return: Always zero, otherwise the current userspace process is ended with non null exit() call
0243  */
0244 static int userspace_tramp(void *stack)
0245 {
0246     void *addr;
0247     int fd;
0248     unsigned long long offset;
0249 
0250     ptrace(PTRACE_TRACEME, 0, 0, 0);
0251 
0252     signal(SIGTERM, SIG_DFL);
0253     signal(SIGWINCH, SIG_IGN);
0254 
0255     fd = phys_mapping(uml_to_phys(__syscall_stub_start), &offset);
0256     addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE,
0257               PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
0258     if (addr == MAP_FAILED) {
0259         printk(UM_KERN_ERR "mapping mmap stub at 0x%lx failed, "
0260                "errno = %d\n", STUB_CODE, errno);
0261         exit(1);
0262     }
0263 
0264     if (stack != NULL) {
0265         fd = phys_mapping(uml_to_phys(stack), &offset);
0266         addr = mmap((void *) STUB_DATA,
0267                 UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
0268                 MAP_FIXED | MAP_SHARED, fd, offset);
0269         if (addr == MAP_FAILED) {
0270             printk(UM_KERN_ERR "mapping segfault stack "
0271                    "at 0x%lx failed, errno = %d\n",
0272                    STUB_DATA, errno);
0273             exit(1);
0274         }
0275     }
0276     if (stack != NULL) {
0277         struct sigaction sa;
0278 
0279         unsigned long v = STUB_CODE +
0280                   (unsigned long) stub_segv_handler -
0281                   (unsigned long) __syscall_stub_start;
0282 
0283         set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
0284         sigemptyset(&sa.sa_mask);
0285         sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO;
0286         sa.sa_sigaction = (void *) v;
0287         sa.sa_restorer = NULL;
0288         if (sigaction(SIGSEGV, &sa, NULL) < 0) {
0289             printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV "
0290                    "handler failed - errno = %d\n", errno);
0291             exit(1);
0292         }
0293     }
0294 
0295     kill(os_getpid(), SIGSTOP);
0296     return 0;
0297 }
0298 
0299 int userspace_pid[NR_CPUS];
0300 int kill_userspace_mm[NR_CPUS];
0301 
0302 /**
0303  * start_userspace() - prepare a new userspace process
0304  * @stub_stack: pointer to the stub stack. Can be NULL, if? FIXME:
0305  *
0306  * Setups a new temporary stack page that is used while userspace_tramp() runs
0307  * Clones the kernel process into a new userspace process, with FDs only.
0308  *
0309  * Return: When positive: the process id of the new userspace process,
0310  *         when negative: an error number.
0311  * FIXME: can PIDs become negative?!
0312  */
0313 int start_userspace(unsigned long stub_stack)
0314 {
0315     void *stack;
0316     unsigned long sp;
0317     int pid, status, n, flags, err;
0318 
0319     /* setup a temporary stack page */
0320     stack = mmap(NULL, UM_KERN_PAGE_SIZE,
0321              PROT_READ | PROT_WRITE | PROT_EXEC,
0322              MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
0323     if (stack == MAP_FAILED) {
0324         err = -errno;
0325         printk(UM_KERN_ERR "start_userspace : mmap failed, "
0326                "errno = %d\n", errno);
0327         return err;
0328     }
0329 
0330     /* set stack pointer to the end of the stack page, so it can grow downwards */
0331     sp = (unsigned long)stack + UM_KERN_PAGE_SIZE;
0332 
0333     flags = CLONE_FILES | SIGCHLD;
0334 
0335     /* clone into new userspace process */
0336     pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
0337     if (pid < 0) {
0338         err = -errno;
0339         printk(UM_KERN_ERR "start_userspace : clone failed, "
0340                "errno = %d\n", errno);
0341         return err;
0342     }
0343 
0344     do {
0345         CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
0346         if (n < 0) {
0347             err = -errno;
0348             printk(UM_KERN_ERR "start_userspace : wait failed, "
0349                    "errno = %d\n", errno);
0350             goto out_kill;
0351         }
0352     } while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGALRM));
0353 
0354     if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {
0355         err = -EINVAL;
0356         printk(UM_KERN_ERR "start_userspace : expected SIGSTOP, got "
0357                "status = %d\n", status);
0358         goto out_kill;
0359     }
0360 
0361     if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
0362            (void *) PTRACE_O_TRACESYSGOOD) < 0) {
0363         err = -errno;
0364         printk(UM_KERN_ERR "start_userspace : PTRACE_OLDSETOPTIONS "
0365                "failed, errno = %d\n", errno);
0366         goto out_kill;
0367     }
0368 
0369     if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) {
0370         err = -errno;
0371         printk(UM_KERN_ERR "start_userspace : munmap failed, "
0372                "errno = %d\n", errno);
0373         goto out_kill;
0374     }
0375 
0376     return pid;
0377 
0378  out_kill:
0379     os_kill_ptraced_process(pid, 1);
0380     return err;
0381 }
0382 
0383 void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
0384 {
0385     int err, status, op, pid = userspace_pid[0];
0386     /* To prevent races if using_sysemu changes under us.*/
0387     int local_using_sysemu;
0388     siginfo_t si;
0389 
0390     /* Handle any immediate reschedules or signals */
0391     interrupt_end();
0392 
0393     while (1) {
0394         if (kill_userspace_mm[0])
0395             fatal_sigsegv();
0396 
0397         /*
0398          * This can legitimately fail if the process loads a
0399          * bogus value into a segment register.  It will
0400          * segfault and PTRACE_GETREGS will read that value
0401          * out of the process.  However, PTRACE_SETREGS will
0402          * fail.  In this case, there is nothing to do but
0403          * just kill the process.
0404          */
0405         if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp)) {
0406             printk(UM_KERN_ERR "userspace - ptrace set regs "
0407                    "failed, errno = %d\n", errno);
0408             fatal_sigsegv();
0409         }
0410 
0411         if (put_fp_registers(pid, regs->fp)) {
0412             printk(UM_KERN_ERR "userspace - ptrace set fp regs "
0413                    "failed, errno = %d\n", errno);
0414             fatal_sigsegv();
0415         }
0416 
0417         /* Now we set local_using_sysemu to be used for one loop */
0418         local_using_sysemu = get_using_sysemu();
0419 
0420         op = SELECT_PTRACE_OPERATION(local_using_sysemu,
0421                          singlestepping(NULL));
0422 
0423         if (ptrace(op, pid, 0, 0)) {
0424             printk(UM_KERN_ERR "userspace - ptrace continue "
0425                    "failed, op = %d, errno = %d\n", op, errno);
0426             fatal_sigsegv();
0427         }
0428 
0429         CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
0430         if (err < 0) {
0431             printk(UM_KERN_ERR "userspace - wait failed, "
0432                    "errno = %d\n", errno);
0433             fatal_sigsegv();
0434         }
0435 
0436         regs->is_user = 1;
0437         if (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) {
0438             printk(UM_KERN_ERR "userspace - PTRACE_GETREGS failed, "
0439                    "errno = %d\n", errno);
0440             fatal_sigsegv();
0441         }
0442 
0443         if (get_fp_registers(pid, regs->fp)) {
0444             printk(UM_KERN_ERR "userspace -  get_fp_registers failed, "
0445                    "errno = %d\n", errno);
0446             fatal_sigsegv();
0447         }
0448 
0449         UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
0450 
0451         if (WIFSTOPPED(status)) {
0452             int sig = WSTOPSIG(status);
0453 
0454             /* These signal handlers need the si argument.
0455              * The SIGIO and SIGALARM handlers which constitute the
0456              * majority of invocations, do not use it.
0457              */
0458             switch (sig) {
0459             case SIGSEGV:
0460             case SIGTRAP:
0461             case SIGILL:
0462             case SIGBUS:
0463             case SIGFPE:
0464             case SIGWINCH:
0465                 ptrace(PTRACE_GETSIGINFO, pid, 0, (struct siginfo *)&si);
0466                 break;
0467             }
0468 
0469             switch (sig) {
0470             case SIGSEGV:
0471                 if (PTRACE_FULL_FAULTINFO) {
0472                     get_skas_faultinfo(pid,
0473                                &regs->faultinfo, aux_fp_regs);
0474                     (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si,
0475                                  regs);
0476                 }
0477                 else handle_segv(pid, regs, aux_fp_regs);
0478                 break;
0479             case SIGTRAP + 0x80:
0480                     handle_trap(pid, regs, local_using_sysemu);
0481                 break;
0482             case SIGTRAP:
0483                 relay_signal(SIGTRAP, (struct siginfo *)&si, regs);
0484                 break;
0485             case SIGALRM:
0486                 break;
0487             case SIGIO:
0488             case SIGILL:
0489             case SIGBUS:
0490             case SIGFPE:
0491             case SIGWINCH:
0492                 block_signals_trace();
0493                 (*sig_info[sig])(sig, (struct siginfo *)&si, regs);
0494                 unblock_signals_trace();
0495                 break;
0496             default:
0497                 printk(UM_KERN_ERR "userspace - child stopped "
0498                        "with signal %d\n", sig);
0499                 fatal_sigsegv();
0500             }
0501             pid = userspace_pid[0];
0502             interrupt_end();
0503 
0504             /* Avoid -ERESTARTSYS handling in host */
0505             if (PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET)
0506                 PT_SYSCALL_NR(regs->gp) = -1;
0507         }
0508     }
0509 }
0510 
0511 static unsigned long thread_regs[MAX_REG_NR];
0512 static unsigned long thread_fp_regs[FP_SIZE];
0513 
0514 static int __init init_thread_regs(void)
0515 {
0516     get_safe_registers(thread_regs, thread_fp_regs);
0517     /* Set parent's instruction pointer to start of clone-stub */
0518     thread_regs[REGS_IP_INDEX] = STUB_CODE +
0519                 (unsigned long) stub_clone_handler -
0520                 (unsigned long) __syscall_stub_start;
0521     thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE -
0522         sizeof(void *);
0523 #ifdef __SIGNAL_FRAMESIZE
0524     thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
0525 #endif
0526     return 0;
0527 }
0528 
0529 __initcall(init_thread_regs);
0530 
0531 int copy_context_skas0(unsigned long new_stack, int pid)
0532 {
0533     int err;
0534     unsigned long current_stack = current_stub_stack();
0535     struct stub_data *data = (struct stub_data *) current_stack;
0536     struct stub_data *child_data = (struct stub_data *) new_stack;
0537     unsigned long long new_offset;
0538     int new_fd = phys_mapping(uml_to_phys((void *)new_stack), &new_offset);
0539 
0540     /*
0541      * prepare offset and fd of child's stack as argument for parent's
0542      * and child's mmap2 calls
0543      */
0544     *data = ((struct stub_data) {
0545         .offset = MMAP_OFFSET(new_offset),
0546         .fd     = new_fd,
0547         .parent_err = -ESRCH,
0548         .child_err = 0,
0549     });
0550 
0551     *child_data = ((struct stub_data) {
0552         .child_err = -ESRCH,
0553     });
0554 
0555     err = ptrace_setregs(pid, thread_regs);
0556     if (err < 0) {
0557         err = -errno;
0558         printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_SETREGS "
0559                "failed, pid = %d, errno = %d\n", pid, -err);
0560         return err;
0561     }
0562 
0563     err = put_fp_registers(pid, thread_fp_regs);
0564     if (err < 0) {
0565         printk(UM_KERN_ERR "copy_context_skas0 : put_fp_registers "
0566                "failed, pid = %d, err = %d\n", pid, err);
0567         return err;
0568     }
0569 
0570     /*
0571      * Wait, until parent has finished its work: read child's pid from
0572      * parent's stack, and check, if bad result.
0573      */
0574     err = ptrace(PTRACE_CONT, pid, 0, 0);
0575     if (err) {
0576         err = -errno;
0577         printk(UM_KERN_ERR "Failed to continue new process, pid = %d, "
0578                "errno = %d\n", pid, errno);
0579         return err;
0580     }
0581 
0582     wait_stub_done(pid);
0583 
0584     pid = data->parent_err;
0585     if (pid < 0) {
0586         printk(UM_KERN_ERR "copy_context_skas0 - stub-parent reports "
0587                "error %d\n", -pid);
0588         return pid;
0589     }
0590 
0591     /*
0592      * Wait, until child has finished too: read child's result from
0593      * child's stack and check it.
0594      */
0595     wait_stub_done(pid);
0596     if (child_data->child_err != STUB_DATA) {
0597         printk(UM_KERN_ERR "copy_context_skas0 - stub-child %d reports "
0598                "error %ld\n", pid, data->child_err);
0599         err = data->child_err;
0600         goto out_kill;
0601     }
0602 
0603     if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
0604            (void *)PTRACE_O_TRACESYSGOOD) < 0) {
0605         err = -errno;
0606         printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_OLDSETOPTIONS "
0607                "failed, errno = %d\n", errno);
0608         goto out_kill;
0609     }
0610 
0611     return pid;
0612 
0613  out_kill:
0614     os_kill_ptraced_process(pid, 1);
0615     return err;
0616 }
0617 
0618 void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
0619 {
0620     (*buf)[0].JB_IP = (unsigned long) handler;
0621     (*buf)[0].JB_SP = (unsigned long) stack + UM_THREAD_SIZE -
0622         sizeof(void *);
0623 }
0624 
0625 #define INIT_JMP_NEW_THREAD 0
0626 #define INIT_JMP_CALLBACK 1
0627 #define INIT_JMP_HALT 2
0628 #define INIT_JMP_REBOOT 3
0629 
0630 void switch_threads(jmp_buf *me, jmp_buf *you)
0631 {
0632     if (UML_SETJMP(me) == 0)
0633         UML_LONGJMP(you, 1);
0634 }
0635 
0636 static jmp_buf initial_jmpbuf;
0637 
0638 /* XXX Make these percpu */
0639 static void (*cb_proc)(void *arg);
0640 static void *cb_arg;
0641 static jmp_buf *cb_back;
0642 
0643 int start_idle_thread(void *stack, jmp_buf *switch_buf)
0644 {
0645     int n;
0646 
0647     set_handler(SIGWINCH);
0648 
0649     /*
0650      * Can't use UML_SETJMP or UML_LONGJMP here because they save
0651      * and restore signals, with the possible side-effect of
0652      * trying to handle any signals which came when they were
0653      * blocked, which can't be done on this stack.
0654      * Signals must be blocked when jumping back here and restored
0655      * after returning to the jumper.
0656      */
0657     n = setjmp(initial_jmpbuf);
0658     switch (n) {
0659     case INIT_JMP_NEW_THREAD:
0660         (*switch_buf)[0].JB_IP = (unsigned long) uml_finishsetup;
0661         (*switch_buf)[0].JB_SP = (unsigned long) stack +
0662             UM_THREAD_SIZE - sizeof(void *);
0663         break;
0664     case INIT_JMP_CALLBACK:
0665         (*cb_proc)(cb_arg);
0666         longjmp(*cb_back, 1);
0667         break;
0668     case INIT_JMP_HALT:
0669         kmalloc_ok = 0;
0670         return 0;
0671     case INIT_JMP_REBOOT:
0672         kmalloc_ok = 0;
0673         return 1;
0674     default:
0675         printk(UM_KERN_ERR "Bad sigsetjmp return in "
0676                "start_idle_thread - %d\n", n);
0677         fatal_sigsegv();
0678     }
0679     longjmp(*switch_buf, 1);
0680 
0681     /* unreachable */
0682     printk(UM_KERN_ERR "impossible long jump!");
0683     fatal_sigsegv();
0684     return 0;
0685 }
0686 
0687 void initial_thread_cb_skas(void (*proc)(void *), void *arg)
0688 {
0689     jmp_buf here;
0690 
0691     cb_proc = proc;
0692     cb_arg = arg;
0693     cb_back = &here;
0694 
0695     block_signals_trace();
0696     if (UML_SETJMP(&here) == 0)
0697         UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
0698     unblock_signals_trace();
0699 
0700     cb_proc = NULL;
0701     cb_arg = NULL;
0702     cb_back = NULL;
0703 }
0704 
0705 void halt_skas(void)
0706 {
0707     block_signals_trace();
0708     UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
0709 }
0710 
0711 static bool noreboot;
0712 
0713 static int __init noreboot_cmd_param(char *str, int *add)
0714 {
0715     noreboot = true;
0716     return 0;
0717 }
0718 
0719 __uml_setup("noreboot", noreboot_cmd_param,
0720 "noreboot\n"
0721 "    Rather than rebooting, exit always, akin to QEMU's -no-reboot option.\n"
0722 "    This is useful if you're using CONFIG_PANIC_TIMEOUT in order to catch\n"
0723 "    crashes in CI\n");
0724 
0725 void reboot_skas(void)
0726 {
0727     block_signals_trace();
0728     UML_LONGJMP(&initial_jmpbuf, noreboot ? INIT_JMP_HALT : INIT_JMP_REBOOT);
0729 }
0730 
0731 void __switch_mm(struct mm_id *mm_idp)
0732 {
0733     userspace_pid[0] = mm_idp->u.pid;
0734     kill_userspace_mm[0] = mm_idp->kill;
0735 }