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 struct sigact_status 36 { 37 unsigned int sigaction:1; 38 __sighandler_t old_handler; 39 void (*old_sigaction) (int, siginfo_t *, void *); 40 }; 41 static struct sigact_status o_sigact[SIGUNUSED]; 42 43 static void temp_sig_handler(int signum) 44 { 45 /* !!! must restore gs firstly */ 46 check_and_restore_gs(); 47 48 if (signum < SIGHUP || signum >= SIGUNUSED) 49 { 50 fprintf(stderr, "Invalid signal %x in temp_sig_handler\n", signum); 51 abort(); 52 } 53 54 if ( !o_sigact[signum].sigaction && o_sigact[signum].old_handler) 55 o_sigact[signum].old_handler(signum); 56 else 57 { 58 fprintf(stderr, "Invalid signal in temp_sig_handler: " 59 "signal %x sa_info %s!!\n", 60 signum, o_sigact[signum].sigaction ? "set":"not set" ); 61 abort(); 62 } 63 } 64 65 static void temp_sig_sigaction(int signum, siginfo_t *info, void *ucontext) 66 { 67 /* !!! must restore gs firstly */ 68 check_and_restore_gs(); 69 70 if (signum < SIGHUP || signum >= SIGUNUSED) 71 { 72 fprintf(stderr, "Invalid signal %x in temp_sig_sigaction\n", signum); 73 abort(); 74 } 75 76 if ( o_sigact[signum].sigaction && o_sigact[signum].old_sigaction ) 77 o_sigact[signum].old_sigaction(signum, info, ucontext); 78 else 79 { 80 fprintf(stderr, "Invalid signal in temp_sig_sigaction: " 81 "signal %x sa_info %s!!\n", 82 signum, o_sigact[signum].sigaction ? "set":"not set" ); 83 abort(); 84 } 85 } 86 87 static int sig_taken = 0; 88 89 static int take_signal_handler(void) 90 { 91 int i; 92 93 if (gs_need_restore == KVM_GS_RESTORE_NO) 94 return 0; 95 if (sig_taken) 96 return 0; 97 98 memset(o_sigact, 0, sizeof(o_sigact)); 99 100 /* SIGHUP is 1 in POSIX */ 101 for (i = SIGHUP; i < SIGUNUSED; i++) 102 { 103 int sigret; 104 struct sigaction act, old_act; 105 106 sigret = sigaction(i, NULL, &old_act); 107 if (sigret) 108 continue; 109 /* We don't need take the handler for default or ignore signals */ 110 if ( !(old_act.sa_flags & SA_SIGINFO) && 111 ((old_act.sa_handler == SIG_IGN ) || 112 (old_act.sa_handler == SIG_DFL))) 113 continue; 114 115 memcpy(&act, &old_act, sizeof(struct sigaction)); 116 117 if (old_act.sa_flags & SA_SIGINFO) 118 { 119 o_sigact[i].old_sigaction = old_act.sa_sigaction; 120 o_sigact[i].sigaction = 1; 121 act.sa_sigaction = temp_sig_sigaction; 122 } 123 else 124 { 125 o_sigact[i].old_handler = old_act.sa_handler; 126 act.sa_handler = temp_sig_handler; 127 } 128 129 sigaction(i, &act, NULL); 130 continue; 131 } 132 sig_taken = 1; 133 return 1; 134 } 135 136 int gs_base_pre_run(void) 137 { 138 if (unlikely(initial_gs == INVALID_GS_REG) ) 139 { 140 initial_gs = _getgs(); 141 /* 142 * As 2.6.35-28 lucid will get correct gs but clobbered GS_BASE 143 * we have to always re-write the gs base 144 */ 145 if (initial_gs == 0x0) 146 gs_need_restore = KVM_GS_RESTORE_NO; 147 else 148 gs_need_restore = KVM_GS_RESTORE_YES; 149 } 150 151 take_signal_handler(); 152 return 0; 153 } 154 155 int gs_base_post_run(void) 156 { 157 check_and_restore_gs(); 158 return 0; 159 } 160 161 /* 162 * ioctl may update errno, which is in thread local storage and 163 * requires gs register, we have to provide our own ioctl 164 * XXX should "call %%gs:$0x10" be replaced with call to vsyscall 165 * page, which is more generic and clean? 166 */ 167 int no_gs_ioctl(int fd, int type, void *arg) 168 { 169 int ret=0; 170 171 asm( 172 "movl %3, %%edx;\n" 173 "movl %2, %%ecx;\n" 174 "movl %1, %%ebx;\n" 175 "movl $0x36, %%eax;\n" 176 "call *%%gs:0x10;\n" 177 "movl %%eax, %0\n" 178 : "=m"(ret) 179 :"m"(fd),"m"(type),"m"(arg) 180 :"%edx","%ecx","%eax","%ebx" 181 ); 182 183 return ret; 184 } 185 186 #endif 187 188