Commit f23db1692be35affcd4dc00a9c44caebb8831d4f
1 parent
3f20e1dd
dirty ram page handling fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1559 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
31 additions
and
18 deletions
exec.c
| @@ -1492,12 +1492,12 @@ static void tlb_protect_code(CPUState *env, ram_addr_t ram_addr, | @@ -1492,12 +1492,12 @@ static void tlb_protect_code(CPUState *env, ram_addr_t ram_addr, | ||
| 1492 | tlb_protect_code1(&env->tlb_write[0][i], vaddr); | 1492 | tlb_protect_code1(&env->tlb_write[0][i], vaddr); |
| 1493 | tlb_protect_code1(&env->tlb_write[1][i], vaddr); | 1493 | tlb_protect_code1(&env->tlb_write[1][i], vaddr); |
| 1494 | 1494 | ||
| 1495 | - phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] &= ~CODE_DIRTY_FLAG; | ||
| 1496 | #ifdef USE_KQEMU | 1495 | #ifdef USE_KQEMU |
| 1497 | if (env->kqemu_enabled) { | 1496 | if (env->kqemu_enabled) { |
| 1498 | kqemu_set_notdirty(env, ram_addr); | 1497 | kqemu_set_notdirty(env, ram_addr); |
| 1499 | } | 1498 | } |
| 1500 | #endif | 1499 | #endif |
| 1500 | + phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] &= ~CODE_DIRTY_FLAG; | ||
| 1501 | 1501 | ||
| 1502 | #if !defined(CONFIG_SOFTMMU) | 1502 | #if !defined(CONFIG_SOFTMMU) |
| 1503 | /* NOTE: as we generated the code for this page, it is already at | 1503 | /* NOTE: as we generated the code for this page, it is already at |
| @@ -1541,19 +1541,23 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, | @@ -1541,19 +1541,23 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, | ||
| 1541 | length = end - start; | 1541 | length = end - start; |
| 1542 | if (length == 0) | 1542 | if (length == 0) |
| 1543 | return; | 1543 | return; |
| 1544 | - mask = ~dirty_flags; | ||
| 1545 | - p = phys_ram_dirty + (start >> TARGET_PAGE_BITS); | ||
| 1546 | len = length >> TARGET_PAGE_BITS; | 1544 | len = length >> TARGET_PAGE_BITS; |
| 1547 | - for(i = 0; i < len; i++) | ||
| 1548 | - p[i] &= mask; | ||
| 1549 | - | ||
| 1550 | env = cpu_single_env; | 1545 | env = cpu_single_env; |
| 1551 | #ifdef USE_KQEMU | 1546 | #ifdef USE_KQEMU |
| 1552 | if (env->kqemu_enabled) { | 1547 | if (env->kqemu_enabled) { |
| 1553 | - for(i = 0; i < len; i++) | ||
| 1554 | - kqemu_set_notdirty(env, (unsigned long)i << TARGET_PAGE_BITS); | 1548 | + ram_addr_t addr; |
| 1549 | + addr = start; | ||
| 1550 | + for(i = 0; i < len; i++) { | ||
| 1551 | + kqemu_set_notdirty(env, addr); | ||
| 1552 | + addr += TARGET_PAGE_SIZE; | ||
| 1553 | + } | ||
| 1555 | } | 1554 | } |
| 1556 | #endif | 1555 | #endif |
| 1556 | + mask = ~dirty_flags; | ||
| 1557 | + p = phys_ram_dirty + (start >> TARGET_PAGE_BITS); | ||
| 1558 | + for(i = 0; i < len; i++) | ||
| 1559 | + p[i] &= mask; | ||
| 1560 | + | ||
| 1557 | /* we modify the TLB cache so that the dirty bit will be set again | 1561 | /* we modify the TLB cache so that the dirty bit will be set again |
| 1558 | when accessing the range */ | 1562 | when accessing the range */ |
| 1559 | start1 = start + (unsigned long)phys_ram_base; | 1563 | start1 = start + (unsigned long)phys_ram_base; |
| @@ -1633,8 +1637,6 @@ static inline void tlb_set_dirty(unsigned long addr, target_ulong vaddr) | @@ -1633,8 +1637,6 @@ static inline void tlb_set_dirty(unsigned long addr, target_ulong vaddr) | ||
| 1633 | CPUState *env = cpu_single_env; | 1637 | CPUState *env = cpu_single_env; |
| 1634 | int i; | 1638 | int i; |
| 1635 | 1639 | ||
| 1636 | - phys_ram_dirty[(addr - (unsigned long)phys_ram_base) >> TARGET_PAGE_BITS] = 0xff; | ||
| 1637 | - | ||
| 1638 | addr &= TARGET_PAGE_MASK; | 1640 | addr &= TARGET_PAGE_MASK; |
| 1639 | i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); | 1641 | i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 1640 | tlb_set_dirty1(&env->tlb_write[0][i], addr); | 1642 | tlb_set_dirty1(&env->tlb_write[0][i], addr); |
| @@ -2005,8 +2007,11 @@ static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t | @@ -2005,8 +2007,11 @@ static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t | ||
| 2005 | #endif | 2007 | #endif |
| 2006 | } | 2008 | } |
| 2007 | stb_p((uint8_t *)(long)addr, val); | 2009 | stb_p((uint8_t *)(long)addr, val); |
| 2008 | - /* we set the page as dirty only if the code has been flushed */ | ||
| 2009 | - if (dirty_flags & CODE_DIRTY_FLAG) | 2010 | + dirty_flags |= (0xff & ~CODE_DIRTY_FLAG); |
| 2011 | + phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags; | ||
| 2012 | + /* we remove the notdirty callback only if the code has been | ||
| 2013 | + flushed */ | ||
| 2014 | + if (dirty_flags == 0xff) | ||
| 2010 | tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr); | 2015 | tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr); |
| 2011 | } | 2016 | } |
| 2012 | 2017 | ||
| @@ -2023,8 +2028,11 @@ static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t | @@ -2023,8 +2028,11 @@ static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t | ||
| 2023 | #endif | 2028 | #endif |
| 2024 | } | 2029 | } |
| 2025 | stw_p((uint8_t *)(long)addr, val); | 2030 | stw_p((uint8_t *)(long)addr, val); |
| 2026 | - /* we set the page as dirty only if the code has been flushed */ | ||
| 2027 | - if (dirty_flags & CODE_DIRTY_FLAG) | 2031 | + dirty_flags |= (0xff & ~CODE_DIRTY_FLAG); |
| 2032 | + phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags; | ||
| 2033 | + /* we remove the notdirty callback only if the code has been | ||
| 2034 | + flushed */ | ||
| 2035 | + if (dirty_flags == 0xff) | ||
| 2028 | tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr); | 2036 | tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr); |
| 2029 | } | 2037 | } |
| 2030 | 2038 | ||
| @@ -2041,8 +2049,11 @@ static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t | @@ -2041,8 +2049,11 @@ static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t | ||
| 2041 | #endif | 2049 | #endif |
| 2042 | } | 2050 | } |
| 2043 | stl_p((uint8_t *)(long)addr, val); | 2051 | stl_p((uint8_t *)(long)addr, val); |
| 2044 | - /* we set the page as dirty only if the code has been flushed */ | ||
| 2045 | - if (dirty_flags & CODE_DIRTY_FLAG) | 2052 | + dirty_flags |= (0xff & ~CODE_DIRTY_FLAG); |
| 2053 | + phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags; | ||
| 2054 | + /* we remove the notdirty callback only if the code has been | ||
| 2055 | + flushed */ | ||
| 2056 | + if (dirty_flags == 0xff) | ||
| 2046 | tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr); | 2057 | tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr); |
| 2047 | } | 2058 | } |
| 2048 | 2059 | ||
| @@ -2207,7 +2218,8 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, | @@ -2207,7 +2218,8 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, | ||
| 2207 | /* invalidate code */ | 2218 | /* invalidate code */ |
| 2208 | tb_invalidate_phys_page_range(addr1, addr1 + l, 0); | 2219 | tb_invalidate_phys_page_range(addr1, addr1 + l, 0); |
| 2209 | /* set dirty bit */ | 2220 | /* set dirty bit */ |
| 2210 | - phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] = 0xff; | 2221 | + phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |= |
| 2222 | + (0xff & ~CODE_DIRTY_FLAG); | ||
| 2211 | } | 2223 | } |
| 2212 | } | 2224 | } |
| 2213 | } else { | 2225 | } else { |
| @@ -2327,7 +2339,8 @@ void stl_phys(target_phys_addr_t addr, uint32_t val) | @@ -2327,7 +2339,8 @@ void stl_phys(target_phys_addr_t addr, uint32_t val) | ||
| 2327 | /* invalidate code */ | 2339 | /* invalidate code */ |
| 2328 | tb_invalidate_phys_page_range(addr1, addr1 + 4, 0); | 2340 | tb_invalidate_phys_page_range(addr1, addr1 + 4, 0); |
| 2329 | /* set dirty bit */ | 2341 | /* set dirty bit */ |
| 2330 | - phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] = 0xff; | 2342 | + phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |= |
| 2343 | + (0xff & ~CODE_DIRTY_FLAG); | ||
| 2331 | } | 2344 | } |
| 2332 | } | 2345 | } |
| 2333 | } | 2346 | } |