Diff for /qemu/kqemu.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2018/04/24 16:37:52 version 1.1.1.2, 2018/04/24 16:40:30
Line 44 Line 44
   
 #include <unistd.h>  #include <unistd.h>
 #include <fcntl.h>  #include <fcntl.h>
 #include "kqemu/kqemu.h"  #include "kqemu.h"
   
 /* compatibility stuff */  /* compatibility stuff */
 #ifndef KQEMU_RET_SYSCALL  #ifndef KQEMU_RET_SYSCALL
Line 54 Line 54
 #define KQEMU_MAX_RAM_PAGES_TO_UPDATE 512  #define KQEMU_MAX_RAM_PAGES_TO_UPDATE 512
 #define KQEMU_RAM_PAGES_UPDATE_ALL (KQEMU_MAX_RAM_PAGES_TO_UPDATE + 1)  #define KQEMU_RAM_PAGES_UPDATE_ALL (KQEMU_MAX_RAM_PAGES_TO_UPDATE + 1)
 #endif  #endif
   #ifndef KQEMU_MAX_MODIFIED_RAM_PAGES
   #define KQEMU_MAX_MODIFIED_RAM_PAGES 512
   #endif
   
 #ifdef _WIN32  #ifdef _WIN32
 #define KQEMU_DEVICE "\\\\.\\kqemu"  #define KQEMU_DEVICE "\\\\.\\kqemu"
Line 71  int kqemu_fd = KQEMU_INVALID_FD; Line 74  int kqemu_fd = KQEMU_INVALID_FD;
 #define kqemu_closefd(x) close(x)  #define kqemu_closefd(x) close(x)
 #endif  #endif
   
   /* 0 = not allowed
      1 = user kqemu
      2 = kernel kqemu
   */
 int kqemu_allowed = 1;  int kqemu_allowed = 1;
 unsigned long *pages_to_flush;  unsigned long *pages_to_flush;
 unsigned int nb_pages_to_flush;  unsigned int nb_pages_to_flush;
 unsigned long *ram_pages_to_update;  unsigned long *ram_pages_to_update;
 unsigned int nb_ram_pages_to_update;  unsigned int nb_ram_pages_to_update;
   unsigned long *modified_ram_pages;
   unsigned int nb_modified_ram_pages;
   uint8_t *modified_ram_pages_table;
 extern uint32_t **l1_phys_map;  extern uint32_t **l1_phys_map;
   
 #define cpuid(index, eax, ebx, ecx, edx) \  #define cpuid(index, eax, ebx, ecx, edx) \
Line 185  int kqemu_init(CPUState *env) Line 195  int kqemu_init(CPUState *env)
     if (!ram_pages_to_update)      if (!ram_pages_to_update)
         goto fail;          goto fail;
   
       modified_ram_pages = qemu_vmalloc(KQEMU_MAX_MODIFIED_RAM_PAGES * 
                                         sizeof(unsigned long));
       if (!modified_ram_pages)
           goto fail;
       modified_ram_pages_table = qemu_mallocz(phys_ram_size >> TARGET_PAGE_BITS);
       if (!modified_ram_pages_table)
           goto fail;
   
     init.ram_base = phys_ram_base;      init.ram_base = phys_ram_base;
     init.ram_size = phys_ram_size;      init.ram_size = phys_ram_size;
     init.ram_dirty = phys_ram_dirty;      init.ram_dirty = phys_ram_dirty;
Line 193  int kqemu_init(CPUState *env) Line 211  int kqemu_init(CPUState *env)
 #if KQEMU_VERSION >= 0x010200  #if KQEMU_VERSION >= 0x010200
     init.ram_pages_to_update = ram_pages_to_update;      init.ram_pages_to_update = ram_pages_to_update;
 #endif  #endif
   #if KQEMU_VERSION >= 0x010300
       init.modified_ram_pages = modified_ram_pages;
   #endif
 #ifdef _WIN32  #ifdef _WIN32
     ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &init, sizeof(init),      ret = DeviceIoControl(kqemu_fd, KQEMU_INIT, &init, sizeof(init),
                           NULL, 0, &temp, NULL) == TRUE ? 0 : -1;                            NULL, 0, &temp, NULL) == TRUE ? 0 : -1;
