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