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