Commit f32fc64851c28e2dd3976d08f93006a3eff68a3d

Authored by bellard
1 parent f1c85677

optional support for kernel code virtualization


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1753 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-exec.c
@@ -627,6 +627,9 @@ int cpu_exec(CPUState *env1) @@ -627,6 +627,9 @@ int cpu_exec(CPUState *env1)
627 jump. */ 627 jump. */
628 { 628 {
629 if (T0 != 0 && 629 if (T0 != 0 &&
  630 +#if USE_KQEMU
  631 + (env->kqemu_enabled != 2) &&
  632 +#endif
630 tb->page_addr[1] == -1 633 tb->page_addr[1] == -1
631 #if defined(TARGET_I386) && defined(USE_CODE_COPY) 634 #if defined(TARGET_I386) && defined(USE_CODE_COPY)
632 && (tb->cflags & CF_CODE_COPY) == 635 && (tb->cflags & CF_CODE_COPY) ==
@@ -756,6 +759,13 @@ int cpu_exec(CPUState *env1) @@ -756,6 +759,13 @@ int cpu_exec(CPUState *env1)
756 T0 = 0; 759 T0 = 0;
757 } 760 }
758 #endif 761 #endif
  762 +#if defined(USE_KQEMU)
  763 +#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
  764 + if (kqemu_is_ok(env) &&
  765 + (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
  766 + cpu_loop_exit();
  767 + }
  768 +#endif
759 } 769 }
760 } else { 770 } else {
761 env_to_regs(); 771 env_to_regs();
exec-all.h
@@ -577,21 +577,27 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) @@ -577,21 +577,27 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
577 577
578 578
579 #ifdef USE_KQEMU 579 #ifdef USE_KQEMU
  580 +#define KQEMU_MODIFY_PAGE_MASK (0xff & ~(VGA_DIRTY_FLAG | CODE_DIRTY_FLAG))
  581 +
580 int kqemu_init(CPUState *env); 582 int kqemu_init(CPUState *env);
581 int kqemu_cpu_exec(CPUState *env); 583 int kqemu_cpu_exec(CPUState *env);
582 void kqemu_flush_page(CPUState *env, target_ulong addr); 584 void kqemu_flush_page(CPUState *env, target_ulong addr);
583 void kqemu_flush(CPUState *env, int global); 585 void kqemu_flush(CPUState *env, int global);
584 void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr); 586 void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr);
  587 +void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr);
585 void kqemu_cpu_interrupt(CPUState *env); 588 void kqemu_cpu_interrupt(CPUState *env);
  589 +void kqemu_record_dump(void);
