linux/arch/um/os-Linux/util.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   3 * Licensed under the GPL
   4 */
   5
   6#include <stdio.h>
   7#include <stdlib.h>
   8#include <unistd.h>
   9#include <errno.h>
  10#include <signal.h>
  11#include <string.h>
  12#include <termios.h>
  13#include <wait.h>
  14#include <sys/mman.h>
  15#include <sys/utsname.h>
  16#include <os.h>
  17
  18void stack_protections(unsigned long address)
  19{
  20        if (mprotect((void *) address, UM_THREAD_SIZE,
  21                    PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
  22                panic("protecting stack failed, errno = %d", errno);
  23}
  24
  25int raw(int fd)
  26{
  27        struct termios tt;
  28        int err;
  29
  30        CATCH_EINTR(err = tcgetattr(fd, &tt));
  31        if (err < 0)
  32                return -errno;
  33
  34        cfmakeraw(&tt);
  35
  36        CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
  37        if (err < 0)
  38                return -errno;
  39
  40        /*
  41         * XXX tcsetattr could have applied only some changes
  42         * (and cfmakeraw() is a set of changes)
  43         */
  44        return 0;
  45}
  46
  47void setup_machinename(char *machine_out)
  48{
  49        struct utsname host;
  50
  51        uname(&host);
  52#ifdef UML_CONFIG_UML_X86
  53# ifndef UML_CONFIG_64BIT
  54        if (!strcmp(host.machine, "x86_64")) {
  55                strcpy(machine_out, "i686");
  56                return;
  57        }
  58# else
  59        if (!strcmp(host.machine, "i686")) {
  60                strcpy(machine_out, "x86_64");
  61                return;
  62        }
  63# endif
  64#endif
  65        strcpy(machine_out, host.machine);
  66}
  67
  68void setup_hostinfo(char *buf, int len)
  69{
  70        struct utsname host;
  71
  72        uname(&host);
  73        snprintf(buf, len, "%s %s %s %s %s", host.sysname, host.nodename,
  74                 host.release, host.version, host.machine);
  75}
  76
  77/*
  78 * We cannot use glibc's abort(). It makes use of tgkill() which
  79 * has no effect within UML's kernel threads.
  80 * After that glibc would execute an invalid instruction to kill
  81 * the calling process and UML crashes with SIGSEGV.
  82 */
  83static inline void __attribute__ ((noreturn)) uml_abort(void)
  84{
  85        sigset_t sig;
  86
  87        fflush(NULL);
  88
  89        if (!sigemptyset(&sig) && !sigaddset(&sig, SIGABRT))
  90                sigprocmask(SIG_UNBLOCK, &sig, 0);
  91
  92        for (;;)
  93                if (kill(getpid(), SIGABRT) < 0)
  94                        exit(127);
  95}
  96
  97void os_dump_core(void)
  98{
  99        int pid;
 100
 101        signal(SIGSEGV, SIG_DFL);
 102
 103        /*
 104         * We are about to SIGTERM this entire process group to ensure that
 105         * nothing is around to run after the kernel exits.  The
 106         * kernel wants to abort, not die through SIGTERM, so we
 107         * ignore it here.
 108         */
 109
 110        signal(SIGTERM, SIG_IGN);
 111        kill(0, SIGTERM);
 112        /*
 113         * Most of the other processes associated with this UML are
 114         * likely sTopped, so give them a SIGCONT so they see the
 115         * SIGTERM.
 116         */
 117        kill(0, SIGCONT);
 118
 119        /*
 120         * Now, having sent signals to everyone but us, make sure they
 121         * die by ptrace.  Processes can survive what's been done to
 122         * them so far - the mechanism I understand is receiving a
 123         * SIGSEGV and segfaulting immediately upon return.  There is
 124         * always a SIGSEGV pending, and (I'm guessing) signals are
 125         * processed in numeric order so the SIGTERM (signal 15 vs
 126         * SIGSEGV being signal 11) is never handled.
 127         *
 128         * Run a waitpid loop until we get some kind of error.
 129         * Hopefully, it's ECHILD, but there's not a lot we can do if
 130         * it's something else.  Tell os_kill_ptraced_process not to
 131         * wait for the child to report its death because there's
 132         * nothing reasonable to do if that fails.
 133         */
 134
 135        while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0)
 136                os_kill_ptraced_process(pid, 0);
 137
 138        uml_abort();
 139}
 140
 141void um_early_printk(const char *s, unsigned int n)
 142{
 143        printf("%.*s", n, s);
 144}
 145