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