]> Git Repo - qemu.git/blame - kqemu.c
32 bit syscall fix (Juergen Keil)
[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{
0de6bb73 122 int critical_features_mask, features, ext_features, ext_features_mask;
9df217a3
FB
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;
0de6bb73 133 ext_features_mask = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR;
9df217a3
FB
134 if (!is_cpuid_supported()) {
135 features = 0;
0de6bb73 136 ext_features = 0;
9df217a3
FB
137 } else {
138 cpuid(1, eax, ebx, ecx, edx);
139 features = edx;
0de6bb73 140 ext_features = ecx;
9df217a3 141 }
ca0d1734
FB
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
9df217a3
FB
148 env->cpuid_features = (env->cpuid_features & ~critical_features_mask) |
149 (features & critical_features_mask);
0de6bb73
FB
150 env->cpuid_ext_features = (env->cpuid_ext_features & ~ext_features_mask) |
151 (ext_features & ext_features_mask);
9df217a3
FB
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 */
155}
156
157int kqemu_init(CPUState *env)
158{
159 struct kqemu_init init;
160 int ret, version;
6e4255f6
FB
161#ifdef _WIN32
162 DWORD temp;
163#endif
9df217a3
FB
164
165 if (!kqemu_allowed)
166 return -1;
167
6e4255f6
FB
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
9df217a3 174 kqemu_fd = open(KQEMU_DEVICE, O_RDWR);
6e4255f6
FB
175#endif
176 if (kqemu_fd == KQEMU_INVALID_FD) {
9df217a3
FB
177 fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated\n", KQEMU_DEVICE);
178 return -1;
179 }
180 version = 0;
6e4255f6
FB
181#ifdef _WIN32
182 DeviceIoControl(kqemu_fd, KQEMU_GET_VERSION, NULL, 0,
183 &version, sizeof(version), &temp, NULL);
184#else
9df217a3 185 ioctl(kqemu_fd, KQEMU_GET_VERSION, &version);
6e4255f6 186#endif
9df217a3
FB
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;
191 }
192
193 pages_to_flush = qemu_vmalloc(KQEMU_MAX_PAGES_TO_FLUSH *
194 sizeof(unsigned long));
195 if (!pages_to_flush)
196 goto fail;
197
aa062973
FB
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;
202
f32fc648
FB
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;
210
9df217a3
FB
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;
aa062973
FB
216#if KQEMU_VERSION >= 0x010200
217 init.ram_pages_to_update = ram_pages_to_update;
218#endif
f32fc648
FB
219#if KQEMU_VERSION >= 0x010300
220 init.modified_ram_pages = modified_ram_pages;
221#endif
6e4255f6
FB
222#ifdef _WIN32
223 ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &init, sizeof(init),
224 NULL, 0, &temp, NULL) == TRUE ? 0 : -1;
225#else
9df217a3 226 ret = ioctl(kqemu_fd, KQEMU_INIT, &init);
6e4255f6 227#endif
9df217a3
FB
228 if (ret < 0) {
229 fprintf(stderr, "Error %d while initializing QEMU acceleration layer - disabling it for now\n", ret);
230 fail:
6e4255f6
FB
231 kqemu_closefd(kqemu_fd);
232 kqemu_fd = KQEMU_INVALID_FD;
9df217a3
FB
233 return -1;
234 }
235 kqemu_update_cpuid(env);
f32fc648 236 env->kqemu_enabled = kqemu_allowed;
9df217a3 237 nb_pages_to_flush = 0;
aa062973 238 nb_ram_pages_to_update = 0;
9df217a3
FB
239 return 0;
240}
241
242void kqemu_flush_page(CPUState *env, target_ulong addr)
243{
f32fc648 244#if defined(DEBUG)
9df217a3
FB
245 if (loglevel & CPU_LOG_INT) {
246 fprintf(logfile, "kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr);
247 }
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;
253}
254
255void kqemu_flush(CPUState *env, int global)
256{
257#ifdef DEBUG
258 if (loglevel & CPU_LOG_INT) {
259 fprintf(logfile, "kqemu_flush:\n");
260 }
261#endif
262 nb_pages_to_flush = KQEMU_FLUSH_ALL;
263}
264
aa062973
FB
265void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr)
266{
267#ifdef DEBUG
268 if (loglevel & CPU_LOG_INT) {
269 fprintf(logfile, "kqemu_set_notdirty: addr=%08lx\n", ram_addr);
270 }
271#endif
fc8dc060
FB
272 /* we only track transitions to dirty state */
273 if (phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] != 0xff)
274 return;
aa062973
FB
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;
279}
280
f32fc648
FB
281static void kqemu_reset_modified_ram_pages(void)
282{
283 int i;
284 unsigned long page_index;
285
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;
289 }
290 nb_modified_ram_pages = 0;
291}
292
293void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr)
294{
295 unsigned long page_index;
296 int ret;
297#ifdef _WIN32
298 DWORD temp;
299#endif
300
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();
320 }
321 }
322}
323
9df217a3
FB
324struct 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;
331
332 uint32_t fpip;
333 uint32_t fpcs;
334 uint32_t fpoo;
335 uint32_t fpos;
336 uint8_t fpregs1[8 * 10];
337};
338
339struct 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];
c28e951f
FB
353 uint8_t xmm_regs[16 * 16];
354 uint8_t dummy2[96];
9df217a3
FB
355};
356
357static struct fpxstate fpx1 __attribute__((aligned(16)));
358
359static void restore_native_fp_frstor(CPUState *env)
360{
361 int fptag, i, j;
362 struct fpstate fp1, *fp = &fp1;
363
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 */
373 }
374 }
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;
380 }
381 asm volatile ("frstor %0" : "=m" (*fp));
382}
383
384static void save_native_fp_fsave(CPUState *env)
385{
386 int fptag, i, j;
387 uint16_t fpuc;
388 struct fpstate fp1, *fp = &fp1;
389
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;
398 }
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;
403 }
404 /* we must restore the default rounding state */
405 fpuc = 0x037f | (env->fpuc & (3 << 10));
406 asm volatile("fldcw %0" : : "m" (fpuc));
407}
408
409static void restore_native_fp_fxrstor(CPUState *env)
410{
411 struct fpxstate *fp = &fpx1;
412 int i, j, fptag;
413
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;
420
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;
425 }
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;
c28e951f 430 memcpy(fp->xmm_regs, env->xmm_regs, CPU_NB_REGS * 16);
9df217a3
FB
431 }
432 asm volatile ("fxrstor %0" : "=m" (*fp));
433}
434
435static void save_native_fp_fxsave(CPUState *env)
436{
437 struct fpxstate *fp = &fpx1;
438 int fptag, i, j;
439 uint16_t fpuc;
440
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;
448 }
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;
453 }
454 if (env->cpuid_features & CPUID_SSE) {
455 env->mxcsr = fp->mxcsr;
c28e951f 456 memcpy(env->xmm_regs, fp->xmm_regs, CPU_NB_REGS * 16);
9df217a3
FB
457 }
458
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));
463}
464
c28e951f
FB
465static int do_syscall(CPUState *env,
466 struct kqemu_cpu_state *kenv)
467{
468 int selector;
469
470 selector = (env->star >> 32) & 0xffff;
471#ifdef __x86_64__
472 if (env->hflags & HF_LMA_MASK) {
93eac243
FB
473 int code64;
474
c28e951f
FB
475 env->regs[R_ECX] = kenv->next_eip;
476 env->regs[11] = env->eflags;
477
93eac243
FB
478 code64 = env->hflags & HF_CS64_MASK;
479
c28e951f
FB
480 cpu_x86_set_cpl(env, 0);
481 cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
482 0, 0xffffffff,
483 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
484 DESC_S_MASK |
485 DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
486 cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
487 0, 0xffffffff,
488 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
489 DESC_S_MASK |
490 DESC_W_MASK | DESC_A_MASK);
491 env->eflags &= ~env->fmask;
93eac243 492 if (code64)
c28e951f
FB
493 env->eip = env->lstar;
494 else
495 env->eip = env->cstar;
496 } else
497#endif
498 {
499 env->regs[R_ECX] = (uint32_t)kenv->next_eip;
500
501 cpu_x86_set_cpl(env, 0);
502 cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
503 0, 0xffffffff,
504 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
505 DESC_S_MASK |
506 DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
507 cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
508 0, 0xffffffff,
509 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
510 DESC_S_MASK |
511 DESC_W_MASK | DESC_A_MASK);
512 env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
513 env->eip = (uint32_t)env->star;
514 }
515 return 2;
516}
517
f32fc648 518#ifdef CONFIG_PROFILER
aa062973
FB
519
520#define PC_REC_SIZE 1
521#define PC_REC_HASH_BITS 16
522#define PC_REC_HASH_SIZE (1 << PC_REC_HASH_BITS)
523
524typedef struct PCRecord {
525 unsigned long pc;
526 int64_t count;
527 struct PCRecord *next;
528} PCRecord;
529
f32fc648
FB
530static PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];
531static int nb_pc_records;
aa062973 532
f32fc648 533static void kqemu_record_pc(unsigned long pc)
aa062973
FB
534{
535 unsigned long h;
536 PCRecord **pr, *r;
537
538 h = pc / PC_REC_SIZE;
539 h = h ^ (h >> PC_REC_HASH_BITS);
540 h &= (PC_REC_HASH_SIZE - 1);
541 pr = &pc_rec_hash[h];
542 for(;;) {
543 r = *pr;
544 if (r == NULL)
545 break;
546 if (r->pc == pc) {
547 r->count++;
548 return;
549 }
550 pr = &r->next;
551 }
552 r = malloc(sizeof(PCRecord));
553 r->count = 1;
554 r->pc = pc;
555 r->next = NULL;
556 *pr = r;
557 nb_pc_records++;
558}
559
f32fc648 560static int pc_rec_cmp(const void *p1, const void *p2)
aa062973
FB
561{
562 PCRecord *r1 = *(PCRecord **)p1;
563 PCRecord *r2 = *(PCRecord **)p2;
564 if (r1->count < r2->count)
565 return 1;
566 else if (r1->count == r2->count)
567 return 0;
568 else
569 return -1;
570}
571
f32fc648
FB
572static void kqemu_record_flush(void)
573{
574 PCRecord *r, *r_next;
575 int h;
576
577 for(h = 0; h < PC_REC_HASH_SIZE; h++) {
578 for(r = pc_rec_hash[h]; r != NULL; r = r_next) {
579 r_next = r->next;
580 free(r);
581 }
582 pc_rec_hash[h] = NULL;
583 }
584 nb_pc_records = 0;
585}
586
aa062973
FB
587void kqemu_record_dump(void)
588{
589 PCRecord **pr, *r;
590 int i, h;
591 FILE *f;
592 int64_t total, sum;
593
594 pr = malloc(sizeof(PCRecord *) * nb_pc_records);
595 i = 0;
596 total = 0;
597 for(h = 0; h < PC_REC_HASH_SIZE; h++) {
598 for(r = pc_rec_hash[h]; r != NULL; r = r->next) {
599 pr[i++] = r;
600 total += r->count;
601 }
602 }
603 qsort(pr, nb_pc_records, sizeof(PCRecord *), pc_rec_cmp);
604
605 f = fopen("/tmp/kqemu.stats", "w");
606 if (!f) {
607 perror("/tmp/kqemu.stats");
608 exit(1);
609 }
26a76461 610 fprintf(f, "total: %" PRId64 "\n", total);
aa062973
FB
611 sum = 0;
612 for(i = 0; i < nb_pc_records; i++) {
613 r = pr[i];
614 sum += r->count;
26a76461 615 fprintf(f, "%08lx: %" PRId64 " %0.2f%% %0.2f%%\n",
aa062973
FB
616 r->pc,
617 r->count,
618 (double)r->count / (double)total * 100.0,
619 (double)sum / (double)total * 100.0);
620 }
621 fclose(f);
622 free(pr);
f32fc648
FB
623
624 kqemu_record_flush();
aa062973
FB
625}
626#endif
627
9df217a3
FB
628int kqemu_cpu_exec(CPUState *env)
629{
630 struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;
f32fc648
FB
631 int ret, cpl, i;
632#ifdef CONFIG_PROFILER
633 int64_t ti;
634#endif
635
6e4255f6
FB
636#ifdef _WIN32
637 DWORD temp;
638#endif
9df217a3 639
f32fc648
FB
640#ifdef CONFIG_PROFILER
641 ti = profile_getclock();
642#endif
9df217a3
FB
643#ifdef DEBUG
644 if (loglevel & CPU_LOG_INT) {
645 fprintf(logfile, "kqemu: cpu_exec: enter\n");
646 cpu_dump_state(env, logfile, fprintf, 0);
647 }
648#endif
649 memcpy(kenv->regs, env->regs, sizeof(kenv->regs));
650 kenv->eip = env->eip;
651 kenv->eflags = env->eflags;
652 memcpy(&kenv->segs, &env->segs, sizeof(env->segs));
653 memcpy(&kenv->ldt, &env->ldt, sizeof(env->ldt));
654 memcpy(&kenv->tr, &env->tr, sizeof(env->tr));
655 memcpy(&kenv->gdt, &env->gdt, sizeof(env->gdt));
656 memcpy(&kenv->idt, &env->idt, sizeof(env->idt));
657 kenv->cr0 = env->cr[0];
658 kenv->cr2 = env->cr[2];
659 kenv->cr3 = env->cr[3];
660 kenv->cr4 = env->cr[4];
661 kenv->a20_mask = env->a20_mask;
c45b3c0e 662#if KQEMU_VERSION >= 0x010100
c28e951f 663 kenv->efer = env->efer;
f32fc648
FB
664#endif
665#if KQEMU_VERSION >= 0x010300
666 kenv->tsc_offset = 0;
667 kenv->star = env->star;
668 kenv->sysenter_cs = env->sysenter_cs;
669 kenv->sysenter_esp = env->sysenter_esp;
670 kenv->sysenter_eip = env->sysenter_eip;
671#ifdef __x86_64__
672 kenv->lstar = env->lstar;
673 kenv->cstar = env->cstar;
674 kenv->fmask = env->fmask;
675 kenv->kernelgsbase = env->kernelgsbase;
676#endif
c28e951f 677#endif
9df217a3
FB
678 if (env->dr[7] & 0xff) {
679 kenv->dr7 = env->dr[7];
680 kenv->dr0 = env->dr[0];
681 kenv->dr1 = env->dr[1];
682 kenv->dr2 = env->dr[2];
683 kenv->dr3 = env->dr[3];
684 } else {
685 kenv->dr7 = 0;
686 }
687 kenv->dr6 = env->dr[6];
f32fc648
FB
688 cpl = (env->hflags & HF_CPL_MASK);
689 kenv->cpl = cpl;
9df217a3 690 kenv->nb_pages_to_flush = nb_pages_to_flush;
aa062973 691#if KQEMU_VERSION >= 0x010200
f32fc648 692 kenv->user_only = (env->kqemu_enabled == 1);
aa062973
FB
693 kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;
694#endif
695 nb_ram_pages_to_update = 0;
9df217a3 696
f32fc648
FB
697#if KQEMU_VERSION >= 0x010300
698 kenv->nb_modified_ram_pages = nb_modified_ram_pages;
699#endif
700 kqemu_reset_modified_ram_pages();
701
702 if (env->cpuid_features & CPUID_FXSR)
703 restore_native_fp_fxrstor(env);
704 else
705 restore_native_fp_frstor(env);
9df217a3 706
6e4255f6 707#ifdef _WIN32
a332e112
FB
708 if (DeviceIoControl(kqemu_fd, KQEMU_EXEC,
709 kenv, sizeof(struct kqemu_cpu_state),
710 kenv, sizeof(struct kqemu_cpu_state),
711 &temp, NULL)) {
712 ret = kenv->retval;
713 } else {
714 ret = -1;
715 }
6e4255f6
FB
716#else
717#if KQEMU_VERSION >= 0x010100
718 ioctl(kqemu_fd, KQEMU_EXEC, kenv);
719 ret = kenv->retval;
720#else
9df217a3 721 ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);
6e4255f6
FB
722#endif
723#endif
f32fc648
FB
724 if (env->cpuid_features & CPUID_FXSR)
725 save_native_fp_fxsave(env);
726 else
727 save_native_fp_fsave(env);
9df217a3
FB
728
729 memcpy(env->regs, kenv->regs, sizeof(env->regs));
730 env->eip = kenv->eip;
731 env->eflags = kenv->eflags;
732 memcpy(env->segs, kenv->segs, sizeof(env->segs));
f32fc648
FB
733 cpu_x86_set_cpl(env, kenv->cpl);
734 memcpy(&env->ldt, &kenv->ldt, sizeof(env->ldt));
9df217a3
FB
735#if 0
736 /* no need to restore that */
9df217a3
FB
737 memcpy(env->tr, kenv->tr, sizeof(env->tr));
738 memcpy(env->gdt, kenv->gdt, sizeof(env->gdt));
739 memcpy(env->idt, kenv->idt, sizeof(env->idt));
9df217a3
FB
740 env->a20_mask = kenv->a20_mask;
741#endif
f32fc648
FB
742 env->cr[0] = kenv->cr0;
743 env->cr[4] = kenv->cr4;
744 env->cr[3] = kenv->cr3;
9df217a3
FB
745 env->cr[2] = kenv->cr2;
746 env->dr[6] = kenv->dr6;
f32fc648
FB
747#if KQEMU_VERSION >= 0x010300
748#ifdef __x86_64__
749 env->kernelgsbase = kenv->kernelgsbase;
750#endif
751#endif
752
753 /* flush pages as indicated by kqemu */
754 if (kenv->nb_pages_to_flush >= KQEMU_FLUSH_ALL) {
755 tlb_flush(env, 1);
756 } else {
757 for(i = 0; i < kenv->nb_pages_to_flush; i++) {
758 tlb_flush_page(env, pages_to_flush[i]);
759 }
760 }
761 nb_pages_to_flush = 0;
762
763#ifdef CONFIG_PROFILER
764 kqemu_time += profile_getclock() - ti;
765 kqemu_exec_count++;
766#endif
9df217a3 767
aa062973
FB
768#if KQEMU_VERSION >= 0x010200
769 if (kenv->nb_ram_pages_to_update > 0) {
770 cpu_tlb_update_dirty(env);
771 }
772#endif
773
f32fc648
FB
774#if KQEMU_VERSION >= 0x010300
775 if (kenv->nb_modified_ram_pages > 0) {
776 for(i = 0; i < kenv->nb_modified_ram_pages; i++) {
777 unsigned long addr;
778 addr = modified_ram_pages[i];
779 tb_invalidate_phys_page_range(addr, addr + TARGET_PAGE_SIZE, 0);
780 }
781 }
782#endif
783
aa062973
FB
784 /* restore the hidden flags */
785 {
786 unsigned int new_hflags;
787#ifdef TARGET_X86_64
788 if ((env->hflags & HF_LMA_MASK) &&
789 (env->segs[R_CS].flags & DESC_L_MASK)) {
790 /* long mode */
791 new_hflags = HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
792 } else
793#endif
794 {
795 /* legacy / compatibility case */
796 new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
797 >> (DESC_B_SHIFT - HF_CS32_SHIFT);
798 new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK)
799 >> (DESC_B_SHIFT - HF_SS32_SHIFT);
800 if (!(env->cr[0] & CR0_PE_MASK) ||
801 (env->eflags & VM_MASK) ||
802 !(env->hflags & HF_CS32_MASK)) {
803 /* XXX: try to avoid this test. The problem comes from the
804 fact that is real mode or vm86 mode we only modify the
805 'base' and 'selector' fields of the segment cache to go
806 faster. A solution may be to force addseg to one in
807 translate-i386.c. */
808 new_hflags |= HF_ADDSEG_MASK;
809 } else {
810 new_hflags |= ((env->segs[R_DS].base |
811 env->segs[R_ES].base |
812 env->segs[R_SS].base) != 0) <<
813 HF_ADDSEG_SHIFT;
814 }
815 }
816 env->hflags = (env->hflags &
817 ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |
818 new_hflags;
819 }
f32fc648
FB
820 /* update FPU flags */
821 env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
822 ((env->cr[0] << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
823 if (env->cr[4] & CR4_OSFXSR_MASK)
824 env->hflags |= HF_OSFXSR_MASK;
825 else
826 env->hflags &= ~HF_OSFXSR_MASK;
827
9df217a3
FB
828#ifdef DEBUG
829 if (loglevel & CPU_LOG_INT) {
830 fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
831 }
832#endif
c28e951f
FB
833 if (ret == KQEMU_RET_SYSCALL) {
834 /* syscall instruction */
835 return do_syscall(env, kenv);
836 } else
9df217a3
FB
837 if ((ret & 0xff00) == KQEMU_RET_INT) {
838 env->exception_index = ret & 0xff;
839 env->error_code = 0;
840 env->exception_is_int = 1;
841 env->exception_next_eip = kenv->next_eip;
f32fc648
FB
842#ifdef CONFIG_PROFILER
843 kqemu_ret_int_count++;
844#endif
9df217a3 845#ifdef DEBUG
c28e951f
FB
846 if (loglevel & CPU_LOG_INT) {
847 fprintf(logfile, "kqemu: interrupt v=%02x:\n",
848 env->exception_index);
849 cpu_dump_state(env, logfile, fprintf, 0);
850 }
9df217a3
FB
851#endif
852 return 1;
853 } else if ((ret & 0xff00) == KQEMU_RET_EXCEPTION) {
854 env->exception_index = ret & 0xff;
855 env->error_code = kenv->error_code;
856 env->exception_is_int = 0;
857 env->exception_next_eip = 0;
f32fc648
FB
858#ifdef CONFIG_PROFILER
859 kqemu_ret_excp_count++;
860#endif
9df217a3
FB
861#ifdef DEBUG
862 if (loglevel & CPU_LOG_INT) {
863 fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n",
864 env->exception_index, env->error_code);
865 cpu_dump_state(env, logfile, fprintf, 0);
866 }
867#endif
868 return 1;
869 } else if (ret == KQEMU_RET_INTR) {
f32fc648
FB
870#ifdef CONFIG_PROFILER
871 kqemu_ret_intr_count++;
872#endif
c45b3c0e
FB
873#ifdef DEBUG
874 if (loglevel & CPU_LOG_INT) {
875 cpu_dump_state(env, logfile, fprintf, 0);
876 }
877#endif
9df217a3
FB
878 return 0;
879 } else if (ret == KQEMU_RET_SOFTMMU) {
f32fc648
FB
880#ifdef CONFIG_PROFILER
881 {
882 unsigned long pc = env->eip + env->segs[R_CS].base;
883 kqemu_record_pc(pc);
884 }
aa062973
FB
885#endif
886#ifdef DEBUG
887 if (loglevel & CPU_LOG_INT) {
888 cpu_dump_state(env, logfile, fprintf, 0);
889 }
890#endif
9df217a3
FB
891 return 2;
892 } else {
893 cpu_dump_state(env, stderr, fprintf, 0);
894 fprintf(stderr, "Unsupported return value: 0x%x\n", ret);
895 exit(1);
896 }
897 return 0;
898}
899
a332e112
FB
900void kqemu_cpu_interrupt(CPUState *env)
901{
902#if defined(_WIN32) && KQEMU_VERSION >= 0x010101
903 /* cancelling the I/O request causes KQEMU to finish executing the
904 current block and successfully returning. */
905 CancelIo(kqemu_fd);
906#endif
907}
908
9df217a3 909#endif
This page took 0.170135 seconds and 4 git commands to generate.