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