Diff for /qemu/exec.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2018/04/24 16:38:36 version 1.1.1.3, 2018/04/24 16:40:47
Line 34 Line 34
   
 #include "cpu.h"  #include "cpu.h"
 #include "exec-all.h"  #include "exec-all.h"
   #if defined(CONFIG_USER_ONLY)
   #include <qemu.h>
   #endif
   
 //#define DEBUG_TB_INVALIDATE  //#define DEBUG_TB_INVALIDATE
 //#define DEBUG_FLUSH  //#define DEBUG_FLUSH
Line 43 Line 46
 //#define DEBUG_TB_CHECK   //#define DEBUG_TB_CHECK 
 //#define DEBUG_TLB_CHECK   //#define DEBUG_TLB_CHECK 
   
   #if !defined(CONFIG_USER_ONLY)
   /* TB consistency checks only implemented for usermode emulation.  */
   #undef DEBUG_TB_CHECK
   #endif
   
 /* threshold to flush the translated code buffer */  /* threshold to flush the translated code buffer */
 #define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)  #define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
   
Line 201  static inline PageDesc *page_find(unsign Line 209  static inline PageDesc *page_find(unsign
 static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)  static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
 {  {
     void **lp, **p;      void **lp, **p;
       PhysPageDesc *pd;
   
     p = (void **)l1_phys_map;      p = (void **)l1_phys_map;
 #if TARGET_PHYS_ADDR_SPACE_BITS > 32  #if TARGET_PHYS_ADDR_SPACE_BITS > 32
Line 220  static PhysPageDesc *phys_page_find_allo Line 229  static PhysPageDesc *phys_page_find_allo
     }      }
 #endif  #endif
     lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));      lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
     p = *lp;      pd = *lp;
     if (!p) {      if (!pd) {
           int i;
         /* allocate if not found */          /* allocate if not found */
         if (!alloc)          if (!alloc)
             return NULL;              return NULL;
         p = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);          pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
         memset(p, 0, sizeof(PhysPageDesc) * L2_SIZE);          *lp = pd;
         *lp = p;          for (i = 0; i < L2_SIZE; i++)
             pd[i].phys_offset = IO_MEM_UNASSIGNED;
     }      }
     return ((PhysPageDesc *)p) + (index & (L2_SIZE - 1));      return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
 }  }
   
 static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)  static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
Line 324  static void tb_invalidate_check(unsigned Line 335  static void tb_invalidate_check(unsigned
     TranslationBlock *tb;      TranslationBlock *tb;
     int i;      int i;
     address &= TARGET_PAGE_MASK;      address &= TARGET_PAGE_MASK;
     for(i = 0;i < CODE_GEN_HASH_SIZE; i++) {      for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
         for(tb = tb_hash[i]; tb != NULL; tb = tb->hash_next) {          for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
             if (!(address + TARGET_PAGE_SIZE <= tb->pc ||              if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
                   address >= tb->pc + tb->size)) {                    address >= tb->pc + tb->size)) {
                 printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",                  printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",
                        address, tb->pc, tb->size);                         address, (long)tb->pc, tb->size);
             }              }
         }          }
     }      }
Line 341  static void tb_page_check(void) Line 352  static void tb_page_check(void)
     TranslationBlock *tb;      TranslationBlock *tb;
     int i, flags1, flags2;      int i, flags1, flags2;
           
     for(i = 0;i < CODE_GEN_HASH_SIZE; i++) {      for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
         for(tb = tb_hash[i]; tb != NULL; tb = tb->hash_next) {          for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
             flags1 = page_get_flags(tb->pc);              flags1 = page_get_flags(tb->pc);
             flags2 = page_get_flags(tb->pc + tb->size - 1);              flags2 = page_get_flags(tb->pc + tb->size - 1);
             if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {              if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
                 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",                  printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
                        tb->pc, tb->size, flags1, flags2);                         (long)tb->pc, tb->size, flags1, flags2);
             }              }
         }          }
     }      }
