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