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