Update Arm docs.
[qemu] / exec.c
diff --git a/exec.c b/exec.c
index 3dbd3eb..e4e68d9 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -672,12 +672,19 @@ void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
 #endif
             }
 #endif /* TARGET_HAS_PRECISE_SMC */
-            saved_tb = env->current_tb;
-            env->current_tb = NULL;
+            /* we need to do that to handle the case where a signal
+               occurs while doing tb_phys_invalidate() */
+            saved_tb = NULL;
+            if (env) {
+                saved_tb = env->current_tb;
+                env->current_tb = NULL;
+            }
             tb_phys_invalidate(tb, -1);
-            env->current_tb = saved_tb;
-            if (env->interrupt_request && env->current_tb)
-                cpu_interrupt(env, env->interrupt_request);
+            if (env) {
+                env->current_tb = saved_tb;
+                if (env->interrupt_request && env->current_tb)
+                    cpu_interrupt(env, env->interrupt_request);
+            }
         }
         tb = tb_next;
     }
@@ -1202,10 +1209,12 @@ void tlb_flush(CPUState *env, int flush_global)
     env->current_tb = NULL;
 
     for(i = 0; i < CPU_TLB_SIZE; i++) {
-        env->tlb_read[0][i].address = -1;
-        env->tlb_write[0][i].address = -1;
-        env->tlb_read[1][i].address = -1;
-        env->tlb_write[1][i].address = -1;
+        env->tlb_table[0][i].addr_read = -1;
+        env->tlb_table[0][i].addr_write = -1;
+        env->tlb_table[0][i].addr_code = -1;
+        env->tlb_table[1][i].addr_read = -1;
+        env->tlb_table[1][i].addr_write = -1;
+        env->tlb_table[1][i].addr_code = -1;
     }
 
     memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
@@ -1223,9 +1232,16 @@ void tlb_flush(CPUState *env, int flush_global)
 
 static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
 {
-    if (addr == (tlb_entry->address & 
-                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)))
-        tlb_entry->address = -1;
+    if (addr == (tlb_entry->addr_read & 
+                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
+        addr == (tlb_entry->addr_write & 
+                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
+        addr == (tlb_entry->addr_code & 
+                 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
+        tlb_entry->addr_read = -1;
+        tlb_entry->addr_write = -1;
+        tlb_entry->addr_code = -1;
+    }
 }
 
 void tlb_flush_page(CPUState *env, target_ulong addr)
@@ -1242,10 +1258,8 @@ void tlb_flush_page(CPUState *env, target_ulong addr)
 
     addr &= TARGET_PAGE_MASK;
     i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    tlb_flush_entry(&env->tlb_read[0][i], addr);
-    tlb_flush_entry(&env->tlb_write[0][i], addr);
-    tlb_flush_entry(&env->tlb_read[1][i], addr);
-    tlb_flush_entry(&env->tlb_write[1][i], addr);
+    tlb_flush_entry(&env->tlb_table[0][i], addr);
+    tlb_flush_entry(&env->tlb_table[1][i], addr);
 
     for(i = 0; i < TB_JMP_CACHE_SIZE; i++) {
         tb = env->tb_jmp_cache[i];
@@ -1288,10 +1302,10 @@ static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
                                          unsigned long start, unsigned long length)
 {
     unsigned long addr;
-    if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
-        addr = (tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend;
+    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
+        addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
         if ((addr - start) < length) {
-            tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
+            tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
         }
     }
 }
@@ -1333,9 +1347,9 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
     start1 = start + (unsigned long)phys_ram_base;
     for(env = first_cpu; env != NULL; env = env->next_cpu) {
         for(i = 0; i < CPU_TLB_SIZE; i++)
-            tlb_reset_dirty_range(&env->tlb_write[0][i], start1, length);
+            tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
         for(i = 0; i < CPU_TLB_SIZE; i++)
-            tlb_reset_dirty_range(&env->tlb_write[1][i], start1, length);
+            tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
     }
 
 #if !defined(CONFIG_SOFTMMU)
@@ -1371,11 +1385,11 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
 {
     ram_addr_t ram_addr;
 
-    if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
-        ram_addr = (tlb_entry->address & TARGET_PAGE_MASK) + 
+    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
+        ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + 
             tlb_entry->addend - (unsigned long)phys_ram_base;
         if (!cpu_physical_memory_is_dirty(ram_addr)) {
-            tlb_entry->address |= IO_MEM_NOTDIRTY;
+            tlb_entry->addr_write |= IO_MEM_NOTDIRTY;
         }
     }
 }
@@ -1385,19 +1399,19 @@ void cpu_tlb_update_dirty(CPUState *env)
 {
     int i;
     for(i = 0; i < CPU_TLB_SIZE; i++)
-        tlb_update_dirty(&env->tlb_write[0][i]);
+        tlb_update_dirty(&env->tlb_table[0][i]);
     for(i = 0; i < CPU_TLB_SIZE; i++)
-        tlb_update_dirty(&env->tlb_write[1][i]);
+        tlb_update_dirty(&env->tlb_table[1][i]);
 }
 
 static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, 
                                   unsigned long start)
 {
     unsigned long addr;
-    if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) {
-        addr = (tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend;
+    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) {
+        addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
         if (addr == start) {
-            tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_RAM;
+            tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_RAM;
         }
     }
 }