Line 207  int kqemu_init(CPUState *env) Line 228  int kqemu_init(CPUState *env)
         return -1;          return -1;
     }      }
     kqemu_update_cpuid(env);      kqemu_update_cpuid(env);
     env->kqemu_enabled = 1;      env->kqemu_enabled = kqemu_allowed;
     nb_pages_to_flush = 0;      nb_pages_to_flush = 0;
     nb_ram_pages_to_update = 0;      nb_ram_pages_to_update = 0;
     return 0;      return 0;
Line 215  int kqemu_init(CPUState *env) Line 236  int kqemu_init(CPUState *env)
   
 void kqemu_flush_page(CPUState *env, target_ulong addr)  void kqemu_flush_page(CPUState *env, target_ulong addr)
 {  {
 #ifdef DEBUG  #if defined(DEBUG)
     if (loglevel & CPU_LOG_INT) {      if (loglevel & CPU_LOG_INT) {
         fprintf(logfile, "kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr);          fprintf(logfile, "kqemu_flush_page: addr=" TARGET_FMT_lx "\n", addr);
     }      }
Line 252  void kqemu_set_notdirty(CPUState *env, r Line 273  void kqemu_set_notdirty(CPUState *env, r
         ram_pages_to_update[nb_ram_pages_to_update++] = ram_addr;          ram_pages_to_update[nb_ram_pages_to_update++] = ram_addr;
 }  }
   
   static void kqemu_reset_modified_ram_pages(void)
   {
       int i;
       unsigned long page_index;
       
       for(i = 0; i < nb_modified_ram_pages; i++) {
           page_index = modified_ram_pages[i] >> TARGET_PAGE_BITS;
           modified_ram_pages_table[page_index] = 0;
       }
       nb_modified_ram_pages = 0;
   }
   
   void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr)
   {
       unsigned long page_index;
       int ret;
   #ifdef _WIN32
       DWORD temp;
   #endif
   
       page_index = ram_addr >> TARGET_PAGE_BITS;
       if (!modified_ram_pages_table[page_index]) {
   #if 0
           printf("%d: modify_page=%08lx\n", nb_modified_ram_pages, ram_addr);
   #endif
           modified_ram_pages_table[page_index] = 1;
           modified_ram_pages[nb_modified_ram_pages++] = ram_addr;
           if (nb_modified_ram_pages >= KQEMU_MAX_MODIFIED_RAM_PAGES) {
               /* flush */
   #ifdef _WIN32
               ret = DeviceIoControl(kqemu_fd, KQEMU_MODIFY_RAM_PAGES, 
                                     &nb_modified_ram_pages, 
                                     sizeof(nb_modified_ram_pages),
                                     NULL, 0, &temp, NULL);
   #else
               ret = ioctl(kqemu_fd, KQEMU_MODIFY_RAM_PAGES, 
                           &nb_modified_ram_pages);
   #endif
               kqemu_reset_modified_ram_pages();
           }
       }
   }
   
 struct fpstate {  struct fpstate {
     uint16_t fpuc;      uint16_t fpuc;
     uint16_t dummy1;      uint16_t dummy1;
Line 442  static int do_syscall(CPUState *env, Line 506  static int do_syscall(CPUState *env,
     return 2;      return 2;
 }  }
   
 #ifdef PROFILE  #ifdef CONFIG_PROFILER
   
 #define PC_REC_SIZE 1  #define PC_REC_SIZE 1
 #define PC_REC_HASH_BITS 16  #define PC_REC_HASH_BITS 16
Line 454  typedef struct PCRecord { Line 518  typedef struct PCRecord {
     struct PCRecord *next;      struct PCRecord *next;
 } PCRecord;  } PCRecord;
   
 PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];  static PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];
 int nb_pc_records;  static int nb_pc_records;
   
 void kqemu_record_pc(unsigned long pc)  static void kqemu_record_pc(unsigned long pc)
 {  {
     unsigned long h;      unsigned long h;
     PCRecord **pr, *r;      PCRecord **pr, *r;
Line 484  void kqemu_record_pc(unsigned long pc) Line 548  void kqemu_record_pc(unsigned long pc)
     nb_pc_records++;      nb_pc_records++;
 }  }
   
 int pc_rec_cmp(const void *p1, const void *p2)  static int pc_rec_cmp(const void *p1, const void *p2)
 {  {
     PCRecord *r1 = *(PCRecord **)p1;      PCRecord *r1 = *(PCRecord **)p1;
     PCRecord *r2 = *(PCRecord **)p2;      PCRecord *r2 = *(PCRecord **)p2;
Line 496  int pc_rec_cmp(const void *p1, const voi Line 560  int pc_rec_cmp(const void *p1, const voi
         return -1;          return -1;
 }  }
   
   static void kqemu_record_flush(void)
   {
       PCRecord *r, *r_next;
       int h;
   
       for(h = 0; h < PC_REC_HASH_SIZE; h++) {
           for(r = pc_rec_hash[h]; r != NULL; r = r_next) {
               r_next = r->next;
               free(r);
           }
           pc_rec_hash[h] = NULL;
       }
       nb_pc_records = 0;
   }
   
 void kqemu_record_dump(void)  void kqemu_record_dump(void)
 {  {
     PCRecord **pr, *r;      PCRecord **pr, *r;
Line 532  void kqemu_record_dump(void) Line 611  void kqemu_record_dump(void)
     }      }
     fclose(f);      fclose(f);
     free(pr);      free(pr);
 }  
 #else      kqemu_record_flush();
 void kqemu_record_dump(void)  
 {  
 }  }
 #endif  #endif
   
 int kqemu_cpu_exec(CPUState *env)  int kqemu_cpu_exec(CPUState *env)
 {  {
     struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;      struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;
     int ret;      int ret, cpl, i;
   #ifdef CONFIG_PROFILER
       int64_t ti;
   #endif
   
 #ifdef _WIN32  #ifdef _WIN32
     DWORD temp;      DWORD temp;
 #endif  #endif
   
   #ifdef CONFIG_PROFILER
       ti = profile_getclock();
   #endif
 #ifdef DEBUG  #ifdef DEBUG
     if (loglevel & CPU_LOG_INT) {      if (loglevel & CPU_LOG_INT) {
         fprintf(logfile, "kqemu: cpu_exec: enter\n");          fprintf(logfile, "kqemu: cpu_exec: enter\n");
Line 569  int kqemu_cpu_exec(CPUState *env) Line 653  int kqemu_cpu_exec(CPUState *env)
 #if KQEMU_VERSION >= 0x010100  #if KQEMU_VERSION >= 0x010100
     kenv->efer = env->efer;      kenv->efer = env->efer;
 #endif  #endif
   #if KQEMU_VERSION >= 0x010300
       kenv->tsc_offset = 0;
       kenv->star = env->star;
       kenv->sysenter_cs = env->sysenter_cs;
       kenv->sysenter_esp = env->sysenter_esp;
       kenv->sysenter_eip = env->sysenter_eip;
   #ifdef __x86_64__
       kenv->lstar = env->lstar;
       kenv->cstar = env->cstar;
       kenv->fmask = env->fmask;
       kenv->kernelgsbase = env->kernelgsbase;
   #endif
   #endif
     if (env->dr[7] & 0xff) {      if (env->dr[7] & 0xff) {
         kenv->dr7 = env->dr[7];          kenv->dr7 = env->dr[7];
         kenv->dr0 = env->dr[0];          kenv->dr0 = env->dr[0];
Line 579  int kqemu_cpu_exec(CPUState *env) Line 676  int kqemu_cpu_exec(CPUState *env)
         kenv->dr7 = 0;          kenv->dr7 = 0;
     }      }
     kenv->dr6 = env->dr[6];      kenv->dr6 = env->dr[6];
     kenv->cpl = 3;      cpl = (env->hflags & HF_CPL_MASK);
       kenv->cpl = cpl;
     kenv->nb_pages_to_flush = nb_pages_to_flush;      kenv->nb_pages_to_flush = nb_pages_to_flush;
     nb_pages_to_flush = 0;  
 #if KQEMU_VERSION >= 0x010200  #if KQEMU_VERSION >= 0x010200
     kenv->user_only = 1;      kenv->user_only = (env->kqemu_enabled == 1);
     kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;      kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;
 #endif  #endif
     nb_ram_pages_to_update = 0;      nb_ram_pages_to_update = 0;
           
     if (!(kenv->cr0 & CR0_TS_MASK)) {  #if KQEMU_VERSION >= 0x010300
         if (env->cpuid_features & CPUID_FXSR)      kenv->nb_modified_ram_pages = nb_modified_ram_pages;
             restore_native_fp_fxrstor(env);  #endif
         else      kqemu_reset_modified_ram_pages();
             restore_native_fp_frstor(env);  
     }      if (env->cpuid_features & CPUID_FXSR)
           restore_native_fp_fxrstor(env);
       else
           restore_native_fp_frstor(env);
   
 #ifdef _WIN32  #ifdef _WIN32
     if (DeviceIoControl(kqemu_fd, KQEMU_EXEC,      if (DeviceIoControl(kqemu_fd, KQEMU_EXEC,
Line 612  int kqemu_cpu_exec(CPUState *env) Line 712  int kqemu_cpu_exec(CPUState *env)
     ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);      ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);
 #endif  #endif
 #endif  #endif
     if (!(kenv->cr0 & CR0_TS_MASK)) {      if (env->cpuid_features & CPUID_FXSR)
         if (env->cpuid_features & CPUID_FXSR)          save_native_fp_fxsave(env);
             save_native_fp_fxsave(env);      else
         else          save_native_fp_fsave(env);
             save_native_fp_fsave(env);  
     }  
   
     memcpy(env->regs, kenv->regs, sizeof(env->regs));      memcpy(env->regs, kenv->regs, sizeof(env->regs));
     env->eip = kenv->eip;      env->eip = kenv->eip;
     env->eflags = kenv->eflags;      env->eflags = kenv->eflags;
     memcpy(env->segs, kenv->segs, sizeof(env->segs));      memcpy(env->segs, kenv->segs, sizeof(env->segs));
       cpu_x86_set_cpl(env, kenv->cpl);
       memcpy(&env->ldt, &kenv->ldt, sizeof(env->ldt));
 #if 0  #if 0
     /* no need to restore that */      /* no need to restore that */
     memcpy(env->ldt, kenv->ldt, sizeof(env->ldt));  
     memcpy(env->tr, kenv->tr, sizeof(env->tr));      memcpy(env->tr, kenv->tr, sizeof(env->tr));
     memcpy(env->gdt, kenv->gdt, sizeof(env->gdt));      memcpy(env->gdt, kenv->gdt, sizeof(env->gdt));
     memcpy(env->idt, kenv->idt, sizeof(env->idt));      memcpy(env->idt, kenv->idt, sizeof(env->idt));
     env->cr[0] = kenv->cr0;  
     env->cr[3] = kenv->cr3;  
     env->cr[4] = kenv->cr4;  
     env->a20_mask = kenv->a20_mask;      env->a20_mask = kenv->a20_mask;
 #endif  #endif
       env->cr[0] = kenv->cr0;
       env->cr[4] = kenv->cr4;
       env->cr[3] = kenv->cr3;
     env->cr[2] = kenv->cr2;      env->cr[2] = kenv->cr2;
     env->dr[6] = kenv->dr6;      env->dr[6] = kenv->dr6;
   #if KQEMU_VERSION >= 0x010300
   #ifdef __x86_64__
       env->kernelgsbase = kenv->kernelgsbase;
   #endif
   #endif
   
       /* flush pages as indicated by kqemu */
       if (kenv->nb_pages_to_flush >= KQEMU_FLUSH_ALL) {
           tlb_flush(env, 1);
       } else {
           for(i = 0; i < kenv->nb_pages_to_flush; i++) {
               tlb_flush_page(env, pages_to_flush[i]);
           }
       }
       nb_pages_to_flush = 0;
   
   #ifdef CONFIG_PROFILER
       kqemu_time += profile_getclock() - ti;
       kqemu_exec_count++;
   #endif
   
 #if KQEMU_VERSION >= 0x010200  #if KQEMU_VERSION >= 0x010200
     if (kenv->nb_ram_pages_to_update > 0) {      if (kenv->nb_ram_pages_to_update > 0) {
Line 643  int kqemu_cpu_exec(CPUState *env) Line 762  int kqemu_cpu_exec(CPUState *env)
     }      }
 #endif  #endif
   
   #if KQEMU_VERSION >= 0x010300
       if (kenv->nb_modified_ram_pages > 0) {
           for(i = 0; i < kenv->nb_modified_ram_pages; i++) {
               unsigned long addr;
               addr = modified_ram_pages[i];
               tb_invalidate_phys_page_range(addr, addr + TARGET_PAGE_SIZE, 0);
           }
       }
   #endif
   
     /* restore the hidden flags */      /* restore the hidden flags */
     {      {
         unsigned int new_hflags;          unsigned int new_hflags;
Line 679  int kqemu_cpu_exec(CPUState *env) Line 808  int kqemu_cpu_exec(CPUState *env)
            ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |             ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |
             new_hflags;              new_hflags;
     }      }
       /* update FPU flags */
       env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |
           ((env->cr[0] << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));
       if (env->cr[4] & CR4_OSFXSR_MASK)
           env->hflags |= HF_OSFXSR_MASK;
       else
           env->hflags &= ~HF_OSFXSR_MASK;
           
 #ifdef DEBUG  #ifdef DEBUG
     if (loglevel & CPU_LOG_INT) {      if (loglevel & CPU_LOG_INT) {
         fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);          fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
Line 694  int kqemu_cpu_exec(CPUState *env) Line 830  int kqemu_cpu_exec(CPUState *env)
         env->error_code = 0;          env->error_code = 0;
         env->exception_is_int = 1;          env->exception_is_int = 1;
         env->exception_next_eip = kenv->next_eip;          env->exception_next_eip = kenv->next_eip;
   #ifdef CONFIG_PROFILER
           kqemu_ret_int_count++;
   #endif
 #ifdef DEBUG  #ifdef DEBUG
         if (loglevel & CPU_LOG_INT) {          if (loglevel & CPU_LOG_INT) {
             fprintf(logfile, "kqemu: interrupt v=%02x:\n",               fprintf(logfile, "kqemu: interrupt v=%02x:\n", 
Line 707  int kqemu_cpu_exec(CPUState *env) Line 846  int kqemu_cpu_exec(CPUState *env)
         env->error_code = kenv->error_code;          env->error_code = kenv->error_code;
         env->exception_is_int = 0;          env->exception_is_int = 0;
         env->exception_next_eip = 0;          env->exception_next_eip = 0;
   #ifdef CONFIG_PROFILER
           kqemu_ret_excp_count++;
   #endif
 #ifdef DEBUG  #ifdef DEBUG
         if (loglevel & CPU_LOG_INT) {          if (loglevel & CPU_LOG_INT) {
             fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n",              fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n",
Line 716  int kqemu_cpu_exec(CPUState *env) Line 858  int kqemu_cpu_exec(CPUState *env)
 #endif  #endif
         return 1;          return 1;
     } else if (ret == KQEMU_RET_INTR) {      } else if (ret == KQEMU_RET_INTR) {
   #ifdef CONFIG_PROFILER
           kqemu_ret_intr_count++;
   #endif
 #ifdef DEBUG  #ifdef DEBUG
         if (loglevel & CPU_LOG_INT) {          if (loglevel & CPU_LOG_INT) {
             cpu_dump_state(env, logfile, fprintf, 0);              cpu_dump_state(env, logfile, fprintf, 0);
Line 723  int kqemu_cpu_exec(CPUState *env) Line 868  int kqemu_cpu_exec(CPUState *env)
 #endif  #endif
         return 0;          return 0;
     } else if (ret == KQEMU_RET_SOFTMMU) {       } else if (ret == KQEMU_RET_SOFTMMU) { 
 #ifdef PROFILE  #ifdef CONFIG_PROFILER
         kqemu_record_pc(env->eip + env->segs[R_CS].base);          {
               unsigned long pc = env->eip + env->segs[R_CS].base;
               kqemu_record_pc(pc);
           }
 #endif  #endif
 #ifdef DEBUG  #ifdef DEBUG
         if (loglevel & CPU_LOG_INT) {          if (loglevel & CPU_LOG_INT) {

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


unix.superglobalmegacorp.com