dirty ram page handling fixes


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1559 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/exec.c b/exec.c
index c75c23e..3466c9d 100644
--- a/exec.c
+++ b/exec.c
@@ -1492,12 +1492,12 @@
     tlb_protect_code1(&env->tlb_write[0][i], vaddr);
     tlb_protect_code1(&env->tlb_write[1][i], vaddr);
 
-    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] &= ~CODE_DIRTY_FLAG;
 #ifdef USE_KQEMU
     if (env->kqemu_enabled) {
         kqemu_set_notdirty(env, ram_addr);
     }
 #endif
+    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] &= ~CODE_DIRTY_FLAG;
     
 #if !defined(CONFIG_SOFTMMU)
     /* NOTE: as we generated the code for this page, it is already at
@@ -1541,19 +1541,23 @@
     length = end - start;
     if (length == 0)
         return;
-    mask = ~dirty_flags;
-    p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
     len = length >> TARGET_PAGE_BITS;
-    for(i = 0; i < len; i++)
-        p[i] &= mask;
-
     env = cpu_single_env;
 #ifdef USE_KQEMU
     if (env->kqemu_enabled) {
-        for(i = 0; i < len; i++)
-            kqemu_set_notdirty(env, (unsigned long)i << TARGET_PAGE_BITS);
+        ram_addr_t addr;
+        addr = start;
+        for(i = 0; i < len; i++) {
+            kqemu_set_notdirty(env, addr);
+            addr += TARGET_PAGE_SIZE;
+        }
     }
 #endif
+    mask = ~dirty_flags;
+    p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
+    for(i = 0; i < len; i++)
+        p[i] &= mask;
+
     /* we modify the TLB cache so that the dirty bit will be set again
        when accessing the range */
     start1 = start + (unsigned long)phys_ram_base;
@@ -1633,8 +1637,6 @@
     CPUState *env = cpu_single_env;
     int i;
 
-    phys_ram_dirty[(addr - (unsigned long)phys_ram_base) >> TARGET_PAGE_BITS] = 0xff;
-
     addr &= TARGET_PAGE_MASK;
     i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     tlb_set_dirty1(&env->tlb_write[0][i], addr);
@@ -2005,8 +2007,11 @@
 #endif
     }
     stb_p((uint8_t *)(long)addr, val);
-    /* we set the page as dirty only if the code has been flushed */
-    if (dirty_flags & CODE_DIRTY_FLAG)
+    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
+       flushed */
+    if (dirty_flags == 0xff)
         tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
 }
 
@@ -2023,8 +2028,11 @@
 #endif
     }
     stw_p((uint8_t *)(long)addr, val);
-    /* we set the page as dirty only if the code has been flushed */
-    if (dirty_flags & CODE_DIRTY_FLAG)
+    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
+       flushed */
+    if (dirty_flags == 0xff)
         tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
 }
 
@@ -2041,8 +2049,11 @@
 #endif
     }
     stl_p((uint8_t *)(long)addr, val);
-    /* we set the page as dirty only if the code has been flushed */
-    if (dirty_flags & CODE_DIRTY_FLAG)
+    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
+       flushed */
+    if (dirty_flags == 0xff)
         tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
 }
 
@@ -2207,7 +2218,8 @@
                     /* invalidate code */
                     tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
                     /* set dirty bit */
-                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] = 0xff;
+                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |= 
+                        (0xff & ~CODE_DIRTY_FLAG);
                 }
             }
         } else {
@@ -2327,7 +2339,8 @@
             /* invalidate code */
             tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
             /* set dirty bit */
-            phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] = 0xff;
+            phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
+                (0xff & ~CODE_DIRTY_FLAG);
         }
     }
 }