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