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