Convert udivx and sdivx to TCG
[qemu/malc.git] / kqemu.c
blob148a52f1cc69f5d8c1950ba2ff78f40b92ce91ce
1 /*
2 * KQEMU support
4 * Copyright (c) 2005 Fabrice Bellard
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.
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.
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
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>
41 #include "cpu.h"
42 #include "exec-all.h"
44 #ifdef USE_KQEMU
46 #define DEBUG
47 //#define PROFILE
49 #include <unistd.h>
50 #include <fcntl.h>
51 #include "kqemu.h"
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
65 #ifdef _WIN32
66 #define KQEMU_DEVICE "\\\\.\\kqemu"
67 #else
68 #define KQEMU_DEVICE "/dev/kqemu"
69 #endif
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
81 /* 0 = not allowed
82 1 = user kqemu
83 2 = kernel kqemu
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;
95 #define cpuid(index, eax, ebx, ecx, edx) \
96 asm volatile ("cpuid" \
97 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
98 : "0" (index))
100 #ifdef __x86_64__
101 static int is_cpuid_supported(void)
103 return 1;
105 #else
106 static int is_cpuid_supported(void)
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)
119 : "cc");
120 return (v0 != v1);
122 #endif
124 static void kqemu_update_cpuid(CPUState *env)
126 int critical_features_mask, features, ext_features, ext_features_mask;
127 uint32_t eax, ebx, ecx, edx;
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;
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 */
161 int kqemu_init(CPUState *env)
163 struct kqemu_init init;
164 int ret, version;
165 #ifdef _WIN32
166 DWORD temp;
167 #endif
169 if (!kqemu_allowed)
170 return -1;
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;
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;
198 pages_to_flush = qemu_vmalloc(KQEMU_MAX_PAGES_TO_FLUSH *
199 sizeof(unsigned long));
200 if (!pages_to_flush)
201 goto fail;
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;
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;
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;
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;
247 void kqemu_flush_page(CPUState *env, target_ulong addr)
249 #if defined(DEBUG)
250 if (loglevel & CPU_LOG_INT) {
251 fprintf(logfile, "kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr);
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;
260 void kqemu_flush(CPUState *env, int global)
262 #ifdef DEBUG
263 if (loglevel & CPU_LOG_INT) {
264 fprintf(logfile, "kqemu_flush:\n");
266 #endif
267 nb_pages_to_flush = KQEMU_FLUSH_ALL;
270 void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr)
272 #ifdef DEBUG
273 if (loglevel & CPU_LOG_INT) {
274 fprintf(logfile, "kqemu_set_notdirty: addr=%08lx\n", ram_addr);
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;
286 static void kqemu_reset_modified_ram_pages(void)
288 int i;
289 unsigned long page_index;
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;
295 nb_modified_ram_pages = 0;
298 void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr)
300 unsigned long page_index;
301 int ret;
302 #ifdef _WIN32
303 DWORD temp;
304 #endif
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();
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;
337 uint32_t fpip;
338 uint32_t fpcs;
339 uint32_t fpoo;
340 uint32_t fpos;
341 uint8_t fpregs1[8 * 10];
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];
362 static struct fpxstate fpx1 __attribute__((aligned(16)));
364 static void restore_native_fp_frstor(CPUState *env)
366 int fptag, i, j;
367 struct fpstate fp1, *fp = &fp1;
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 */
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;
386 asm volatile ("frstor %0" : "=m" (*fp));
389 static void save_native_fp_fsave(CPUState *env)
391 int fptag, i, j;
392 uint16_t fpuc;
393 struct fpstate fp1, *fp = &fp1;
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;
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;
409 /* we must restore the default rounding state */
410 fpuc = 0x037f | (env->fpuc & (3 << 10));
411 asm volatile("fldcw %0" : : "m" (fpuc));
414 static void restore_native_fp_fxrstor(CPUState *env)
416 struct fpxstate *fp = &fpx1;
417 int i, j, fptag;
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;
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;
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);
437 asm volatile ("fxrstor %0" : "=m" (*fp));
440 static void save_native_fp_fxsave(CPUState *env)
442 struct fpxstate *fp = &fpx1;
443 int fptag, i, j;
444 uint16_t fpuc;
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;
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;
459 if (env->cpuid_features & CPUID_SSE) {
460 env->mxcsr = fp->mxcsr;
461 memcpy(env->xmm_regs, fp->xmm_regs, CPU_NB_REGS * 16);
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));
470 static int do_syscall(CPUState *env,
471 struct kqemu_cpu_state *kenv)
473 int selector;
475 selector = (env->star >> 32) & 0xffff;
476 #ifdef __x86_64__
477 if (env->hflags & HF_LMA_MASK) {
478 int code64;
480 env->regs[R_ECX] = kenv->next_eip;
481 env->regs[11] = env->eflags;
483 code64 = env->hflags & HF_CS64_MASK;
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
504 env->regs[R_ECX] = (uint32_t)kenv->next_eip;
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;
520 return 2;
523 #ifdef CONFIG_PROFILER
525 #define PC_REC_SIZE 1
526 #define PC_REC_HASH_BITS 16
527 #define PC_REC_HASH_SIZE (1 << PC_REC_HASH_BITS)
529 typedef struct PCRecord {
530 unsigned long pc;
531 int64_t count;
532 struct PCRecord *next;
533 } PCRecord;
535 static PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];
536 static int nb_pc_records;
538 static void kqemu_record_pc(unsigned long pc)
540 unsigned long h;
541 PCRecord **pr, *r;
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;
555 pr = &r->next;
557 r = malloc(sizeof(PCRecord));
558 r->count = 1;
559 r->pc = pc;
560 r->next = NULL;
561 *pr = r;
562 nb_pc_records++;
565 static int pc_rec_cmp(const void *p1, const void *p2)
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;
577 static void kqemu_record_flush(void)
579 PCRecord *r, *r_next;
580 int h;
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);
587 pc_rec_hash[h] = NULL;
589 nb_pc_records = 0;
592 void kqemu_record_dump(void)
594 PCRecord **pr, *r;
595 int i, h;
596 FILE *f;
597 int64_t total, sum;
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;
608 qsort(pr, nb_pc_records, sizeof(PCRecord *), pc_rec_cmp);
610 f = fopen("/tmp/kqemu.stats", "w");
611 if (!f) {
612 perror("/tmp/kqemu.stats");
613 exit(1);
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);
626 fclose(f);
627 free(pr);
629 kqemu_record_flush();
631 #endif
633 int kqemu_cpu_exec(CPUState *env)
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
641 #ifdef _WIN32
642 DWORD temp;
643 #endif
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);
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;
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;
702 #if KQEMU_VERSION >= 0x010300
703 kenv->nb_modified_ram_pages = nb_modified_ram_pages;
704 #endif
705 kqemu_reset_modified_ram_pages();
707 if (env->cpuid_features & CPUID_FXSR)
708 restore_native_fp_fxrstor(env);
709 else
710 restore_native_fp_frstor(env);
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;
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);
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
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]);
766 nb_pages_to_flush = 0;
768 #ifdef CONFIG_PROFILER
769 kqemu_time += profile_getclock() - ti;
770 kqemu_exec_count++;
771 #endif
773 #if KQEMU_VERSION >= 0x010200
774 if (kenv->nb_ram_pages_to_update > 0) {
775 cpu_tlb_update_dirty(env);
777 #endif
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);
787 #endif
789 /* restore the hidden flags */
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
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;
821 env->hflags = (env->hflags &
822 ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |
823 new_hflags;
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;
833 #ifdef DEBUG
834 if (loglevel & CPU_LOG_INT) {
835 fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
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);
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);
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);
882 #endif
883 return 0;
884 } else if (ret == KQEMU_RET_SOFTMMU) {
885 #ifdef CONFIG_PROFILER
887 unsigned long pc = env->eip + env->segs[R_CS].base;
888 kqemu_record_pc(pc);
890 #endif
891 #ifdef DEBUG
892 if (loglevel & CPU_LOG_INT) {
893 cpu_dump_state(env, logfile, fprintf, 0);
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);
902 return 0;
905 void kqemu_cpu_interrupt(CPUState *env)
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
914 #endif