linux/arch/um/sys-i386/bugs.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   3 * Licensed under the GPL
   4 */
   5
   6#include <signal.h>
   7#include "kern_constants.h"
   8#include "kern_util.h"
   9#include "longjmp.h"
  10#include "task.h"
  11#include "user.h"
  12#include "sysdep/ptrace.h"
  13
  14/* Set during early boot */
  15static int host_has_cmov = 1;
  16static jmp_buf cmov_test_return;
  17
  18static void cmov_sigill_test_handler(int sig)
  19{
  20        host_has_cmov = 0;
  21        longjmp(cmov_test_return, 1);
  22}
  23
  24void arch_check_bugs(void)
  25{
  26        struct sigaction old, new;
  27
  28        printk(UM_KERN_INFO "Checking for host processor cmov support...");
  29        new.sa_handler = cmov_sigill_test_handler;
  30
  31        /* Make sure that SIGILL is enabled after the handler longjmps back */
  32        new.sa_flags = SA_NODEFER;
  33        sigemptyset(&new.sa_mask);
  34        sigaction(SIGILL, &new, &old);
  35
  36        if (setjmp(cmov_test_return) == 0) {
  37                unsigned long foo = 0;
  38                __asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
  39                printk(UM_KERN_CONT "Yes\n");
  40        } else
  41                printk(UM_KERN_CONT "No\n");
  42
  43        sigaction(SIGILL, &old, &new);
  44}
  45
  46void arch_examine_signal(int sig, struct uml_pt_regs *regs)
  47{
  48        unsigned char tmp[2];
  49
  50        /*
  51         * This is testing for a cmov (0x0f 0x4x) instruction causing a
  52         * SIGILL in init.
  53         */
  54        if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
  55                return;
  56
  57        if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
  58                printk(UM_KERN_ERR "SIGILL in init, could not read "
  59                       "instructions!\n");
  60                return;
  61        }
  62
  63        if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
  64                return;
  65
  66        if (host_has_cmov == 0)
  67                printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
  68                       "processor doesn't implement.  Boot a filesystem "
  69                       "compiled for older processors");
  70        else if (host_has_cmov == 1)
  71                printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
  72                       "processor claims to implement");
  73        else
  74                printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
  75                        host_has_cmov);
  76}
  77