586 590
587 static inline int kqemu_is_ok(CPUState *env) 591 static inline int kqemu_is_ok(CPUState *env)
588 { 592 {
589 return(env->kqemu_enabled && 593 return(env->kqemu_enabled &&
590 - (env->hflags & HF_CPL_MASK) == 3 &&  
591 - (env->eflags & IOPL_MASK) != IOPL_MASK &&  
592 (env->cr[0] & CR0_PE_MASK) && 594 (env->cr[0] & CR0_PE_MASK) &&
  595 + !(env->hflags & HF_INHIBIT_IRQ_MASK) &&
593 (env->eflags & IF_MASK) && 596 (env->eflags & IF_MASK) &&
594 - !(env->eflags & VM_MASK)); 597 + !(env->eflags & VM_MASK) &&
  598 + (env->kqemu_enabled == 2 ||
  599 + ((env->hflags & HF_CPL_MASK) == 3 &&
  600 + (env->eflags & IOPL_MASK) != IOPL_MASK)));
595 } 601 }
596 602
597 #endif 603 #endif
@@ -1796,6 +1796,11 @@ static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t @@ -1796,6 +1796,11 @@ static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t
1796 #endif 1796 #endif
1797 } 1797 }
1798 stb_p((uint8_t *)(long)addr, val); 1798 stb_p((uint8_t *)(long)addr, val);
  1799 +#ifdef USE_KQEMU
  1800 + if (cpu_single_env->kqemu_enabled &&
  1801 + (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
  1802 + kqemu_modify_page(cpu_single_env, ram_addr);
  1803 +#endif
1799 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG); 1804 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
1800 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags; 1805 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
1801 /* we remove the notdirty callback only if the code has been 1806 /* we remove the notdirty callback only if the code has been
@@ -1817,6 +1822,11 @@ static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t @@ -1817,6 +1822,11 @@ static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t
1817 #endif 1822 #endif
1818 } 1823 }
1819 stw_p((uint8_t *)(long)addr, val); 1824 stw_p((uint8_t *)(long)addr, val);
  1825 +#ifdef USE_KQEMU
  1826 + if (cpu_single_env->kqemu_enabled &&
  1827 + (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
  1828 + kqemu_modify_page(cpu_single_env, ram_addr);
  1829 +#endif
1820 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG); 1830 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
1821 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags; 1831 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
1822 /* we remove the notdirty callback only if the code has been 1832 /* we remove the notdirty callback only if the code has been
@@ -1838,6 +1848,11 @@ static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t @@ -1838,6 +1848,11 @@ static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t
1838 #endif 1848 #endif
1839 } 1849 }
1840 stl_p((uint8_t *)(long)addr, val); 1850 stl_p((uint8_t *)(long)addr, val);
  1851 +#ifdef USE_KQEMU
  1852 + if (cpu_single_env->kqemu_enabled &&
  1853 + (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
  1854 + kqemu_modify_page(cpu_single_env, ram_addr);
  1855 +#endif
1841 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG); 1856 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
1842 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags; 1857 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
1843 /* we remove the notdirty callback only if the code has been 1858 /* we remove the notdirty callback only if the code has been
@@ -54,6 +54,9 @@ @@ -54,6 +54,9 @@
54 #define KQEMU_MAX_RAM_PAGES_TO_UPDATE 512 54 #define KQEMU_MAX_RAM_PAGES_TO_UPDATE 512
55 #define KQEMU_RAM_PAGES_UPDATE_ALL (KQEMU_MAX_RAM_PAGES_TO_UPDATE + 1) 55 #define KQEMU_RAM_PAGES_UPDATE_ALL (KQEMU_MAX_RAM_PAGES_TO_UPDATE + 1)
56 #endif 56 #endif
  57 +#ifndef KQEMU_MAX_MODIFIED_RAM_PAGES
  58 +#define KQEMU_MAX_MODIFIED_RAM_PAGES 512
  59 +#endif
57 60
58 #ifdef _WIN32 61 #ifdef _WIN32
59 #define KQEMU_DEVICE "\\\\.\\kqemu" 62 #define KQEMU_DEVICE "\\\\.\\kqemu"
@@ -71,11 +74,18 @@ int kqemu_fd = KQEMU_INVALID_FD; @@ -71,11 +74,18 @@ int kqemu_fd = KQEMU_INVALID_FD;
71 #define kqemu_closefd(x) close(x) 74 #define kqemu_closefd(x) close(x)
72 #endif 75 #endif
73 76
  77 +/* 0 = not allowed
  78 + 1 = user kqemu
  79 + 2 = kernel kqemu
  80 +*/
74 int kqemu_allowed = 1; 81 int kqemu_allowed = 1;
75 unsigned long *pages_to_flush; 82 unsigned long *pages_to_flush;
76 unsigned int nb_pages_to_flush; 83 unsigned int nb_pages_to_flush;
77 unsigned long *ram_pages_to_update; 84 unsigned long *ram_pages_to_update;
78 unsigned int nb_ram_pages_to_update; 85 unsigned int nb_ram_pages_to_update;
  86 +unsigned long *modified_ram_pages;
  87 +unsigned int nb_modified_ram_pages;
  88 +uint8_t *modified_ram_pages_table;
79 extern uint32_t **l1_phys_map; 89 extern uint32_t **l1_phys_map;
80 90
81 #define cpuid(index, eax, ebx, ecx, edx) \ 91 #define cpuid(index, eax, ebx, ecx, edx) \
@@ -185,6 +195,14 @@ int kqemu_init(CPUState *env) @@ -185,6 +195,14 @@ int kqemu_init(CPUState *env)
185 if (!ram_pages_to_update) 195 if (!ram_pages_to_update)
186 goto fail; 196 goto fail;
187 197
  198 + modified_ram_pages = qemu_vmalloc(KQEMU_MAX_MODIFIED_RAM_PAGES *
  199 + sizeof(unsigned long));
  200 + if (!modified_ram_pages)
  201 + goto fail;
  202 + modified_ram_pages_table = qemu_mallocz(phys_ram_size >> TARGET_PAGE_BITS);
  203 + if (!modified_ram_pages_table)
  204 + goto fail;
  205 +
188 init.ram_base = phys_ram_base; 206 init.ram_base = phys_ram_base;
189 init.ram_size = phys_ram_size; 207 init.ram_size = phys_ram_size;
190 init.ram_dirty = phys_ram_dirty; 208 init.ram_dirty = phys_ram_dirty;
@@ -193,6 +211,9 @@ int kqemu_init(CPUState *env) @@ -193,6 +211,9 @@ int kqemu_init(CPUState *env)
193 #if KQEMU_VERSION >= 0x010200 211 #if KQEMU_VERSION >= 0x010200
194 init.ram_pages_to_update = ram_pages_to_update; 212 init.ram_pages_to_update = ram_pages_to_update;
195 #endif 213 #endif
  214 +#if KQEMU_VERSION >= 0x010300
  215 + init.modified_ram_pages = modified_ram_pages;
  216 +#endif
196 #ifdef _WIN32 217 #ifdef _WIN32
197 ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &init, sizeof(init), 218 ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &init, sizeof(init),
198 NULL, 0, &temp, NULL) == TRUE ? 0 : -1; 219 NULL, 0, &temp, NULL) == TRUE ? 0 : -1;
@@ -207,7 +228,7 @@ int kqemu_init(CPUState *env) @@ -207,7 +228,7 @@ int kqemu_init(CPUState *env)
207 return -1; 228 return -1;
208 } 229 }
209 kqemu_update_cpuid(env); 230 kqemu_update_cpuid(env);
210 - env->kqemu_enabled = 1; 231 + env->kqemu_enabled = kqemu_allowed;
211 nb_pages_to_flush = 0; 232 nb_pages_to_flush = 0;
212 nb_ram_pages_to_update = 0; 233 nb_ram_pages_to_update = 0;
213 return 0; 234 return 0;
@@ -215,7 +236,7 @@ int kqemu_init(CPUState *env) @@ -215,7 +236,7 @@ int kqemu_init(CPUState *env)
215 236
216 void kqemu_flush_page(CPUState *env, target_ulong addr) 237 void kqemu_flush_page(CPUState *env, target_ulong addr)
217 { 238 {
218 -#ifdef DEBUG 239 +#if defined(DEBUG)
219 if (loglevel & CPU_LOG_INT) { 240 if (loglevel & CPU_LOG_INT) {
220 fprintf(logfile, "kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr); 241 fprintf(logfile, "kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr);
221 } 242 }
@@ -252,6 +273,49 @@ void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr) @@ -252,6 +273,49 @@ void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr)
252 ram_pages_to_update[nb_ram_pages_to_update++] = ram_addr; 273 ram_pages_to_update[nb_ram_pages_to_update++] = ram_addr;
253 } 274 }
254 275
  276 +static void kqemu_reset_modified_ram_pages(void)
  277 +{
  278 + int i;
  279 + unsigned long page_index;
  280 +
  281 + for(i = 0; i < nb_modified_ram_pages; i++) {
  282 + page_index = modified_ram_pages[i] >> TARGET_PAGE_BITS;
  283 + modified_ram_pages_table[page_index] = 0;
  284 + }
  285 + nb_modified_ram_pages = 0;
  286 +}
  287 +
  288 +void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr)
  289 +{
  290 + unsigned long page_index;
  291 + int ret;
  292 +#ifdef _WIN32
  293 + DWORD temp;
  294 +#endif
  295 +
  296 + page_index = ram_addr >> TARGET_PAGE_BITS;
  297 + if (!modified_ram_pages_table[page_index]) {
  298 +#if 0
  299 + printf("%d: modify_page=%08lx\n", nb_modified_ram_pages, ram_addr);
  300 +#endif
  301 + modified_ram_pages_table[page_index] = 1;
  302 + modified_ram_pages[nb_modified_ram_pages++] = ram_addr;
  303 + if (nb_modified_ram_pages >= KQEMU_MAX_MODIFIED_RAM_PAGES) {
  304 + /* flush */
  305 +#ifdef _WIN32
  306 + ret = DeviceIoControl(kqemu_fd, KQEMU_MODIFY_RAM_PAGES,
  307 + &nb_modified_ram_pages,
  308 + sizeof(nb_modified_ram_pages),
  309 + NULL, 0, &temp, NULL);
  310 +#else
  311 + ret = ioctl(kqemu_fd, KQEMU_MODIFY_RAM_PAGES,
  312 + &nb_modified_ram_pages);
  313 +#endif
  314 + kqemu_reset_modified_ram_pages();
  315 + }
  316 + }
  317 +}
  318 +
