0001
0002
0003
0004
0005
0006 #include <signal.h>
0007 #include <kern_util.h>
0008 #include <longjmp.h>
0009 #include <sysdep/ptrace.h>
0010 #include <generated/asm-offsets.h>
0011
0012
0013 static int host_has_cmov = 1;
0014 static jmp_buf cmov_test_return;
0015
0016 static void cmov_sigill_test_handler(int sig)
0017 {
0018 host_has_cmov = 0;
0019 longjmp(cmov_test_return, 1);
0020 }
0021
0022 void arch_check_bugs(void)
0023 {
0024 struct sigaction old, new;
0025
0026 printk(UM_KERN_INFO "Checking for host processor cmov support...");
0027 new.sa_handler = cmov_sigill_test_handler;
0028
0029
0030 new.sa_flags = SA_NODEFER;
0031 sigemptyset(&new.sa_mask);
0032 sigaction(SIGILL, &new, &old);
0033
0034 if (setjmp(cmov_test_return) == 0) {
0035 unsigned long foo = 0;
0036 __asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
0037 printk(UM_KERN_CONT "Yes\n");
0038 } else
0039 printk(UM_KERN_CONT "No\n");
0040
0041 sigaction(SIGILL, &old, &new);
0042 }
0043
0044 void arch_examine_signal(int sig, struct uml_pt_regs *regs)
0045 {
0046 unsigned char tmp[2];
0047
0048
0049
0050
0051
0052 if ((sig != SIGILL) || (get_current_pid() != 1))
0053 return;
0054
0055 if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
0056 printk(UM_KERN_ERR "SIGILL in init, could not read "
0057 "instructions!\n");
0058 return;
0059 }
0060
0061 if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
0062 return;
0063
0064 if (host_has_cmov == 0)
0065 printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
0066 "processor doesn't implement. Boot a filesystem "
0067 "compiled for older processors");
0068 else if (host_has_cmov == 1)
0069 printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
0070 "processor claims to implement");
0071 else
0072 printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
0073 host_has_cmov);
0074 }