Line 810  static void tb_invalidate_phys_page(targ Line 821  static void tb_invalidate_phys_page(targ
   
 /* add the tb in the target page and protect it if necessary */  /* add the tb in the target page and protect it if necessary */
 static inline void tb_alloc_page(TranslationBlock *tb,   static inline void tb_alloc_page(TranslationBlock *tb, 
                                  unsigned int n, unsigned int page_addr)                                   unsigned int n, target_ulong page_addr)
 {  {
     PageDesc *p;      PageDesc *p;
     TranslationBlock *last_first_tb;      TranslationBlock *last_first_tb;
Line 826  static inline void tb_alloc_page(Transla Line 837  static inline void tb_alloc_page(Transla
   
 #if defined(CONFIG_USER_ONLY)  #if defined(CONFIG_USER_ONLY)
     if (p->flags & PAGE_WRITE) {      if (p->flags & PAGE_WRITE) {
         unsigned long host_start, host_end, addr;          target_ulong addr;
           PageDesc *p2;
         int prot;          int prot;
   
         /* force the host page as non writable (writes will have a          /* force the host page as non writable (writes will have a
            page fault + mprotect overhead) */             page fault + mprotect overhead) */
         host_start = page_addr & qemu_host_page_mask;          page_addr &= qemu_host_page_mask;
         host_end = host_start + qemu_host_page_size;  
         prot = 0;          prot = 0;
         for(addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE)          for(addr = page_addr; addr < page_addr + qemu_host_page_size;
             prot |= page_get_flags(addr);              addr += TARGET_PAGE_SIZE) {
         mprotect((void *)host_start, qemu_host_page_size,   
               p2 = page_find (addr >> TARGET_PAGE_BITS);
               if (!p2)
                   continue;
               prot |= p2->flags;
               p2->flags &= ~PAGE_WRITE;
               page_get_flags(addr);
             }
           mprotect(g2h(page_addr), qemu_host_page_size, 
                  (prot & PAGE_BITS) & ~PAGE_WRITE);                   (prot & PAGE_BITS) & ~PAGE_WRITE);
 #ifdef DEBUG_TB_INVALIDATE  #ifdef DEBUG_TB_INVALIDATE
         printf("protecting code page: 0x%08lx\n",           printf("protecting code page: 0x%08lx\n", 
                host_start);                 page_addr);
 #endif  #endif
         p->flags &= ~PAGE_WRITE;  
     }      }
 #else  #else
     /* if some code is already present, then the pages are already      /* if some code is already present, then the pages are already
Line 993  static void tb_reset_jump_recursive(Tran Line 1011  static void tb_reset_jump_recursive(Tran
 #if defined(TARGET_HAS_ICE)  #if defined(TARGET_HAS_ICE)
 static void breakpoint_invalidate(CPUState *env, target_ulong pc)  static void breakpoint_invalidate(CPUState *env, target_ulong pc)
 {  {
     target_ulong phys_addr;      target_ulong addr, pd;
       ram_addr_t ram_addr;
       PhysPageDesc *p;
   
     phys_addr = cpu_get_phys_page_debug(env, pc);      addr = cpu_get_phys_page_debug(env, pc);
     tb_invalidate_phys_page_range(phys_addr, phys_addr + 1, 0);      p = phys_page_find(addr >> TARGET_PAGE_BITS);
       if (!p) {
           pd = IO_MEM_UNASSIGNED;
       } else {
           pd = p->phys_offset;
       }
       ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
       tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
 }  }
 #endif  #endif
   
Line 1546  int tlb_set_page_exec(CPUState *env, tar Line 1573  int tlb_set_page_exec(CPUState *env, tar
   
 /* called from signal handler: invalidate the code and unprotect the  /* called from signal handler: invalidate the code and unprotect the
    page. Return TRUE if the fault was succesfully handled. */     page. Return TRUE if the fault was succesfully handled. */
 int page_unprotect(unsigned long addr, unsigned long pc, void *puc)  int page_unprotect(target_ulong addr, unsigned long pc, void *puc)
 {  {
 #if !defined(CONFIG_SOFTMMU)  #if !defined(CONFIG_SOFTMMU)
     VirtPageDesc *vp;      VirtPageDesc *vp;
Line 1645  void page_dump(FILE *f) Line 1672  void page_dump(FILE *f)
     }      }
 }  }
   
 int page_get_flags(unsigned long address)  int page_get_flags(target_ulong address)
 {  {
     PageDesc *p;      PageDesc *p;
   
Line 1658  int page_get_flags(unsigned long address Line 1685  int page_get_flags(unsigned long address
 /* modify the flags of a page and invalidate the code if  /* modify the flags of a page and invalidate the code if
    necessary. The flag PAGE_WRITE_ORG is positionned automatically     necessary. The flag PAGE_WRITE_ORG is positionned automatically
    depending on PAGE_WRITE */     depending on PAGE_WRITE */
 void page_set_flags(unsigned long start, unsigned long end, int flags)  void page_set_flags(target_ulong start, target_ulong end, int flags)
 {  {
     PageDesc *p;      PageDesc *p;
     unsigned long addr;      target_ulong addr;
   
     start = start & TARGET_PAGE_MASK;      start = start & TARGET_PAGE_MASK;
     end = TARGET_PAGE_ALIGN(end);      end = TARGET_PAGE_ALIGN(end);
Line 1684  void page_set_flags(unsigned long start, Line 1711  void page_set_flags(unsigned long start,
   
 /* called from signal handler: invalidate the code and unprotect the  /* called from signal handler: invalidate the code and unprotect the
    page. Return TRUE if the fault was succesfully handled. */     page. Return TRUE if the fault was succesfully handled. */
 int page_unprotect(unsigned long address, unsigned long pc, void *puc)  int page_unprotect(target_ulong address, unsigned long pc, void *puc)
 {  {
     unsigned int page_index, prot, pindex;      unsigned int page_index, prot, pindex;
     PageDesc *p, *p1;      PageDesc *p, *p1;
     unsigned long host_start, host_end, addr;      target_ulong host_start, host_end, addr;
   
     host_start = address & qemu_host_page_mask;      host_start = address & qemu_host_page_mask;
     page_index = host_start >> TARGET_PAGE_BITS;      page_index = host_start >> TARGET_PAGE_BITS;
Line 1707  int page_unprotect(unsigned long address Line 1734  int page_unprotect(unsigned long address
     if (prot & PAGE_WRITE_ORG) {      if (prot & PAGE_WRITE_ORG) {
         pindex = (address - host_start) >> TARGET_PAGE_BITS;          pindex = (address - host_start) >> TARGET_PAGE_BITS;
         if (!(p1[pindex].flags & PAGE_WRITE)) {          if (!(p1[pindex].flags & PAGE_WRITE)) {
             mprotect((void *)host_start, qemu_host_page_size,               mprotect((void *)g2h(host_start), qemu_host_page_size, 
                      (prot & PAGE_BITS) | PAGE_WRITE);                       (prot & PAGE_BITS) | PAGE_WRITE);
             p1[pindex].flags |= PAGE_WRITE;              p1[pindex].flags |= PAGE_WRITE;
             /* and since the content will be modified, we must invalidate              /* and since the content will be modified, we must invalidate
Line 1723  int page_unprotect(unsigned long address Line 1750  int page_unprotect(unsigned long address
 }  }
   
 /* call this function when system calls directly modify a memory area */  /* call this function when system calls directly modify a memory area */
 void page_unprotect_range(uint8_t *data, unsigned long data_size)  /* ??? This should be redundant now we have lock_user.  */
   void page_unprotect_range(target_ulong data, target_ulong data_size)
 {  {
     unsigned long start, end, addr;      target_ulong start, end, addr;
   
     start = (unsigned long)data;      start = data;
     end = start + data_size;      end = start + data_size;
     start &= TARGET_PAGE_MASK;      start &= TARGET_PAGE_MASK;
     end = TARGET_PAGE_ALIGN(end);      end = TARGET_PAGE_ALIGN(end);
Line 1796  static void notdirty_mem_writeb(void *op Line 1824  static void notdirty_mem_writeb(void *op
 #endif  #endif
     }      }
     stb_p((uint8_t *)(long)addr, val);      stb_p((uint8_t *)(long)addr, val);
   #ifdef USE_KQEMU
       if (cpu_single_env->kqemu_enabled &&
           (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
           kqemu_modify_page(cpu_single_env, ram_addr);
   #endif
     dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);      dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
     phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;      phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
     /* we remove the notdirty callback only if the code has been      /* we remove the notdirty callback only if the code has been
Line 1817  static void notdirty_mem_writew(void *op Line 1850  static void notdirty_mem_writew(void *op
 #endif  #endif
     }      }
     stw_p((uint8_t *)(long)addr, val);      stw_p((uint8_t *)(long)addr, val);
   #ifdef USE_KQEMU
       if (cpu_single_env->kqemu_enabled &&
           (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
           kqemu_modify_page(cpu_single_env, ram_addr);
   #endif
     dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);      dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
     phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;      phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
     /* we remove the notdirty callback only if the code has been      /* we remove the notdirty callback only if the code has been
Line 1838  static void notdirty_mem_writel(void *op Line 1876  static void notdirty_mem_writel(void *op
 #endif  #endif
     }      }
     stl_p((uint8_t *)(long)addr, val);      stl_p((uint8_t *)(long)addr, val);
   #ifdef USE_KQEMU
       if (cpu_single_env->kqemu_enabled &&
           (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
           kqemu_modify_page(cpu_single_env, ram_addr);
   #endif
     dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);      dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
     phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;      phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
     /* we remove the notdirty callback only if the code has been      /* we remove the notdirty callback only if the code has been
Line 1917  void cpu_physical_memory_rw(target_phys_ Line 1960  void cpu_physical_memory_rw(target_phys_
 {  {
     int l, flags;      int l, flags;
     target_ulong page;      target_ulong page;
       void * p;
   
     while (len > 0) {      while (len > 0) {
         page = addr & TARGET_PAGE_MASK;          page = addr & TARGET_PAGE_MASK;
Line 1929  void cpu_physical_memory_rw(target_phys_ Line 1973  void cpu_physical_memory_rw(target_phys_
         if (is_write) {          if (is_write) {
             if (!(flags & PAGE_WRITE))              if (!(flags & PAGE_WRITE))
                 return;                  return;
             memcpy((uint8_t *)addr, buf, len);              p = lock_user(addr, len, 0);
               memcpy(p, buf, len);
               unlock_user(p, addr, len);
         } else {          } else {
             if (!(flags & PAGE_READ))              if (!(flags & PAGE_READ))
                 return;                  return;
             memcpy(buf, (uint8_t *)addr, len);              p = lock_user(addr, len, 1);
               memcpy(buf, p, len);
               unlock_user(p, addr, 0);
         }          }
         len -= l;          len -= l;
         buf += l;          buf += l;
Line 2032  void cpu_physical_memory_rw(target_phys_ Line 2080  void cpu_physical_memory_rw(target_phys_
     }      }
 }  }
   
   /* used for ROM loading : can write in RAM and ROM */
   void cpu_physical_memory_write_rom(target_phys_addr_t addr, 
                                      const uint8_t *buf, int len)
   {
       int l;
       uint8_t *ptr;
       target_phys_addr_t page;
       unsigned long pd;
       PhysPageDesc *p;
       
       while (len > 0) {
           page = addr & TARGET_PAGE_MASK;
           l = (page + TARGET_PAGE_SIZE) - addr;
           if (l > len)
               l = len;
           p = phys_page_find(page >> TARGET_PAGE_BITS);
           if (!p) {
               pd = IO_MEM_UNASSIGNED;
           } else {
               pd = p->phys_offset;
           }
           
           if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
               (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM) {
               /* do nothing */
           } else {
               unsigned long addr1;
               addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
               /* ROM/RAM case */
               ptr = phys_ram_base + addr1;
               memcpy(ptr, buf, l);
           }
           len -= l;
           buf += l;
           addr += l;
       }
   }
   
   
 /* warning: addr must be aligned */  /* warning: addr must be aligned */
 uint32_t ldl_phys(target_phys_addr_t addr)  uint32_t ldl_phys(target_phys_addr_t addr)
 {  {

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


unix.superglobalmegacorp.com