255 struct fpstate { 319 struct fpstate {
256 uint16_t fpuc; 320 uint16_t fpuc;
257 uint16_t dummy1; 321 uint16_t dummy1;
@@ -442,7 +506,7 @@ static int do_syscall(CPUState *env, @@ -442,7 +506,7 @@ static int do_syscall(CPUState *env,
442 return 2; 506 return 2;
443 } 507 }
444 508
445 -#ifdef PROFILE 509 +#ifdef CONFIG_PROFILER
446 510
447 #define PC_REC_SIZE 1 511 #define PC_REC_SIZE 1
448 #define PC_REC_HASH_BITS 16 512 #define PC_REC_HASH_BITS 16
@@ -454,10 +518,10 @@ typedef struct PCRecord { @@ -454,10 +518,10 @@ typedef struct PCRecord {
454 struct PCRecord *next; 518 struct PCRecord *next;
455 } PCRecord; 519 } PCRecord;
456 520
457 -PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];  
458 -int nb_pc_records; 521 +static PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];
  522 +static int nb_pc_records;
459 523
460 -void kqemu_record_pc(unsigned long pc) 524 +static void kqemu_record_pc(unsigned long pc)
461 { 525 {
462 unsigned long h; 526 unsigned long h;
463 PCRecord **pr, *r; 527 PCRecord **pr, *r;
@@ -484,7 +548,7 @@ void kqemu_record_pc(unsigned long pc) @@ -484,7 +548,7 @@ void kqemu_record_pc(unsigned long pc)
484 nb_pc_records++; 548 nb_pc_records++;
485 } 549 }
486 550
487 -int pc_rec_cmp(const void *p1, const void *p2) 551 +static int pc_rec_cmp(const void *p1, const void *p2)
488 { 552 {
489 PCRecord *r1 = *(PCRecord **)p1; 553 PCRecord *r1 = *(PCRecord **)p1;
490 PCRecord *r2 = *(PCRecord **)p2; 554 PCRecord *r2 = *(PCRecord **)p2;
@@ -496,6 +560,21 @@ int pc_rec_cmp(const void *p1, const void *p2) @@ -496,6 +560,21 @@ int pc_rec_cmp(const void *p1, const void *p2)
496 return -1; 560 return -1;
497 } 561 }
498 562
  563 +static void kqemu_record_flush(void)
  564 +{
  565 + PCRecord *r, *r_next;
  566 + int h;
  567 +
  568 + for(h = 0; h < PC_REC_HASH_SIZE; h++) {
  569 + for(r = pc_rec_hash[h]; r != NULL; r = r_next) {
  570 + r_next = r->next;
  571 + free(r);
  572 + }
  573 + pc_rec_hash[h] = NULL;
  574 + }
  575 + nb_pc_records = 0;
  576 +}
  577 +