@@ -1411,17 +1425,17 @@ static inline void tlb_set_dirty(CPUState *env,
 
     addr &= TARGET_PAGE_MASK;
     i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    tlb_set_dirty1(&env->tlb_write[0][i], addr);
-    tlb_set_dirty1(&env->tlb_write[1][i], addr);
+    tlb_set_dirty1(&env->tlb_table[0][i], addr);
+    tlb_set_dirty1(&env->tlb_table[1][i], addr);
 }
 
 /* add a new TLB entry. At most one entry for a given virtual address
    is permitted. Return 0 if OK or 2 if the page could not be mapped
    (can only happen in non SOFTMMU mode for I/O pages or pages
    conflicting with the host address space). */
-int tlb_set_page(CPUState *env, target_ulong vaddr, 
-                 target_phys_addr_t paddr, int prot, 
-                 int is_user, int is_softmmu)
+int tlb_set_page_exec(CPUState *env, target_ulong vaddr, 
+                      target_phys_addr_t paddr, int prot, 
+                      int is_user, int is_softmmu)
 {
     PhysPageDesc *p;
     unsigned long pd;
@@ -1429,6 +1443,7 @@ int tlb_set_page(CPUState *env, target_ulong vaddr,
     target_ulong address;
     target_phys_addr_t addend;
     int ret;
+    CPUTLBEntry *te;
 
     p = phys_page_find(paddr >> TARGET_PAGE_BITS);
     if (!p) {
@@ -1438,7 +1453,7 @@ int tlb_set_page(CPUState *env, target_ulong vaddr,
     }
 #if defined(DEBUG_TLB)
     printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n",
-           vaddr, paddr, prot, is_user, is_softmmu, pd);
+           vaddr, (int)paddr, prot, is_user, is_softmmu, pd);
 #endif
 
     ret = 0;
@@ -1458,29 +1473,30 @@ int tlb_set_page(CPUState *env, target_ulong vaddr,
         
         index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
         addend -= vaddr;
+        te = &env->tlb_table[is_user][index];
+        te->addend = addend;
         if (prot & PAGE_READ) {
-            env->tlb_read[is_user][index].address = address;
-            env->tlb_read[is_user][index].addend = addend;
+            te->addr_read = address;
         } else {
-            env->tlb_read[is_user][index].address = -1;
-            env->tlb_read[is_user][index].addend = -1;
+            te->addr_read = -1;
+        }
+        if (prot & PAGE_EXEC) {
+            te->addr_code = address;
+        } else {
+            te->addr_code = -1;
         }
         if (prot & PAGE_WRITE) {
             if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) {
                 /* ROM: access is ignored (same as unassigned) */
-                env->tlb_write[is_user][index].address = vaddr | IO_MEM_ROM;
-                env->tlb_write[is_user][index].addend = addend;
+                te->addr_write = vaddr | IO_MEM_ROM;
             } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
                        !cpu_physical_memory_is_dirty(pd)) {
-                env->tlb_write[is_user][index].address = vaddr | IO_MEM_NOTDIRTY;
-                env->tlb_write[is_user][index].addend = addend;
+                te->addr_write = vaddr | IO_MEM_NOTDIRTY;
             } else {
-                env->tlb_write[is_user][index].address = address;
-                env->tlb_write[is_user][index].addend = addend;
+                te->addr_write = address;
             }
         } else {
-            env->tlb_write[is_user][index].address = -1;
-            env->tlb_write[is_user][index].addend = -1;
+            te->addr_write = -1;
         }
     }
 #if !defined(CONFIG_SOFTMMU)
