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