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