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 if (nb_ram_pages_to_update >= KQEMU_MAX_RAM_PAGES_TO_UPDATE)
241 nb_ram_pages_to_update = KQEMU_RAM_PAGES_UPDATE_ALL;
243 ram_pages_to_update[nb_ram_pages_to_update++] = ram_addr;
258 uint8_t fpregs1[8 * 10];
274 uint8_t fpregs1[8 * 16];
275 uint8_t xmm_regs[16 * 16];
279 static struct fpxstate fpx1 __attribute__((aligned(16)));
281 static void restore_native_fp_frstor(CPUState *env)
284 struct fpstate fp1, *fp = &fp1;
286 fp->fpuc = env->fpuc;
287 fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
289 for (i=7; i>=0; i--) {
291 if (env->fptags[i]) {
294 /* the FPU automatically computes it */
299 for(i = 0;i < 8; i++) {
300 memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10);
303 asm volatile ("frstor %0" : "=m" (*fp));
306 static void save_native_fp_fsave(CPUState *env)
310 struct fpstate fp1, *fp = &fp1;
312 asm volatile ("fsave %0" : : "m" (*fp));
313 env->fpuc = fp->fpuc;
314 env->fpstt = (fp->fpus >> 11) & 7;
315 env->fpus = fp->fpus & ~0x3800;
317 for(i = 0;i < 8; i++) {
318 env->fptags[i] = ((fptag & 3) == 3);
322 for(i = 0;i < 8; i++) {
323 memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10);
326 /* we must restore the default rounding state */
327 fpuc = 0x037f | (env->fpuc & (3 << 10));
328 asm volatile("fldcw %0" : : "m" (fpuc));
331 static void restore_native_fp_fxrstor(CPUState *env)
333 struct fpxstate *fp = &fpx1;
336 fp->fpuc = env->fpuc;
337 fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
339 for(i = 0; i < 8; i++)
340 fptag |= (env->fptags[i] << i);
341 fp->fptag = fptag ^ 0xff;
344 for(i = 0;i < 8; i++) {
345 memcpy(&fp->fpregs1[i * 16], &env->fpregs[j].d, 10);
348 if (env->cpuid_features & CPUID_SSE) {
349 fp->mxcsr = env->mxcsr;
350 /* XXX: check if DAZ is not available */
351 fp->mxcsr_mask = 0xffff;
352 memcpy(fp->xmm_regs, env->xmm_regs, CPU_NB_REGS * 16);
354 asm volatile ("fxrstor %0" : "=m" (*fp));
357 static void save_native_fp_fxsave(CPUState *env)
359 struct fpxstate *fp = &fpx1;
363 asm volatile ("fxsave %0" : : "m" (*fp));
364 env->fpuc = fp->fpuc;
365 env->fpstt = (fp->fpus >> 11) & 7;
366 env->fpus = fp->fpus & ~0x3800;
367 fptag = fp->fptag ^ 0xff;
368 for(i = 0;i < 8; i++) {
369 env->fptags[i] = (fptag >> i) & 1;
372 for(i = 0;i < 8; i++) {
373 memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 16], 10);
376 if (env->cpuid_features & CPUID_SSE) {
377 env->mxcsr = fp->mxcsr;
378 memcpy(env->xmm_regs, fp->xmm_regs, CPU_NB_REGS * 16);
381 /* we must restore the default rounding state */
382 asm volatile ("fninit");
383 fpuc = 0x037f | (env->fpuc & (3 << 10));
384 asm volatile("fldcw %0" : : "m" (fpuc));
387 static int do_syscall(CPUState *env,
388 struct kqemu_cpu_state *kenv)
392 selector = (env->star >> 32) & 0xffff;
394 if (env->hflags & HF_LMA_MASK) {
395 env->regs[R_ECX] = kenv->next_eip;
396 env->regs[11] = env->eflags;
398 cpu_x86_set_cpl(env, 0);
399 cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
401 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
403 DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
404 cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
406 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
408 DESC_W_MASK | DESC_A_MASK);
409 env->eflags &= ~env->fmask;
410 if (env->hflags & HF_CS64_MASK)
411 env->eip = env->lstar;
413 env->eip = env->cstar;
417 env->regs[R_ECX] = (uint32_t)kenv->next_eip;
419 cpu_x86_set_cpl(env, 0);
420 cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
422 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
424 DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
425 cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,
427 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
429 DESC_W_MASK | DESC_A_MASK);
430 env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
431 env->eip = (uint32_t)env->star;
438 #define PC_REC_SIZE 1
439 #define PC_REC_HASH_BITS 16
440 #define PC_REC_HASH_SIZE (1 << PC_REC_HASH_BITS)
442 typedef struct PCRecord {
445 struct PCRecord *next;
448 PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];
451 void kqemu_record_pc(unsigned long pc)
456 h = pc / PC_REC_SIZE;
457 h = h ^ (h >> PC_REC_HASH_BITS);
458 h &= (PC_REC_HASH_SIZE - 1);
459 pr = &pc_rec_hash[h];
470 r = malloc(sizeof(PCRecord));
478 int pc_rec_cmp(const void *p1, const void *p2)
480 PCRecord *r1 = *(PCRecord **)p1;
481 PCRecord *r2 = *(PCRecord **)p2;
482 if (r1->count < r2->count)
484 else if (r1->count == r2->count)
490 void kqemu_record_dump(void)
497 pr = malloc(sizeof(PCRecord *) * nb_pc_records);
500 for(h = 0; h < PC_REC_HASH_SIZE; h++) {
501 for(r = pc_rec_hash[h]; r != NULL; r = r->next) {
506 qsort(pr, nb_pc_records, sizeof(PCRecord *), pc_rec_cmp);
508 f = fopen("/tmp/kqemu.stats", "w");
510 perror("/tmp/kqemu.stats");
513 fprintf(f, "total: %lld\n", total);
515 for(i = 0; i < nb_pc_records; i++) {
518 fprintf(f, "%08lx: %lld %0.2f%% %0.2f%%\n",
521 (double)r->count / (double)total * 100.0,
522 (double)sum / (double)total * 100.0);
528 void kqemu_record_dump(void)
533 int kqemu_cpu_exec(CPUState *env)
535 struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;
542 if (loglevel & CPU_LOG_INT) {
543 fprintf(logfile, "kqemu: cpu_exec: enter\n");
544 cpu_dump_state(env, logfile, fprintf, 0);
547 memcpy(kenv->regs, env->regs, sizeof(kenv->regs));
548 kenv->eip = env->eip;
549 kenv->eflags = env->eflags;
550 memcpy(&kenv->segs, &env->segs, sizeof(env->segs));
551 memcpy(&kenv->ldt, &env->ldt, sizeof(env->ldt));
552 memcpy(&kenv->tr, &env->tr, sizeof(env->tr));
553 memcpy(&kenv->gdt, &env->gdt, sizeof(env->gdt));
554 memcpy(&kenv->idt, &env->idt, sizeof(env->idt));
555 kenv->cr0 = env->cr[0];
556 kenv->cr2 = env->cr[2];
557 kenv->cr3 = env->cr[3];
558 kenv->cr4 = env->cr[4];
559 kenv->a20_mask = env->a20_mask;
560 #if KQEMU_VERSION >= 0x010100
561 kenv->efer = env->efer;
563 if (env->dr[7] & 0xff) {
564 kenv->dr7 = env->dr[7];
565 kenv->dr0 = env->dr[0];
566 kenv->dr1 = env->dr[1];
567 kenv->dr2 = env->dr[2];
568 kenv->dr3 = env->dr[3];
572 kenv->dr6 = env->dr[6];
574 kenv->nb_pages_to_flush = nb_pages_to_flush;
575 nb_pages_to_flush = 0;
576 #if KQEMU_VERSION >= 0x010200
578 kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;
580 nb_ram_pages_to_update = 0;
582 if (!(kenv->cr0 & CR0_TS_MASK)) {
583 if (env->cpuid_features & CPUID_FXSR)
584 restore_native_fp_fxrstor(env);
586 restore_native_fp_frstor(env);
590 DeviceIoControl(kqemu_fd, KQEMU_EXEC,
591 kenv, sizeof(struct kqemu_cpu_state),
592 kenv, sizeof(struct kqemu_cpu_state),
596 #if KQEMU_VERSION >= 0x010100
597 ioctl(kqemu_fd, KQEMU_EXEC, kenv);
600 ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);
603 if (!(kenv->cr0 & CR0_TS_MASK)) {
604 if (env->cpuid_features & CPUID_FXSR)
605 save_native_fp_fxsave(env);
607 save_native_fp_fsave(env);
610 memcpy(env->regs, kenv->regs, sizeof(env->regs));
611 env->eip = kenv->eip;
612 env->eflags = kenv->eflags;
613 memcpy(env->segs, kenv->segs, sizeof(env->segs));
615 /* no need to restore that */
616 memcpy(env->ldt, kenv->ldt, sizeof(env->ldt));
617 memcpy(env->tr, kenv->tr, sizeof(env->tr));
618 memcpy(env->gdt, kenv->gdt, sizeof(env->gdt));
619 memcpy(env->idt, kenv->idt, sizeof(env->idt));
620 env->cr[0] = kenv->cr0;
621 env->cr[3] = kenv->cr3;
622 env->cr[4] = kenv->cr4;
623 env->a20_mask = kenv->a20_mask;
625 env->cr[2] = kenv->cr2;
626 env->dr[6] = kenv->dr6;
628 #if KQEMU_VERSION >= 0x010200
629 if (kenv->nb_ram_pages_to_update > 0) {
630 cpu_tlb_update_dirty(env);
634 /* restore the hidden flags */
636 unsigned int new_hflags;
638 if ((env->hflags & HF_LMA_MASK) &&
639 (env->segs[R_CS].flags & DESC_L_MASK)) {
641 new_hflags = HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
645 /* legacy / compatibility case */
646 new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
647 >> (DESC_B_SHIFT - HF_CS32_SHIFT);
648 new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK)
649 >> (DESC_B_SHIFT - HF_SS32_SHIFT);
650 if (!(env->cr[0] & CR0_PE_MASK) ||
651 (env->eflags & VM_MASK) ||
652 !(env->hflags & HF_CS32_MASK)) {
653 /* XXX: try to avoid this test. The problem comes from the
654 fact that is real mode or vm86 mode we only modify the
655 'base' and 'selector' fields of the segment cache to go
656 faster. A solution may be to force addseg to one in
658 new_hflags |= HF_ADDSEG_MASK;
660 new_hflags |= ((env->segs[R_DS].base |
661 env->segs[R_ES].base |
662 env->segs[R_SS].base) != 0) <<
666 env->hflags = (env->hflags &
667 ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |
672 if (loglevel & CPU_LOG_INT) {
673 fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
676 if (ret == KQEMU_RET_SYSCALL) {
677 /* syscall instruction */
678 return do_syscall(env, kenv);
680 if ((ret & 0xff00) == KQEMU_RET_INT) {
681 env->exception_index = ret & 0xff;
683 env->exception_is_int = 1;
684 env->exception_next_eip = kenv->next_eip;
686 if (loglevel & CPU_LOG_INT) {
687 fprintf(logfile, "kqemu: interrupt v=%02x:\n",
688 env->exception_index);
689 cpu_dump_state(env, logfile, fprintf, 0);
693 } else if ((ret & 0xff00) == KQEMU_RET_EXCEPTION) {
694 env->exception_index = ret & 0xff;
695 env->error_code = kenv->error_code;
696 env->exception_is_int = 0;
697 env->exception_next_eip = 0;
699 if (loglevel & CPU_LOG_INT) {
700 fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n",
701 env->exception_index, env->error_code);
702 cpu_dump_state(env, logfile, fprintf, 0);
706 } else if (ret == KQEMU_RET_INTR) {
708 if (loglevel & CPU_LOG_INT) {
709 cpu_dump_state(env, logfile, fprintf, 0);
713 } else if (ret == KQEMU_RET_SOFTMMU) {
715 kqemu_record_pc(env->eip + env->segs[R_CS].base);
718 if (loglevel & CPU_LOG_INT) {
719 cpu_dump_state(env, logfile, fprintf, 0);
724 cpu_dump_state(env, stderr, fprintf, 0);
725 fprintf(stderr, "Unsupported return value: 0x%x\n", ret);