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