Home | History | Annotate | Download | only in target-i386
      1 #include <sys/types.h>
      2 #include <sys/ioctl.h>
      3 #include "qemu-common.h"
      4 
      5 #ifdef CONFIG_KVM_GS_RESTORE
      6 
      7 #define INVALID_GS_REG  0xffff
      8 #define KVM_GS_RESTORE_NODETECTED 0x1
      9 #define KVM_GS_RESTORE_NO 0x2
     10 #define KVM_GS_RESTORE_YES 0x3
     11 int initial_gs = INVALID_GS_REG;
     12 int gs_need_restore = KVM_GS_RESTORE_NODETECTED;
     13 
     14 static void restoregs(int gs)
     15 {
     16     asm("movl %0, %%gs"::"r"(gs));
     17 }
     18 
     19 static unsigned int _getgs()
     20 {
     21     unsigned int gs = 0;
     22     asm("movl %%gs,%0" :"=r"(gs):);
     23     return gs;
     24 }
     25 
     26 /* No fprintf or any system call before the gs is restored successfully */
     27 static void check_and_restore_gs(void)
     28 {
     29     if (gs_need_restore == KVM_GS_RESTORE_NO)
     30         return;
     31 
     32     restoregs(initial_gs);
     33 }
     34 
     35 static struct sigaction old_alarm_act, old_gio_act, old_pipe_act,old_usr1_act, old_chld_act;
     36 static void temp_sig_handler(int host_signum)
     37 {
     38     /* !!! must restore gs firstly */
     39     check_and_restore_gs();
     40     switch (host_signum)
     41     {
     42     case SIGALRM:
     43         old_alarm_act.sa_handler(host_signum);
     44         break;
     45 
     46     case SIGIO:
     47         old_gio_act.sa_handler(host_signum);
     48         break;
     49 
     50     case SIGUSR1:
     51         old_usr1_act.sa_handler(host_signum);
     52         break;
     53 
     54     case SIGPIPE:
     55         old_pipe_act.sa_handler(host_signum);
     56         break;
     57 
     58     case SIGCHLD:
     59         old_chld_act.sa_handler(host_signum);
     60         break;
     61 
     62     default:
     63         fprintf(stderr, "Not take signal %x!!\n", host_signum);
     64         break;
     65     }
     66 }
     67 
     68 static int sig_taken = 0;
     69 static int take_signal_handler(void)
     70 {
     71     struct sigaction act;
     72     int ret;
     73 
     74     if (gs_need_restore == KVM_GS_RESTORE_NO)
     75         return 0;
     76     if (sig_taken)
     77         return 0;
     78 
     79     sig_taken = 1;
     80     sigfillset(&act.sa_mask);
     81     act.sa_flags = 0;
     82     act.sa_handler = temp_sig_handler;
     83     /* Did we missed any other signal ? */
     84     sigaction(SIGALRM, &act, &old_alarm_act);
     85     sigaction(SIGIO, &act, &old_gio_act);
     86     sigaction(SIGUSR1, &act, &old_usr1_act);
     87     sigaction(SIGPIPE, &act, &old_pipe_act);
     88     act.sa_flags = SA_NOCLDSTOP;
     89     sigaction(SIGCHLD, &act, &old_chld_act);
     90     return 1;
     91 }
     92 
     93 int gs_base_pre_run(void)
     94 {
     95     if (unlikely(initial_gs == INVALID_GS_REG) )
     96     {
     97         initial_gs = _getgs();
     98         /*
     99          * As 2.6.35-28 lucid will get correct gs but clobbered GS_BASE
    100          * we have to always re-write the gs base
    101          */
    102         if (initial_gs == 0x0)
    103             gs_need_restore = KVM_GS_RESTORE_NO;
    104         else
    105             gs_need_restore = KVM_GS_RESTORE_YES;
    106     }
    107 
    108     take_signal_handler();
    109     return 0;
    110 }
    111 
    112 int gs_base_post_run(void)
    113 {
    114     check_and_restore_gs();
    115     return 0;
    116 }
    117 
    118 /*
    119  * ioctl may update errno, which is in thread local storage and
    120  * requires gs register, we have to provide our own ioctl
    121  * XXX should "call %%gs:$0x10" be replaced with call to vsyscall
    122  * page, which is more generic and clean?
    123  */
    124 int no_gs_ioctl(int fd, int type, void *arg)
    125 {
    126     int ret=0;
    127 
    128     asm(
    129       "movl %3, %%edx;\n"
    130       "movl %2, %%ecx;\n"
    131       "movl %1, %%ebx;\n"
    132       "movl $0x36, %%eax;\n"
    133       "call *%%gs:0x10;\n"
    134       "movl %%eax, %0\n"
    135       : "=m"(ret)
    136       :"m"(fd),"m"(type),"m"(arg)
    137       :"%edx","%ecx","%eax","%ebx"
    138       );
    139 
    140     return ret;
    141 }
    142 
    143 #endif
    144 
    145