@@ -1579,9 +1595,9 @@ void tlb_flush_page(CPUState *env, target_ulong addr)
 {
 }
 
-int tlb_set_page(CPUState *env, target_ulong vaddr, 
-                 target_phys_addr_t paddr, int prot, 
-                 int is_user, int is_softmmu)
+int tlb_set_page_exec(CPUState *env, target_ulong vaddr, 
+                      target_phys_addr_t paddr, int prot, 
+                      int is_user, int is_softmmu)
 {
     return 0;
 }
@@ -1780,6 +1796,11 @@ static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t
 #endif
     }
     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);
     phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
     /* we remove the notdirty callback only if the code has been
@@ -1801,6 +1822,11 @@ static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t
 #endif
     }
     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);
     phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
     /* we remove the notdirty callback only if the code has been
@@ -1822,6 +1848,11 @@ static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t
 #endif
     }
     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);
     phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
     /* we remove the notdirty callback only if the code has been
@@ -1868,14 +1899,14 @@ int cpu_register_io_memory(int io_index,
     int i;
 
     if (io_index <= 0) {
-        if (io_index >= IO_MEM_NB_ENTRIES)
+        if (io_mem_nb >= IO_MEM_NB_ENTRIES)
             return -1;
         io_index = io_mem_nb++;
     } else {
         if (io_index >= IO_MEM_NB_ENTRIES)
             return -1;
     }
-    
+
     for(i = 0;i < 3; i++) {
         io_mem_read[io_index][i] = mem_read[i];
         io_mem_write[io_index][i] = mem_write[i];
@@ -2045,6 +2076,41 @@ uint32_t ldl_phys(target_phys_addr_t addr)
     return val;
 }
 
+/* warning: addr must be aligned */
+uint64_t ldq_phys(target_phys_addr_t addr)
+{
+    int io_index;
+    uint8_t *ptr;
+    uint64_t val;
+    unsigned long pd;
+    PhysPageDesc *p;
+
+    p = phys_page_find(addr >> TARGET_PAGE_BITS);
+    if (!p) {
+        pd = IO_MEM_UNASSIGNED;
+    } else {
+        pd = p->phys_offset;
+    }
+        
+    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
+        /* I/O case */
+        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+#ifdef TARGET_WORDS_BIGENDIAN
+        val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
+        val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
+#else
+        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
+        val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
+#endif
+    } else {
+        /* RAM case */
+        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
+            (addr & ~TARGET_PAGE_MASK);
+        val = ldq_p(ptr);
+    }
+    return val;
+}
+
 /* XXX: optimize */
 uint32_t ldub_phys(target_phys_addr_t addr)
 {
@@ -2061,14 +2127,6 @@ uint32_t lduw_phys(target_phys_addr_t addr)
     return tswap16(val);
 }
 
-/* XXX: optimize */
-uint64_t ldq_phys(target_phys_addr_t addr)
-{
-    uint64_t val;
-    cpu_physical_memory_read(addr, (uint8_t *)&val, 8);
-    return tswap64(val);
-}
-
 /* warning: addr must be aligned. The ram page is not masked as dirty
    and the code inside is not invalidated. It is useful if the dirty
    bits are used to track modified PTEs */