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