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