4 * Copyright (c) 2005 Fabrice Bellard
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.
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.
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
25 #include <sys/types.h>
27 #include <sys/ioctl.h>
47 #include "kqemu/kqemu.h"
49 /* compatibility stuff */
50 #ifndef KQEMU_RET_SYSCALL
51 #define KQEMU_RET_SYSCALL 0x0300 /* syscall insn */
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)
59 #define KQEMU_DEVICE "\\\\.\\kqemu"
61 #define KQEMU_DEVICE "/dev/kqemu"
65 #define KQEMU_INVALID_FD INVALID_HANDLE_VALUE
66 HANDLE kqemu_fd = KQEMU_INVALID_FD;
67 #define kqemu_closefd(x) CloseHandle(x)
69 #define KQEMU_INVALID_FD -1
70 int kqemu_fd = KQEMU_INVALID_FD;
71 #define kqemu_closefd(x) close(x)
74 int kqemu_allowed = 1;
75 unsigned long *pages_to_flush;
76 unsigned int nb_pages_to_flush;
77 unsigned long *ram_pages_to_update;
78 unsigned int nb_ram_pages_to_update;
79 extern uint32_t **l1_phys_map;
81 #define cpuid(index, eax, ebx, ecx, edx) \
82 asm volatile ("cpuid" \
83 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
87 static int is_cpuid_supported(void)
92 static int is_cpuid_supported(void)
95 asm volatile ("pushf\n"
98 "xorl $0x00200000, %0\n"
103 : "=a" (v0), "=d" (v1)
110 static void kqemu_update_cpuid(CPUState *env)
112 int critical_features_mask, features;
113 uint32_t eax, ebx, ecx, edx;
115 /* the following features are kept identical on the host and
116 target cpus because they are important for user code. Strictly
117 speaking, only SSE really matters because the OS must support
118 it if the user code uses it. */
119 critical_features_mask =
120 CPUID_CMOV | CPUID_CX8 |
121 CPUID_FXSR | CPUID_MMX | CPUID_SSE |
123 if (!is_cpuid_supported()) {
126 cpuid(1, eax, ebx, ecx, edx);
129 env->cpuid_features = (env->cpuid_features & ~critical_features_mask) |
130 (features & critical_features_mask);
131 /* XXX: we could update more of the target CPUID state so that the
132 non accelerated code sees exactly the same CPU features as the
136 int kqemu_init(CPUState *env)
138 struct kqemu_init init;
148 kqemu_fd = CreateFile(KQEMU_DEVICE, GENERIC_WRITE | GENERIC_READ,
149 FILE_SHARE_READ | FILE_SHARE_WRITE,
150 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
153 kqemu_fd = open(KQEMU_DEVICE, O_RDWR);
155 if (kqemu_fd == KQEMU_INVALID_FD) {
156 fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated\n", KQEMU_DEVICE);
161 DeviceIoControl(kqemu_fd, KQEMU_GET_VERSION, NULL, 0,
162 &version, sizeof(version), &temp, NULL);
164 ioctl(kqemu_fd, KQEMU_GET_VERSION, &version);
166 if (version != KQEMU_VERSION) {
167 fprintf(stderr, "Version mismatch between kqemu module and qemu (%08x %08x) - disabling kqemu use\n",
168 version, KQEMU_VERSION);
172 pages_to_flush = qemu_vmalloc(KQEMU_MAX_PAGES_TO_FLUSH *
173 sizeof(unsigned long));
177 ram_pages_to_update = qemu_vmalloc(KQEMU_MAX_RAM_PAGES_TO_UPDATE *
178 sizeof(unsigned long));
179 if (!ram_pages_to_update)
182 init.ram_base = phys_ram_base;
183 init.ram_size = phys_ram_size;
184 init.ram_dirty = phys_ram_dirty;
185 init.phys_to_ram_map = l1_phys_map;
186 init.pages_to_flush = pages_to_flush;
187 #if KQEMU_VERSION >= 0x010200
188 init.ram_pages_to_update = ram_pages_to_update;
191 ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &init, sizeof(init),
192 NULL, 0, &temp, NULL) == TRUE ? 0 : -1;
194 ret = ioctl(kqemu_fd, KQEMU_INIT, &init);
197 fprintf(stderr, "Error %d while initializing QEMU acceleration layer - disabling it for now\n", ret);
199 kqemu_closefd(kqemu_fd);
200 kqemu_fd = KQEMU_INVALID_FD;
203 kqemu_update_cpuid(env);
204 env->kqemu_enabled = 1;
205 nb_pages_to_flush = 0;
206 nb_ram_pages_to_update = 0;
210 void kqemu_flush_page(CPUState *env, target_ulong addr)
213 if (loglevel & CPU_LOG_INT) {
214 fprintf(logfile, "kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr);
217 if (nb_pages_to_flush >= KQEMU_MAX_PAGES_TO_FLUSH)
218 nb_pages_to_flush = KQEMU_FLUSH_ALL;
220 pages_to_flush[nb_pages_to_flush++] = addr;
223 void kqemu_flush(CPUState *env, int global)
226 if (loglevel & CPU_LOG_INT) {
227 fprintf(logfile, "kqemu_flush:\n");
230 nb_pages_to_flush = KQEMU_FLUSH_ALL;
233 void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr)
236 if (loglevel & CPU_LOG_INT) {
237 fprintf(logfile, "kqemu_set_notdirty: addr=%08lx\n", ram_addr);
240 /* we only track transitions to dirty state */
241 if (phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] != 0xff)
243 if (nb_ram_pages_to_update >= KQEMU_MAX_RAM_PAGES_TO_UPDATE)
244 nb_ram_pages_to_update = KQEMU_RAM_PAGES_UPDATE_ALL;
246 ram_pages_to_update[nb_ram_pages_to_update++] = ram_addr;
261 uint8_t fpregs1[8 * 10];
277 uint8_t fpregs1[8 * 16];
278 uint8_t xmm_regs[16 * 16];
282 static struct fpxstate fpx1 __attribute__((aligned(16)));
284 static void restore_native_fp_frstor(CPUState *env)
287 struct fpstate fp1, *fp = &fp1;
289 fp->fpuc = env->fpuc;
290 fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
292 for (i=7; i>=0; i--) {
294 if (env->fptags[i]) {
297 /* the FPU automatically computes it */
302 for(i = 0;i < 8; i++) {
303 memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
306 asm volatile ("frstor %0" : "=m" (*fp));
309 static void save_native_fp_fsave(CPUState *env)
313 struct fpstate fp1, *fp = &fp1;
315 asm volatile ("fsave %0" : : "m" (*fp));
316 env->fpuc = fp->fpuc;
317 env->fpstt = (fp->fpus >> 11) & 7;
318 env->fpus = fp->fpus & ~0x3800;
320 for(i = 0;i < 8; i++) {
321 env->fptags[i] = ((fptag & 3) == 3);
325 for(i = 0;i < 8; i++) {
326 memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
329 /* we must restore the default rounding state */
330 fpuc = 0x037f | (env->fpuc & (3 << 10));
331 asm volatile("fldcw %0" : : "m" (fpuc));
334 static void restore_native_fp_fxrstor(CPUState *env)
336 struct fpxstate *fp = &fpx1;
339 fp->fpuc = env->fpuc;
340 fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
342 for(i = 0; i < 8; i++)
343 fptag |= (env->fptags[i] << i);
344 fp->fptag = fptag ^ 0xff;
347 for(i = 0;i < 8; i++) {
348 memcpy(&fp->fpregs1[i * 16], &env->fpregs[j].d, 10);
351 if (env->cpuid_features & CPUID_SSE) {
352 fp->mxcsr = env->mxcsr;
353 /* XXX: check if DAZ is not available */
354 fp->mxcsr_mask = 0xffff;
355 memcpy(fp->xmm_regs, env->xmm_regs, CPU_NB_REGS * 16);
357 asm volatile ("fxrstor %0" : "=m" (*fp));
360 static void save_native_fp_fxsave(CPUState *env)
362 struct fpxstate *fp = &fpx1;
366 asm volatile ("fxsave %0" : : "m" (*fp));
367 env->fpuc = fp->fpuc;
368 env->fpstt = (fp->fpus >> 11) & 7;
369 env->fpus = fp->fpus & ~0x3800;
370 fptag = fp->fptag ^ 0xff;
371 for(i = 0;i < 8; i++) {
372 env->fptags[i] = (fptag >> i) & 1;
375 for(i = 0;i < 8; i++) {
376 memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 16], 10);
379 if (env->cpuid_features & CPUID_SSE) {
380 env->mxcsr = fp->mxcsr;
381 memcpy(env->xmm_regs, fp->xmm_regs, CPU_NB_REGS * 16);
384 /* we must restore the default rounding state */
385 asm volatile ("fninit");
386 fpuc = 0x037f | (env->fpuc & (3 << 10));
387 asm volatile("fldcw %0" : : "m" (fpuc));
390 static int do_syscall(CPUState *env,
391 struct kqemu_cpu_state *kenv)
395 selector = (env->star >> 32) & 0xffff;
397 if (env->hflags & HF_LMA_MASK) {
398 env->regs[R_ECX] = kenv->next_eip;
399 env->regs[11] = env->eflags;
401 cpu_x86_set_cpl(env, 0);
402 cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
404 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
406 DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
407 cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
409 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
411 DESC_W_MASK | DESC_A_MASK);
412 env->eflags &= ~env->fmask;
413 if (env->hflags & HF_CS64_MASK)
414 env->eip = env->lstar;
416 env->eip = env->cstar;
420 env->regs[R_ECX] = (uint32_t)kenv->next_eip;
422 cpu_x86_set_cpl(env, 0);
423 cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
425 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
427 DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
428 cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
430 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
432 DESC_W_MASK | DESC_A_MASK);
433 env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
434 env->eip = (uint32_t)env->star;
441 #define PC_REC_SIZE 1
442 #define PC_REC_HASH_BITS 16
443 #define PC_REC_HASH_SIZE (1 << PC_REC_HASH_BITS)
445 typedef struct PCRecord {
448 struct PCRecord *next;
451 PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];
454 void kqemu_record_pc(unsigned long pc)
459 h = pc / PC_REC_SIZE;
460 h = h ^ (h >> PC_REC_HASH_BITS);
461 h &= (PC_REC_HASH_SIZE - 1);
462 pr = &pc_rec_hash[h];
473 r = malloc(sizeof(PCRecord));
481 int pc_rec_cmp(const void *p1, const void *p2)
483 PCRecord *r1 = *(PCRecord **)p1;
484 PCRecord *r2 = *(PCRecord **)p2;
485 if (r1->count < r2->count)
487 else if (r1->count == r2->count)
493 void kqemu_record_dump(void)
500 pr = malloc(sizeof(PCRecord *) * nb_pc_records);
503 for(h = 0; h < PC_REC_HASH_SIZE; h++) {
504 for(r = pc_rec_hash[h]; r != NULL; r = r->next) {
509 qsort(pr, nb_pc_records, sizeof(PCRecord *), pc_rec_cmp);
511 f = fopen("/tmp/kqemu.stats", "w");
513 perror("/tmp/kqemu.stats");
516 fprintf(f, "total: %lld\n", total);
518 for(i = 0; i < nb_pc_records; i++) {
521 fprintf(f, "%08lx: %lld %0.2f%% %0.2f%%\n",
524 (double)r->count / (double)total * 100.0,
525 (double)sum / (double)total * 100.0);
531 void kqemu_record_dump(void)
536 int kqemu_cpu_exec(CPUState *env)
538 struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;
545 if (loglevel & CPU_LOG_INT) {
546 fprintf(logfile, "kqemu: cpu_exec: enter\n");
547 cpu_dump_state(env, logfile, fprintf, 0);
550 memcpy(kenv->regs, env->regs, sizeof(kenv->regs));
551 kenv->eip = env->eip;
552 kenv->eflags = env->eflags;
553 memcpy(&kenv->segs, &env->segs, sizeof(env->segs));
554 memcpy(&kenv->ldt, &env->ldt, sizeof(env->ldt));
555 memcpy(&kenv->tr, &env->tr, sizeof(env->tr));
556 memcpy(&kenv->gdt, &env->gdt, sizeof(env->gdt));
557 memcpy(&kenv->idt, &env->idt, sizeof(env->idt));
558 kenv->cr0 = env->cr[0];
559 kenv->cr2 = env->cr[2];
560 kenv->cr3 = env->cr[3];
561 kenv->cr4 = env->cr[4];
562 kenv->a20_mask = env->a20_mask;
563 #if KQEMU_VERSION >= 0x010100
564 kenv->efer = env->efer;
566 if (env->dr[7] & 0xff) {
567 kenv->dr7 = env->dr[7];
568 kenv->dr0 = env->dr[0];
569 kenv->dr1 = env->dr[1];
570 kenv->dr2 = env->dr[2];
571 kenv->dr3 = env->dr[3];
575 kenv->dr6 = env->dr[6];
577 kenv->nb_pages_to_flush = nb_pages_to_flush;
578 nb_pages_to_flush = 0;
579 #if KQEMU_VERSION >= 0x010200
581 kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;
583 nb_ram_pages_to_update = 0;
585 if (!(kenv->cr0 & CR0_TS_MASK)) {
586 if (env->cpuid_features & CPUID_FXSR)
587 restore_native_fp_fxrstor(env);
589 restore_native_fp_frstor(env);
593 DeviceIoControl(kqemu_fd, KQEMU_EXEC,
594 kenv, sizeof(struct kqemu_cpu_state),
595 kenv, sizeof(struct kqemu_cpu_state),
599 #if KQEMU_VERSION >= 0x010100
600 ioctl(kqemu_fd, KQEMU_EXEC, kenv);
603 ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);
606 if (!(kenv->cr0 & CR0_TS_MASK)) {
607 if (env->cpuid_features & CPUID_FXSR)
608 save_native_fp_fxsave(env);
610 save_native_fp_fsave(env);
613 memcpy(env->regs, kenv->regs, sizeof(env->regs));
614 env->eip = kenv->eip;
615 env->eflags = kenv->eflags;
616 memcpy(env->segs, kenv->segs, sizeof(env->segs));
618 /* no need to restore that */
619 memcpy(env->ldt, kenv->ldt, sizeof(env->ldt));
620 memcpy(env->tr, kenv->tr, sizeof(env->tr));
621 memcpy(env->gdt, kenv->gdt, sizeof(env->gdt));
622 memcpy(env->idt, kenv->idt, sizeof(env->idt));
623 env->cr[0] = kenv->cr0;
624 env->cr[3] = kenv->cr3;
625 env->cr[4] = kenv->cr4;
626 env->a20_mask = kenv->a20_mask;
628 env->cr[2] = kenv->cr2;
629 env->dr[6] = kenv->dr6;
631 #if KQEMU_VERSION >= 0x010200
632 if (kenv->nb_ram_pages_to_update > 0) {
633 cpu_tlb_update_dirty(env);
637 /* restore the hidden flags */
639 unsigned int new_hflags;
641 if ((env->hflags & HF_LMA_MASK) &&
642 (env->segs[R_CS].flags & DESC_L_MASK)) {
644 new_hflags = HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
648 /* legacy / compatibility case */
649 new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
650 >> (DESC_B_SHIFT - HF_CS32_SHIFT);
651 new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK)
652 >> (DESC_B_SHIFT - HF_SS32_SHIFT);
653 if (!(env->cr[0] & CR0_PE_MASK) ||
654 (env->eflags & VM_MASK) ||
655 !(env->hflags & HF_CS32_MASK)) {
656 /* XXX: try to avoid this test. The problem comes from the
657 fact that is real mode or vm86 mode we only modify the
658 'base' and 'selector' fields of the segment cache to go
659 faster. A solution may be to force addseg to one in
661 new_hflags |= HF_ADDSEG_MASK;
663 new_hflags |= ((env->segs[R_DS].base |
664 env->segs[R_ES].base |
665 env->segs[R_SS].base) != 0) <<
669 env->hflags = (env->hflags &
670 ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |
675 if (loglevel & CPU_LOG_INT) {
676 fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
679 if (ret == KQEMU_RET_SYSCALL) {
680 /* syscall instruction */
681 return do_syscall(env, kenv);
683 if ((ret & 0xff00) == KQEMU_RET_INT) {
684 env->exception_index = ret & 0xff;
686 env->exception_is_int = 1;
687 env->exception_next_eip = kenv->next_eip;
689 if (loglevel & CPU_LOG_INT) {
690 fprintf(logfile, "kqemu: interrupt v=%02x:\n",
691 env->exception_index);
692 cpu_dump_state(env, logfile, fprintf, 0);
696 } else if ((ret & 0xff00) == KQEMU_RET_EXCEPTION) {
697 env->exception_index = ret & 0xff;
698 env->error_code = kenv->error_code;
699 env->exception_is_int = 0;
700 env->exception_next_eip = 0;
702 if (loglevel & CPU_LOG_INT) {
703 fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n",
704 env->exception_index, env->error_code);
705 cpu_dump_state(env, logfile, fprintf, 0);
709 } else if (ret == KQEMU_RET_INTR) {
711 if (loglevel & CPU_LOG_INT) {
712 cpu_dump_state(env, logfile, fprintf, 0);
716 } else if (ret == KQEMU_RET_SOFTMMU) {
718 kqemu_record_pc(env->eip + env->segs[R_CS].base);
721 if (loglevel & CPU_LOG_INT) {
722 cpu_dump_state(env, logfile, fprintf, 0);
727 cpu_dump_state(env, stderr, fprintf, 0);
728 fprintf(stderr, "Unsupported return value: 0x%x\n", ret);