499 void kqemu_record_dump(void) 578 void kqemu_record_dump(void)
500 { 579 {
501 PCRecord **pr, *r; 580 PCRecord **pr, *r;
@@ -532,21 +611,26 @@ void kqemu_record_dump(void) @@ -532,21 +611,26 @@ void kqemu_record_dump(void)
532 } 611 }
533 fclose(f); 612 fclose(f);
534 free(pr); 613 free(pr);
535 -}  
536 -#else  
537 -void kqemu_record_dump(void)  
538 -{ 614 +
  615 + kqemu_record_flush();
539 } 616 }
540 #endif 617 #endif
541 618
542 int kqemu_cpu_exec(CPUState *env) 619 int kqemu_cpu_exec(CPUState *env)
543 { 620 {
544 struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state; 621 struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;
545 - int ret; 622 + int ret, cpl, i;
  623 +#ifdef CONFIG_PROFILER
  624 + int64_t ti;
  625 +#endif
  626 +
546 #ifdef _WIN32 627 #ifdef _WIN32
547 DWORD temp; 628 DWORD temp;
548 #endif 629 #endif
549 630
  631 +#ifdef CONFIG_PROFILER
  632 + ti = profile_getclock();
  633 +#endif
550 #ifdef DEBUG 634 #ifdef DEBUG
551 if (loglevel & CPU_LOG_INT) { 635 if (loglevel & CPU_LOG_INT) {
552 fprintf(logfile, "kqemu: cpu_exec: enter\n"); 636 fprintf(logfile, "kqemu: cpu_exec: enter\n");
@@ -569,6 +653,19 @@ int kqemu_cpu_exec(CPUState *env) @@ -569,6 +653,19 @@ int kqemu_cpu_exec(CPUState *env)
569 #if KQEMU_VERSION >= 0x010100 653 #if KQEMU_VERSION >= 0x010100
570 kenv->efer = env->efer; 654 kenv->efer = env->efer;
571 #endif 655 #endif
  656 +#if KQEMU_VERSION >= 0x010300
  657 + kenv->tsc_offset = 0;
  658 + kenv->star = env->star;
  659 + kenv->sysenter_cs = env->sysenter_cs;
  660 + kenv->sysenter_esp = env->sysenter_esp;
  661 + kenv->sysenter_eip = env->sysenter_eip;
  662 +#ifdef __x86_64__
  663 + kenv->lstar = env->lstar;
  664 + kenv->cstar = env->cstar;
  665 + kenv->fmask = env->fmask;
  666 + kenv->kernelgsbase = env->kernelgsbase;
  667 +#endif
  668 +#endif
572 if (env->dr[7] & 0xff) { 669 if (env->dr[7] & 0xff) {
573 kenv->dr7 = env->dr[7]; 670 kenv->dr7 = env->dr[7];
574 kenv->dr0 = env->dr[0]; 671 kenv->dr0 = env->dr[0];
@@ -579,21 +676,24 @@ int kqemu_cpu_exec(CPUState *env) @@ -579,21 +676,24 @@ int kqemu_cpu_exec(CPUState *env)
579 kenv->dr7 = 0; 676 kenv->dr7 = 0;
580 } 677 }
581 kenv->dr6 = env->dr[6]; 678 kenv->dr6 = env->dr[6];
582 - kenv->cpl = 3; 679 + cpl = (env->hflags & HF_CPL_MASK);
  680 + kenv->cpl = cpl;
583 kenv->nb_pages_to_flush = nb_pages_to_flush; 681 kenv->nb_pages_to_flush = nb_pages_to_flush;
584 - nb_pages_to_flush = 0;  
585 #if KQEMU_VERSION >= 0x010200 682 #if KQEMU_VERSION >= 0x010200
586 - kenv->user_only = 1; 683 + kenv->user_only = (env->kqemu_enabled == 1);
587 kenv->nb_ram_pages_to_update = nb_ram_pages_to_update; 684 kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;
588 #endif 685 #endif
589 nb_ram_pages_to_update = 0; 686 nb_ram_pages_to_update = 0;
590 687
591 - if (!(kenv->cr0 & CR0_TS_MASK)) {  
592 - if (env->cpuid_features & CPUID_FXSR)  
593 - restore_native_fp_fxrstor(env);  
594 - else  
595 - restore_native_fp_frstor(env);  
596 - } 688 +#if KQEMU_VERSION >= 0x010300
  689 + kenv->nb_modified_ram_pages = nb_modified_ram_pages;
  690 +#endif
  691 + kqemu_reset_modified_ram_pages();
  692 +
  693 + if (env->cpuid_features & CPUID_FXSR)
  694 + restore_native_fp_fxrstor(env);
  695 + else
  696 + restore_native_fp_frstor(env);
597 697
598 #ifdef _WIN32 698 #ifdef _WIN32
599 if (DeviceIoControl(kqemu_fd, KQEMU_EXEC, 699 if (DeviceIoControl(kqemu_fd, KQEMU_EXEC,
@@ -612,30 +712,49 @@ int kqemu_cpu_exec(CPUState *env) @@ -612,30 +712,49 @@ int kqemu_cpu_exec(CPUState *env)
612 ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv); 712 ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);
613 #endif 713 #endif
614 #endif 714 #endif
615 - if (!(kenv->cr0 & CR0_TS_MASK)) {  
616 - if (env->cpuid_features & CPUID_FXSR)  
617 - save_native_fp_fxsave(env);  
618 - else  
619 - save_native_fp_fsave(env);  
620 - } 715 + if (env->cpuid_features & CPUID_FXSR)
  716 + save_native_fp_fxsave(env);
  717 + else
  718 + save_native_fp_fsave(env);
621 719
622 memcpy(env->regs, kenv->regs, sizeof(env->regs)); 720 memcpy(env->regs, kenv->regs, sizeof(env->regs));
623 env->eip = kenv->eip; 721 env->eip = kenv->eip;
624 env->eflags = kenv->eflags; 722 env->eflags = kenv->eflags;
625 memcpy(env->segs, kenv->segs, sizeof(env->segs)); 723 memcpy(env->segs, kenv->segs, sizeof(env->segs));
  724 + cpu_x86_set_cpl(env, kenv->cpl);
  725 + memcpy(&env->ldt, &kenv->ldt, sizeof(env->ldt));
626 #if 0 726 #if 0
627 /* no need to restore that */ 727 /* no need to restore that */
628 - memcpy(env->ldt, kenv->ldt, sizeof(env->ldt));  
629 memcpy(env->tr, kenv->tr, sizeof(env->tr)); 728 memcpy(env->tr, kenv->tr, sizeof(env->tr));
630 memcpy(env->gdt, kenv->gdt, sizeof(env->gdt)); 729 memcpy(env->gdt, kenv->gdt, sizeof(env->gdt));
631 memcpy(env->idt, kenv->idt, sizeof(env->idt)); 730 memcpy(env->idt, kenv->idt, sizeof(env->idt));
632 - env->cr[0] = kenv->cr0;  
633 - env->cr[3] = kenv->cr3;  
634 - env->cr[4] = kenv->cr4;  
635 env->a20_mask = kenv->a20_mask; 731 env->a20_mask = kenv->a20_mask;
636 #endif 732 #endif
  733 + env->cr[0] = kenv->cr0;
  734 + env->cr[4] = kenv->cr4;
  735 + env->cr[3] = kenv->cr3;
637 env->cr[2] = kenv->cr2; 736 env->cr[2] = kenv->cr2;
638 env->dr[6] = kenv->dr6; 737 env->dr[6] = kenv->dr6;
  738 +#if KQEMU_VERSION >= 0x010300
  739 +#ifdef __x86_64__
  740 + env->kernelgsbase = kenv->kernelgsbase;
  741 +#endif
  742 +#endif
  743 +
  744 + /* flush pages as indicated by kqemu */
  745 + if (kenv->nb_pages_to_flush >= KQEMU_FLUSH_ALL) {
  746 + tlb_flush(env, 1);
  747 + } else {
  748 + for(i = 0; i < kenv->nb_pages_to_flush; i++) {
  749 + tlb_flush_page(env, pages_to_flush[i]);
  750 + }
  751 + }
  752 + nb_pages_to_flush = 0;
  753 +
  754 +#ifdef CONFIG_PROFILER
  755 + kqemu_time += profile_getclock() - ti;
  756 + kqemu_exec_count++;
  757 +#endif
639 758
640 #if KQEMU_VERSION >= 0x010200 759 #if KQEMU_VERSION >= 0x010200
641 if (kenv->nb_ram_pages_to_update > 0) { 760 if (kenv->nb_ram_pages_to_update > 0) {
@@ -643,6 +762,16 @@ int kqemu_cpu_exec(CPUState *env) @@ -643,6 +762,16 @@ int kqemu_cpu_exec(CPUState *env)
643 } 762 }
644 #endif 763 #endif
645 764
  765 +#if KQEMU_VERSION >= 0x010300
  766 + if (kenv->nb_modified_ram_pages > 0) {
  767 + for(i = 0; i < kenv->nb_modified_ram_pages; i++) {
  768 + unsigned long addr;
  769 + addr = modified_ram_pages[i];
  770 + tb_invalidate_phys_page_range(addr, addr + TARGET_PAGE_SIZE, 0);
  771 + }
  772 + }
  773 +#endif
  774 +
646 /* restore the hidden flags */ 775 /* restore the hidden flags */
647 { 776 {
648 unsigned int new_hflags; 777 unsigned int new_hflags;
@@ -679,7 +808,14 @@ int kqemu_cpu_exec(CPUState *env) @@ -679,7 +808,14 @@ int kqemu_cpu_exec(CPUState *env)
679 ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) | 808 ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |
680 new_hflags; 809 new_hflags;
681 } 810 }
682 - 811 + /* update FPU flags */
  812 + env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
  813 + ((env->cr[0] << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
  814 + if (env->cr[4] & CR4_OSFXSR_MASK)
  815 + env->hflags |= HF_OSFXSR_MASK;
  816 + else
  817 + env->hflags &= ~HF_OSFXSR_MASK;
  818 +
683 #ifdef DEBUG 819 #ifdef DEBUG
684 if (loglevel & CPU_LOG_INT) { 820 if (loglevel & CPU_LOG_INT) {
685 fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret); 821 fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
@@ -694,6 +830,9 @@ int kqemu_cpu_exec(CPUState *env) @@ -694,6 +830,9 @@ int kqemu_cpu_exec(CPUState *env)
694 env->error_code = 0; 830 env->error_code = 0;
695 env->exception_is_int = 1; 831 env->exception_is_int = 1;
696 env->exception_next_eip = kenv->next_eip; 832 env->exception_next_eip = kenv->next_eip;
  833 +#ifdef CONFIG_PROFILER
  834 + kqemu_ret_int_count++;
  835 +#endif
697 #ifdef DEBUG 836 #ifdef DEBUG
698 if (loglevel & CPU_LOG_INT) { 837 if (loglevel & CPU_LOG_INT) {
699 fprintf(logfile, "kqemu: interrupt v=%02x:\n", 838 fprintf(logfile, "kqemu: interrupt v=%02x:\n",
@@ -707,6 +846,9 @@ int kqemu_cpu_exec(CPUState *env) @@ -707,6 +846,9 @@ int kqemu_cpu_exec(CPUState *env)
707 env->error_code = kenv->error_code; 846 env->error_code = kenv->error_code;
708 env->exception_is_int = 0; 847 env->exception_is_int = 0;
709 env->exception_next_eip = 0; 848 env->exception_next_eip = 0;
  849 +#ifdef CONFIG_PROFILER
  850 + kqemu_ret_excp_count++;
  851 +#endif
710 #ifdef DEBUG 852 #ifdef DEBUG
711 if (loglevel & CPU_LOG_INT) { 853 if (loglevel & CPU_LOG_INT) {
712 fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n", 854 fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n",
@@ -716,6 +858,9 @@ int kqemu_cpu_exec(CPUState *env) @@ -716,6 +858,9 @@ int kqemu_cpu_exec(CPUState *env)
716 #endif 858 #endif
717 return 1; 859 return 1;
718 } else if (ret == KQEMU_RET_INTR) { 860 } else if (ret == KQEMU_RET_INTR) {
  861 +#ifdef CONFIG_PROFILER
  862 + kqemu_ret_intr_count++;
  863 +#endif
719 #ifdef DEBUG 864 #ifdef DEBUG
720 if (loglevel & CPU_LOG_INT) { 865 if (loglevel & CPU_LOG_INT) {
721 cpu_dump_state(env, logfile, fprintf, 0); 866 cpu_dump_state(env, logfile, fprintf, 0);
@@ -723,8 +868,11 @@ int kqemu_cpu_exec(CPUState *env) @@ -723,8 +868,11 @@ int kqemu_cpu_exec(CPUState *env)
723 #endif 868 #endif
724 return 0; 869 return 0;
725 } else if (ret == KQEMU_RET_SOFTMMU) { 870 } else if (ret == KQEMU_RET_SOFTMMU) {
726 -#ifdef PROFILE  
727 - kqemu_record_pc(env->eip + env->segs[R_CS].base); 871 +#ifdef CONFIG_PROFILER
  872 + {
  873 + unsigned long pc = env->eip + env->segs[R_CS].base;
  874 + kqemu_record_pc(pc);
  875 + }
728 #endif 876 #endif
729 #ifdef DEBUG 877 #ifdef DEBUG
730 if (loglevel & CPU_LOG_INT) { 878 if (loglevel & CPU_LOG_INT) {