64 bit syscall fix
[qemu] / kqemu.c
1 /*
2  *  KQEMU support
3  * 
4  *  Copyright (c) 2005 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "config.h"
21 #ifdef _WIN32
22 #include <windows.h>
23 #include <winioctl.h>
24 #else
25 #include <sys/types.h>
26 #include <sys/mman.h>
27 #include <sys/ioctl.h>
28 #endif
29 #ifdef HOST_SOLARIS
30 #include <sys/modctl.h>
31 #endif
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #include <inttypes.h>
39
40 #include "cpu.h"
41 #include "exec-all.h"
42
43 #ifdef USE_KQEMU
44
45 #define DEBUG
46 //#define PROFILE
47
48 #include <unistd.h>
49 #include <fcntl.h>
50 #include "kqemu.h"
51
52 /* compatibility stuff */
53 #ifndef KQEMU_RET_SYSCALL
54 #define KQEMU_RET_SYSCALL   0x0300 /* syscall insn */
55 #endif
56 #ifndef KQEMU_MAX_RAM_PAGES_TO_UPDATE
57 #define KQEMU_MAX_RAM_PAGES_TO_UPDATE 512
58 #define KQEMU_RAM_PAGES_UPDATE_ALL (KQEMU_MAX_RAM_PAGES_TO_UPDATE + 1)
59 #endif
60 #ifndef KQEMU_MAX_MODIFIED_RAM_PAGES
61 #define KQEMU_MAX_MODIFIED_RAM_PAGES 512
62 #endif
63
64 #ifdef _WIN32
65 #define KQEMU_DEVICE "\\\\.\\kqemu"
66 #else
67 #define KQEMU_DEVICE "/dev/kqemu"
68 #endif
69
70 #ifdef _WIN32
71 #define KQEMU_INVALID_FD INVALID_HANDLE_VALUE
72 HANDLE kqemu_fd = KQEMU_INVALID_FD;
73 #define kqemu_closefd(x) CloseHandle(x)
74 #else
75 #define KQEMU_INVALID_FD -1
76 int kqemu_fd = KQEMU_INVALID_FD;
77 #define kqemu_closefd(x) close(x)
78 #endif
79
80 /* 0 = not allowed
81    1 = user kqemu
82    2 = kernel kqemu
83 */
84 int kqemu_allowed = 1;
85 unsigned long *pages_to_flush;
86 unsigned int nb_pages_to_flush;
87 unsigned long *ram_pages_to_update;
88 unsigned int nb_ram_pages_to_update;
89 unsigned long *modified_ram_pages;
90 unsigned int nb_modified_ram_pages;
91 uint8_t *modified_ram_pages_table;
92 extern uint32_t **l1_phys_map;
93
94 #define cpuid(index, eax, ebx, ecx, edx) \
95   asm volatile ("cpuid" \
96                 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
97                 : "0" (index))
98
99 #ifdef __x86_64__
100 static int is_cpuid_supported(void)
101 {
102     return 1;
103 }
104 #else
105 static int is_cpuid_supported(void)
106 {
107     int v0, v1;
108     asm volatile ("pushf\n"
109                   "popl %0\n"
110                   "movl %0, %1\n"
111                   "xorl $0x00200000, %0\n"
112                   "pushl %0\n"
113                   "popf\n"
114                   "pushf\n"
115                   "popl %0\n"
116                   : "=a" (v0), "=d" (v1)
117                   :
118                   : "cc");
119     return (v0 != v1);
120 }
121 #endif
122
123 static void kqemu_update_cpuid(CPUState *env)
124 {
125     int critical_features_mask, features, ext_features, ext_features_mask;
126     uint32_t eax, ebx, ecx, edx;
127
128     /* the following features are kept identical on the host and
129        target cpus because they are important for user code. Strictly
130        speaking, only SSE really matters because the OS must support
131        it if the user code uses it. */
132     critical_features_mask = 
133         CPUID_CMOV | CPUID_CX8 | 
134         CPUID_FXSR | CPUID_MMX | CPUID_SSE | 
135         CPUID_SSE2 | CPUID_SEP;
136     ext_features_mask = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR;
137     if (!is_cpuid_supported()) {
138         features = 0;
139         ext_features = 0;
140     } else {
141         cpuid(1, eax, ebx, ecx, edx);
142         features = edx;
143         ext_features = ecx;
144     }
145 #ifdef __x86_64__
146     /* NOTE: on x86_64 CPUs, SYSENTER is not supported in
147        compatibility mode, so in order to have the best performances
148        it is better not to use it */
149     features &= ~CPUID_SEP;
150 #endif
151     env->cpuid_features = (env->cpuid_features & ~critical_features_mask) |
152         (features & critical_features_mask);
153     env->cpuid_ext_features = (env->cpuid_ext_features & ~ext_features_mask) |
154         (ext_features & ext_features_mask);
155     /* XXX: we could update more of the target CPUID state so that the
156        non accelerated code sees exactly the same CPU features as the
157        accelerated code */
158 }
159
160 int kqemu_init(CPUState *env)
161 {
162     struct kqemu_init init;
163     int ret, version;
164 #ifdef _WIN32
165     DWORD temp;
166 #endif
167
168     if (!kqemu_allowed)
169         return -1;
170
171 #ifdef _WIN32
172     kqemu_fd = CreateFile(KQEMU_DEVICE, GENERIC_WRITE | GENERIC_READ,
173                           FILE_SHARE_READ | FILE_SHARE_WRITE,
174                           NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
175                           NULL);
176 #else
177     kqemu_fd = open(KQEMU_DEVICE, O_RDWR);
178 #endif
179     if (kqemu_fd == KQEMU_INVALID_FD) {
180         fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated\n", KQEMU_DEVICE);
181         return -1;
182     }
183     version = 0;
184 #ifdef _WIN32
185     DeviceIoControl(kqemu_fd, KQEMU_GET_VERSION, NULL, 0,
186                     &version, sizeof(version), &temp, NULL);
187 #else
188     ioctl(kqemu_fd, KQEMU_GET_VERSION, &version);
189 #endif
190     if (version != KQEMU_VERSION) {
191         fprintf(stderr, "Version mismatch between kqemu module and qemu (%08x %08x) - disabling kqemu use\n",
192                 version, KQEMU_VERSION);
193         goto fail;
194     }
195
196     pages_to_flush = qemu_vmalloc(KQEMU_MAX_PAGES_TO_FLUSH * 
197                                   sizeof(unsigned long));
198     if (!pages_to_flush)
199         goto fail;
200
201     ram_pages_to_update = qemu_vmalloc(KQEMU_MAX_RAM_PAGES_TO_UPDATE * 
202                                        sizeof(unsigned long));
203     if (!ram_pages_to_update)
204         goto fail;
205
206     modified_ram_pages = qemu_vmalloc(KQEMU_MAX_MODIFIED_RAM_PAGES * 
207                                       sizeof(unsigned long));
208     if (!modified_ram_pages)
209         goto fail;
210     modified_ram_pages_table = qemu_mallocz(phys_ram_size >> TARGET_PAGE_BITS);
211     if (!modified_ram_pages_table)
212         goto fail;
213
214     init.ram_base = phys_ram_base;
215     init.ram_size = phys_ram_size;
216     init.ram_dirty = phys_ram_dirty;
217     init.phys_to_ram_map = l1_phys_map;
218     init.pages_to_flush = pages_to_flush;
219 #if KQEMU_VERSION >= 0x010200
220     init.ram_pages_to_update = ram_pages_to_update;
221 #endif
222 #if KQEMU_VERSION >= 0x010300
223     init.modified_ram_pages = modified_ram_pages;
224 #endif
225 #ifdef _WIN32
226     ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &init, sizeof(init),
227                           NULL, 0, &temp, NULL) == TRUE ? 0 : -1;
228 #else
229     ret = ioctl(kqemu_fd, KQEMU_INIT, &init);
230 #endif
231     if (ret < 0) {
232         fprintf(stderr, "Error %d while initializing QEMU acceleration layer - disabling it for now\n", ret);
233     fail:
234         kqemu_closefd(kqemu_fd);
235         kqemu_fd = KQEMU_INVALID_FD;
236         return -1;
237     }
238     kqemu_update_cpuid(env);
239     env->kqemu_enabled = kqemu_allowed;
240     nb_pages_to_flush = 0;
241     nb_ram_pages_to_update = 0;
242     return 0;
243 }
244
245 void kqemu_flush_page(CPUState *env, target_ulong addr)
246 {
247 #if defined(DEBUG)
248     if (loglevel & CPU_LOG_INT) {
249         fprintf(logfile, "kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr);
250     }
251 #endif
252     if (nb_pages_to_flush >= KQEMU_MAX_PAGES_TO_FLUSH)
253         nb_pages_to_flush = KQEMU_FLUSH_ALL;
254     else
255         pages_to_flush[nb_pages_to_flush++] = addr;
256 }
257
258 void kqemu_flush(CPUState *env, int global)
259 {
260 #ifdef DEBUG
261     if (loglevel & CPU_LOG_INT) {
262         fprintf(logfile, "kqemu_flush:\n");
263     }
264 #endif
265     nb_pages_to_flush = KQEMU_FLUSH_ALL;
266 }
267
268 void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr)
269 {
270 #ifdef DEBUG
271     if (loglevel & CPU_LOG_INT) {
272         fprintf(logfile, "kqemu_set_notdirty: addr=%08lx\n", ram_addr);
273     }
274 #endif
275     /* we only track transitions to dirty state */
276     if (phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] != 0xff)
277         return;
278     if (nb_ram_pages_to_update >= KQEMU_MAX_RAM_PAGES_TO_UPDATE)
279         nb_ram_pages_to_update = KQEMU_RAM_PAGES_UPDATE_ALL;
280     else
281         ram_pages_to_update[nb_ram_pages_to_update++] = ram_addr;
282 }
283
284 static void kqemu_reset_modified_ram_pages(void)
285 {
286     int i;
287     unsigned long page_index;
288     
289     for(i = 0; i < nb_modified_ram_pages; i++) {
290         page_index = modified_ram_pages[i] >> TARGET_PAGE_BITS;
291         modified_ram_pages_table[page_index] = 0;
292     }
293     nb_modified_ram_pages = 0;
294 }
295
296 void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr)
297 {
298     unsigned long page_index;
299     int ret;
300 #ifdef _WIN32
301     DWORD temp;
302 #endif
303
304     page_index = ram_addr >> TARGET_PAGE_BITS;
305     if (!modified_ram_pages_table[page_index]) {
306 #if 0
307         printf("%d: modify_page=%08lx\n", nb_modified_ram_pages, ram_addr);
308 #endif
309         modified_ram_pages_table[page_index] = 1;
310         modified_ram_pages[nb_modified_ram_pages++] = ram_addr;
311         if (nb_modified_ram_pages >= KQEMU_MAX_MODIFIED_RAM_PAGES) {
312             /* flush */
313 #ifdef _WIN32
314             ret = DeviceIoControl(kqemu_fd, KQEMU_MODIFY_RAM_PAGES, 
315                                   &nb_modified_ram_pages, 
316                                   sizeof(nb_modified_ram_pages),
317                                   NULL, 0, &temp, NULL);
318 #else
319             ret = ioctl(kqemu_fd, KQEMU_MODIFY_RAM_PAGES, 
320                         &nb_modified_ram_pages);
321 #endif
322             kqemu_reset_modified_ram_pages();
323         }
324     }
325 }
326
327 struct fpstate {
328     uint16_t fpuc;
329     uint16_t dummy1;
330     uint16_t fpus;
331     uint16_t dummy2;
332     uint16_t fptag;
333     uint16_t dummy3;
334
335     uint32_t fpip;
336     uint32_t fpcs;
337     uint32_t fpoo;
338     uint32_t fpos;
339     uint8_t fpregs1[8 * 10];
340 };
341
342 struct fpxstate {
343     uint16_t fpuc;
344     uint16_t fpus;
345     uint16_t fptag;
346     uint16_t fop;
347     uint32_t fpuip;
348     uint16_t cs_sel;
349     uint16_t dummy0;
350     uint32_t fpudp;
351     uint16_t ds_sel;
352     uint16_t dummy1;
353     uint32_t mxcsr;
354     uint32_t mxcsr_mask;
355     uint8_t fpregs1[8 * 16];
356     uint8_t xmm_regs[16 * 16];
357     uint8_t dummy2[96];
358 };
359
360 static struct fpxstate fpx1 __attribute__((aligned(16)));
361
362 static void restore_native_fp_frstor(CPUState *env)
363 {
364     int fptag, i, j;
365     struct fpstate fp1, *fp = &fp1;
366     
367     fp->fpuc = env->fpuc;
368     fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
369     fptag = 0;
370     for (i=7; i>=0; i--) {
371         fptag <<= 2;
372         if (env->fptags[i]) {
373             fptag |= 3;
374         } else {
375             /* the FPU automatically computes it */
376         }
377     }
378     fp->fptag = fptag;
379     j = env->fpstt;
380     for(i = 0;i < 8; i++) {
381         memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
382         j = (j + 1) & 7;
383     }
384     asm volatile ("frstor %0" : "=m" (*fp));
385 }
386  
387 static void save_native_fp_fsave(CPUState *env)
388 {
389     int fptag, i, j;
390     uint16_t fpuc;
391     struct fpstate fp1, *fp = &fp1;
392
393     asm volatile ("fsave %0" : : "m" (*fp));
394     env->fpuc = fp->fpuc;
395     env->fpstt = (fp->fpus >> 11) & 7;
396     env->fpus = fp->fpus & ~0x3800;
397     fptag = fp->fptag;
398     for(i = 0;i < 8; i++) {
399         env->fptags[i] = ((fptag & 3) == 3);
400         fptag >>= 2;
401     }
402     j = env->fpstt;
403     for(i = 0;i < 8; i++) {
404         memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
405         j = (j + 1) & 7;
406     }
407     /* we must restore the default rounding state */
408     fpuc = 0x037f | (env->fpuc & (3 << 10));
409     asm volatile("fldcw %0" : : "m" (fpuc));
410 }
411
412 static void restore_native_fp_fxrstor(CPUState *env)
413 {
414     struct fpxstate *fp = &fpx1;
415     int i, j, fptag;
416
417     fp->fpuc = env->fpuc;
418     fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
419     fptag = 0;
420     for(i = 0; i < 8; i++)
421         fptag |= (env->fptags[i] << i);
422     fp->fptag = fptag ^ 0xff;
423
424     j = env->fpstt;
425     for(i = 0;i < 8; i++) {
426         memcpy(&fp->fpregs1[i * 16], &env->fpregs[j].d, 10);
427         j = (j + 1) & 7;
428     }
429     if (env->cpuid_features & CPUID_SSE) {
430         fp->mxcsr = env->mxcsr;
431         /* XXX: check if DAZ is not available */
432         fp->mxcsr_mask = 0xffff;
433         memcpy(fp->xmm_regs, env->xmm_regs, CPU_NB_REGS * 16);
434     }
435     asm volatile ("fxrstor %0" : "=m" (*fp));
436 }
437
438 static void save_native_fp_fxsave(CPUState *env)
439 {
440     struct fpxstate *fp = &fpx1;
441     int fptag, i, j;
442     uint16_t fpuc;
443
444     asm volatile ("fxsave %0" : : "m" (*fp));
445     env->fpuc = fp->fpuc;
446     env->fpstt = (fp->fpus >> 11) & 7;
447     env->fpus = fp->fpus & ~0x3800;
448     fptag = fp->fptag ^ 0xff;
449     for(i = 0;i < 8; i++) {
450         env->fptags[i] = (fptag >> i) & 1;
451     }
452     j = env->fpstt;
453     for(i = 0;i < 8; i++) {
454         memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 16], 10);
455         j = (j + 1) & 7;
456     }
457     if (env->cpuid_features & CPUID_SSE) {
458         env->mxcsr = fp->mxcsr;
459         memcpy(env->xmm_regs, fp->xmm_regs, CPU_NB_REGS * 16);
460     }
461
462     /* we must restore the default rounding state */
463     asm volatile ("fninit");
464     fpuc = 0x037f | (env->fpuc & (3 << 10));
465     asm volatile("fldcw %0" : : "m" (fpuc));
466 }
467
468 static int do_syscall(CPUState *env,
469                       struct kqemu_cpu_state *kenv)
470 {
471     int selector;
472     
473     selector = (env->star >> 32) & 0xffff;
474 #ifdef __x86_64__
475     if (env->hflags & HF_LMA_MASK) {
476         int code64;
477
478         env->regs[R_ECX] = kenv->next_eip;
479         env->regs[11] = env->eflags;
480
481         code64 = env->hflags & HF_CS64_MASK;
482
483         cpu_x86_set_cpl(env, 0);
484         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
485                                0, 0xffffffff, 
486                                DESC_G_MASK | DESC_P_MASK |
487                                DESC_S_MASK |
488                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
489         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
490                                0, 0xffffffff,
491                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
492                                DESC_S_MASK |
493                                DESC_W_MASK | DESC_A_MASK);
494         env->eflags &= ~env->fmask;
495         if (code64)
496             env->eip = env->lstar;
497         else
498             env->eip = env->cstar;
499     } else 
500 #endif
501     {
502         env->regs[R_ECX] = (uint32_t)kenv->next_eip;
503         
504         cpu_x86_set_cpl(env, 0);
505         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
506                            0, 0xffffffff, 
507                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
508                                DESC_S_MASK |
509                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
510         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
511                                0, 0xffffffff,
512                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
513                                DESC_S_MASK |
514                                DESC_W_MASK | DESC_A_MASK);
515         env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
516         env->eip = (uint32_t)env->star;
517     }
518     return 2;
519 }
520
521 #ifdef CONFIG_PROFILER
522
523 #define PC_REC_SIZE 1
524 #define PC_REC_HASH_BITS 16
525 #define PC_REC_HASH_SIZE (1 << PC_REC_HASH_BITS)
526
527 typedef struct PCRecord {
528     unsigned long pc;
529     int64_t count;
530     struct PCRecord *next;
531 } PCRecord;
532
533 static PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];
534 static int nb_pc_records;
535
536 static void kqemu_record_pc(unsigned long pc)
537 {
538     unsigned long h;
539     PCRecord **pr, *r;
540
541     h = pc / PC_REC_SIZE;
542     h = h ^ (h >> PC_REC_HASH_BITS);
543     h &= (PC_REC_HASH_SIZE - 1);
544     pr = &pc_rec_hash[h];
545     for(;;) {
546         r = *pr;
547         if (r == NULL)
548             break;
549         if (r->pc == pc) {
550             r->count++;
551             return;
552         }
553         pr = &r->next;
554     }
555     r = malloc(sizeof(PCRecord));
556     r->count = 1;
557     r->pc = pc;
558     r->next = NULL;
559     *pr = r;
560     nb_pc_records++;
561 }
562
563 static int pc_rec_cmp(const void *p1, const void *p2)
564 {
565     PCRecord *r1 = *(PCRecord **)p1;
566     PCRecord *r2 = *(PCRecord **)p2;
567     if (r1->count < r2->count)
568         return 1;
569     else if (r1->count == r2->count)
570         return 0;
571     else
572         return -1;
573 }
574
575 static void kqemu_record_flush(void)
576 {
577     PCRecord *r, *r_next;
578     int h;
579
580     for(h = 0; h < PC_REC_HASH_SIZE; h++) {
581         for(r = pc_rec_hash[h]; r != NULL; r = r_next) {
582             r_next = r->next;
583             free(r);
584         }
585         pc_rec_hash[h] = NULL;
586     }
587     nb_pc_records = 0;
588 }
589
590 void kqemu_record_dump(void)
591 {
592     PCRecord **pr, *r;
593     int i, h;
594     FILE *f;
595     int64_t total, sum;
596
597     pr = malloc(sizeof(PCRecord *) * nb_pc_records);
598     i = 0;
599     total = 0;
600     for(h = 0; h < PC_REC_HASH_SIZE; h++) {
601         for(r = pc_rec_hash[h]; r != NULL; r = r->next) {
602             pr[i++] = r;
603             total += r->count;
604         }
605     }
606     qsort(pr, nb_pc_records, sizeof(PCRecord *), pc_rec_cmp);
607     
608     f = fopen("/tmp/kqemu.stats", "w");
609     if (!f) {
610         perror("/tmp/kqemu.stats");
611         exit(1);
612     }
613     fprintf(f, "total: %" PRId64 "\n", total);
614     sum = 0;
615     for(i = 0; i < nb_pc_records; i++) {
616         r = pr[i];
617         sum += r->count;
618         fprintf(f, "%08lx: %" PRId64 " %0.2f%% %0.2f%%\n", 
619                 r->pc, 
620                 r->count, 
621                 (double)r->count / (double)total * 100.0,
622                 (double)sum / (double)total * 100.0);
623     }
624     fclose(f);
625     free(pr);
626
627     kqemu_record_flush();
628 }
629 #endif
630
631 int kqemu_cpu_exec(CPUState *env)
632 {
633     struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;
634     int ret, cpl, i;
635 #ifdef CONFIG_PROFILER
636     int64_t ti;
637 #endif
638
639 #ifdef _WIN32
640     DWORD temp;
641 #endif
642
643 #ifdef CONFIG_PROFILER
644     ti = profile_getclock();
645 #endif
646 #ifdef DEBUG
647     if (loglevel & CPU_LOG_INT) {
648         fprintf(logfile, "kqemu: cpu_exec: enter\n");
649         cpu_dump_state(env, logfile, fprintf, 0);
650     }
651 #endif
652     memcpy(kenv->regs, env->regs, sizeof(kenv->regs));
653     kenv->eip = env->eip;
654     kenv->eflags = env->eflags;
655     memcpy(&kenv->segs, &env->segs, sizeof(env->segs));
656     memcpy(&kenv->ldt, &env->ldt, sizeof(env->ldt));
657     memcpy(&kenv->tr, &env->tr, sizeof(env->tr));
658     memcpy(&kenv->gdt, &env->gdt, sizeof(env->gdt));
659     memcpy(&kenv->idt, &env->idt, sizeof(env->idt));
660     kenv->cr0 = env->cr[0];
661     kenv->cr2 = env->cr[2];
662     kenv->cr3 = env->cr[3];
663     kenv->cr4 = env->cr[4];
664     kenv->a20_mask = env->a20_mask;
665 #if KQEMU_VERSION >= 0x010100
666     kenv->efer = env->efer;
667 #endif
668 #if KQEMU_VERSION >= 0x010300
669     kenv->tsc_offset = 0;
670     kenv->star = env->star;
671     kenv->sysenter_cs = env->sysenter_cs;
672     kenv->sysenter_esp = env->sysenter_esp;
673     kenv->sysenter_eip = env->sysenter_eip;
674 #ifdef __x86_64__
675     kenv->lstar = env->lstar;
676     kenv->cstar = env->cstar;
677     kenv->fmask = env->fmask;
678     kenv->kernelgsbase = env->kernelgsbase;
679 #endif
680 #endif
681     if (env->dr[7] & 0xff) {
682         kenv->dr7 = env->dr[7];
683         kenv->dr0 = env->dr[0];
684         kenv->dr1 = env->dr[1];
685         kenv->dr2 = env->dr[2];
686         kenv->dr3 = env->dr[3];
687     } else {
688         kenv->dr7 = 0;
689     }
690     kenv->dr6 = env->dr[6];
691     cpl = (env->hflags & HF_CPL_MASK);
692     kenv->cpl = cpl;
693     kenv->nb_pages_to_flush = nb_pages_to_flush;
694 #if KQEMU_VERSION >= 0x010200
695     kenv->user_only = (env->kqemu_enabled == 1);
696     kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;
697 #endif
698     nb_ram_pages_to_update = 0;
699     
700 #if KQEMU_VERSION >= 0x010300
701     kenv->nb_modified_ram_pages = nb_modified_ram_pages;
702 #endif
703     kqemu_reset_modified_ram_pages();
704
705     if (env->cpuid_features & CPUID_FXSR)
706         restore_native_fp_fxrstor(env);
707     else
708         restore_native_fp_frstor(env);
709
710 #ifdef _WIN32
711     if (DeviceIoControl(kqemu_fd, KQEMU_EXEC,
712                         kenv, sizeof(struct kqemu_cpu_state),
713                         kenv, sizeof(struct kqemu_cpu_state),
714                         &temp, NULL)) {
715         ret = kenv->retval;
716     } else {
717         ret = -1;
718     }
719 #else
720 #if KQEMU_VERSION >= 0x010100
721     ioctl(kqemu_fd, KQEMU_EXEC, kenv);
722     ret = kenv->retval;
723 #else
724     ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);
725 #endif
726 #endif
727     if (env->cpuid_features & CPUID_FXSR)
728         save_native_fp_fxsave(env);
729     else
730         save_native_fp_fsave(env);
731
732     memcpy(env->regs, kenv->regs, sizeof(env->regs));
733     env->eip = kenv->eip;
734     env->eflags = kenv->eflags;
735     memcpy(env->segs, kenv->segs, sizeof(env->segs));
736     cpu_x86_set_cpl(env, kenv->cpl);
737     memcpy(&env->ldt, &kenv->ldt, sizeof(env->ldt));
738 #if 0
739     /* no need to restore that */
740     memcpy(env->tr, kenv->tr, sizeof(env->tr));
741     memcpy(env->gdt, kenv->gdt, sizeof(env->gdt));
742     memcpy(env->idt, kenv->idt, sizeof(env->idt));
743     env->a20_mask = kenv->a20_mask;
744 #endif
745     env->cr[0] = kenv->cr0;
746     env->cr[4] = kenv->cr4;
747     env->cr[3] = kenv->cr3;
748     env->cr[2] = kenv->cr2;
749     env->dr[6] = kenv->dr6;
750 #if KQEMU_VERSION >= 0x010300
751 #ifdef __x86_64__
752     env->kernelgsbase = kenv->kernelgsbase;
753 #endif
754 #endif
755
756     /* flush pages as indicated by kqemu */
757     if (kenv->nb_pages_to_flush >= KQEMU_FLUSH_ALL) {
758         tlb_flush(env, 1);
759     } else {
760         for(i = 0; i < kenv->nb_pages_to_flush; i++) {
761             tlb_flush_page(env, pages_to_flush[i]);
762         }
763     }
764     nb_pages_to_flush = 0;
765
766 #ifdef CONFIG_PROFILER
767     kqemu_time += profile_getclock() - ti;
768     kqemu_exec_count++;
769 #endif
770
771 #if KQEMU_VERSION >= 0x010200
772     if (kenv->nb_ram_pages_to_update > 0) {
773         cpu_tlb_update_dirty(env);
774     }
775 #endif
776
777 #if KQEMU_VERSION >= 0x010300
778     if (kenv->nb_modified_ram_pages > 0) {
779         for(i = 0; i < kenv->nb_modified_ram_pages; i++) {
780             unsigned long addr;
781             addr = modified_ram_pages[i];
782             tb_invalidate_phys_page_range(addr, addr + TARGET_PAGE_SIZE, 0);
783         }
784     }
785 #endif
786
787     /* restore the hidden flags */
788     {
789         unsigned int new_hflags;
790 #ifdef TARGET_X86_64
791         if ((env->hflags & HF_LMA_MASK) && 
792             (env->segs[R_CS].flags & DESC_L_MASK)) {
793             /* long mode */
794             new_hflags = HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
795         } else
796 #endif
797         {
798             /* legacy / compatibility case */
799             new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
800                 >> (DESC_B_SHIFT - HF_CS32_SHIFT);
801             new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK)
802                 >> (DESC_B_SHIFT - HF_SS32_SHIFT);
803             if (!(env->cr[0] & CR0_PE_MASK) || 
804                    (env->eflags & VM_MASK) ||
805                    !(env->hflags & HF_CS32_MASK)) {
806                 /* XXX: try to avoid this test. The problem comes from the
807                    fact that is real mode or vm86 mode we only modify the
808                    'base' and 'selector' fields of the segment cache to go
809                    faster. A solution may be to force addseg to one in
810                    translate-i386.c. */
811                 new_hflags |= HF_ADDSEG_MASK;
812             } else {
813                 new_hflags |= ((env->segs[R_DS].base | 
814                                 env->segs[R_ES].base |
815                                 env->segs[R_SS].base) != 0) << 
816                     HF_ADDSEG_SHIFT;
817             }
818         }
819         env->hflags = (env->hflags & 
820            ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |
821             new_hflags;
822     }
823     /* update FPU flags */
824     env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
825         ((env->cr[0] << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
826     if (env->cr[4] & CR4_OSFXSR_MASK)
827         env->hflags |= HF_OSFXSR_MASK;
828     else
829         env->hflags &= ~HF_OSFXSR_MASK;
830         
831 #ifdef DEBUG
832     if (loglevel & CPU_LOG_INT) {
833         fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
834     }
835 #endif
836     if (ret == KQEMU_RET_SYSCALL) {
837         /* syscall instruction */
838         return do_syscall(env, kenv);
839     } else 
840     if ((ret & 0xff00) == KQEMU_RET_INT) {
841         env->exception_index = ret & 0xff;
842         env->error_code = 0;
843         env->exception_is_int = 1;
844         env->exception_next_eip = kenv->next_eip;
845 #ifdef CONFIG_PROFILER
846         kqemu_ret_int_count++;
847 #endif
848 #ifdef DEBUG
849         if (loglevel & CPU_LOG_INT) {
850             fprintf(logfile, "kqemu: interrupt v=%02x:\n", 
851                     env->exception_index);
852             cpu_dump_state(env, logfile, fprintf, 0);
853         }
854 #endif
855         return 1;
856     } else if ((ret & 0xff00) == KQEMU_RET_EXCEPTION) {
857         env->exception_index = ret & 0xff;
858         env->error_code = kenv->error_code;
859         env->exception_is_int = 0;
860         env->exception_next_eip = 0;
861 #ifdef CONFIG_PROFILER
862         kqemu_ret_excp_count++;
863 #endif
864 #ifdef DEBUG
865         if (loglevel & CPU_LOG_INT) {
866             fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n",
867                     env->exception_index, env->error_code);
868             cpu_dump_state(env, logfile, fprintf, 0);
869         }
870 #endif
871         return 1;
872     } else if (ret == KQEMU_RET_INTR) {
873 #ifdef CONFIG_PROFILER
874         kqemu_ret_intr_count++;
875 #endif
876 #ifdef DEBUG
877         if (loglevel & CPU_LOG_INT) {
878             cpu_dump_state(env, logfile, fprintf, 0);
879         }
880 #endif
881         return 0;
882     } else if (ret == KQEMU_RET_SOFTMMU) { 
883 #ifdef CONFIG_PROFILER
884         {
885             unsigned long pc = env->eip + env->segs[R_CS].base;
886             kqemu_record_pc(pc);
887         }
888 #endif
889 #ifdef DEBUG
890         if (loglevel & CPU_LOG_INT) {
891             cpu_dump_state(env, logfile, fprintf, 0);
892         }
893 #endif
894         return 2;
895     } else {
896         cpu_dump_state(env, stderr, fprintf, 0);
897         fprintf(stderr, "Unsupported return value: 0x%x\n", ret);
898         exit(1);
899     }
900     return 0;
901 }
902
903 void kqemu_cpu_interrupt(CPUState *env)
904 {
905 #if defined(_WIN32) && KQEMU_VERSION >= 0x010101
906     /* cancelling the I/O request causes KQEMU to finish executing the 
907        current block and successfully returning. */
908     CancelIo(kqemu_fd);
909 #endif
910 }
911
912 #endif