Commit 1ccde1cb942f77958776578939bbcfc4c9bdf362

Authored by bellard
1 parent ad081323

added generic physical memory dirty bit support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@601 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-all.h
@@ -500,6 +500,7 @@ int cpu_inl(CPUState *env, int addr); @@ -500,6 +500,7 @@ int cpu_inl(CPUState *env, int addr);
500 extern int phys_ram_size; 500 extern int phys_ram_size;
501 extern int phys_ram_fd; 501 extern int phys_ram_fd;
502 extern uint8_t *phys_ram_base; 502 extern uint8_t *phys_ram_base;
  503 +extern uint8_t *phys_ram_dirty;
503 504
504 /* physical memory access */ 505 /* physical memory access */
505 #define IO_MEM_NB_ENTRIES 256 506 #define IO_MEM_NB_ENTRIES 256
@@ -509,9 +510,11 @@ extern uint8_t *phys_ram_base; @@ -509,9 +510,11 @@ extern uint8_t *phys_ram_base;
509 #define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */ 510 #define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */
510 #define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ 511 #define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */
511 #define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT) 512 #define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT)
512 -#define IO_MEM_CODE (3 << IO_MEM_SHIFT) 513 +#define IO_MEM_CODE (3 << IO_MEM_SHIFT) /* used internally, never use directly */
  514 +#define IO_MEM_NOTDIRTY (4 << IO_MEM_SHIFT) /* used internally, never use directly */
513 515
514 -typedef void CPUWriteMemoryFunc(uint32_t addr, uint32_t value); 516 +/* NOTE: vaddr is only used internally. Never use it except if you know what you do */
  517 +typedef void CPUWriteMemoryFunc(uint32_t addr, uint32_t value, uint32_t vaddr);
515 typedef uint32_t CPUReadMemoryFunc(uint32_t addr); 518 typedef uint32_t CPUReadMemoryFunc(uint32_t addr);
516 519
517 void cpu_register_physical_memory(unsigned long start_addr, unsigned long size, 520 void cpu_register_physical_memory(unsigned long start_addr, unsigned long size,
@@ -525,6 +528,19 @@ void cpu_physical_memory_rw(CPUState *env, uint8_t *buf, target_ulong addr, @@ -525,6 +528,19 @@ void cpu_physical_memory_rw(CPUState *env, uint8_t *buf, target_ulong addr,
525 int cpu_memory_rw_debug(CPUState *env, 528 int cpu_memory_rw_debug(CPUState *env,
526 uint8_t *buf, target_ulong addr, int len, int is_write); 529 uint8_t *buf, target_ulong addr, int len, int is_write);
527 530
  531 +/* read dirty bit (return 0 or 1) */
  532 +static inline int cpu_physical_memory_is_dirty(target_ulong addr)
  533 +{
  534 + return phys_ram_dirty[addr >> TARGET_PAGE_BITS];
  535 +}
  536 +
  537 +static inline void cpu_physical_memory_set_dirty(target_ulong addr)
  538 +{
  539 + phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 1;
  540 +}
  541 +
  542 +void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end);
  543 +
528 /* gdb stub API */ 544 /* gdb stub API */
529 extern int gdbstub_fd; 545 extern int gdbstub_fd;
530 CPUState *cpu_gdbstub_get_env(void *opaque); 546 CPUState *cpu_gdbstub_get_env(void *opaque);
exec-all.h
@@ -530,6 +530,8 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) @@ -530,6 +530,8 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
530 } 530 }
531 #else 531 #else
532 /* NOTE: this function can trigger an exception */ 532 /* NOTE: this function can trigger an exception */
  533 +/* NOTE2: the returned address is not exactly the physical address: it
  534 + is the offset relative to phys_ram_base */
533 /* XXX: i386 target specific */ 535 /* XXX: i386 target specific */
534 static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) 536 static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
535 { 537 {
@@ -59,6 +59,7 @@ uint8_t *code_gen_ptr; @@ -59,6 +59,7 @@ uint8_t *code_gen_ptr;
59 int phys_ram_size; 59 int phys_ram_size;
60 int phys_ram_fd; 60 int phys_ram_fd;
61 uint8_t *phys_ram_base; 61 uint8_t *phys_ram_base;
  62 +uint8_t *phys_ram_dirty;
62 63
63 typedef struct PageDesc { 64 typedef struct PageDesc {
64 /* offset in memory of the page + io_index in the low 12 bits */ 65 /* offset in memory of the page + io_index in the low 12 bits */
@@ -162,7 +163,7 @@ static inline PageDesc *page_find(unsigned int index) @@ -162,7 +163,7 @@ static inline PageDesc *page_find(unsigned int index)
162 #if !defined(CONFIG_USER_ONLY) 163 #if !defined(CONFIG_USER_ONLY)
163 static void tlb_protect_code(CPUState *env, uint32_t addr); 164 static void tlb_protect_code(CPUState *env, uint32_t addr);
164 static void tlb_unprotect_code(CPUState *env, uint32_t addr); 165 static void tlb_unprotect_code(CPUState *env, uint32_t addr);
165 -static void tlb_unprotect_code_phys(CPUState *env, uint32_t phys_addr); 166 +static void tlb_unprotect_code_phys(CPUState *env, uint32_t phys_addr, target_ulong vaddr);
166 167
167 static inline VirtPageDesc *virt_page_find_alloc(unsigned int index) 168 static inline VirtPageDesc *virt_page_find_alloc(unsigned int index)
168 { 169 {
@@ -528,8 +529,11 @@ static void build_page_bitmap(PageDesc *p) @@ -528,8 +529,11 @@ static void build_page_bitmap(PageDesc *p)
528 529
529 /* invalidate all TBs which intersect with the target physical page 530 /* invalidate all TBs which intersect with the target physical page
530 starting in range [start;end[. NOTE: start and end must refer to 531 starting in range [start;end[. NOTE: start and end must refer to
531 - the same physical page */  
532 -static void tb_invalidate_phys_page_range(target_ulong start, target_ulong end) 532 + the same physical page. 'vaddr' is a virtual address referencing
  533 + the physical page of code. It is only used an a hint if there is no
  534 + code left. */
  535 +static void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
  536 + target_ulong vaddr)
533 { 537 {
534 int n; 538 int n;
535 PageDesc *p; 539 PageDesc *p;
@@ -571,13 +575,13 @@ static void tb_invalidate_phys_page_range(target_ulong start, target_ulong end) @@ -571,13 +575,13 @@ static void tb_invalidate_phys_page_range(target_ulong start, target_ulong end)
571 /* if no code remaining, no need to continue to use slow writes */ 575 /* if no code remaining, no need to continue to use slow writes */
572 if (!p->first_tb) { 576 if (!p->first_tb) {
573 invalidate_page_bitmap(p); 577 invalidate_page_bitmap(p);
574 - tlb_unprotect_code_phys(cpu_single_env, start); 578 + tlb_unprotect_code_phys(cpu_single_env, start, vaddr);
575 } 579 }
576 #endif 580 #endif
577 } 581 }
578 582
579 /* len must be <= 8 and start must be a multiple of len */ 583 /* len must be <= 8 and start must be a multiple of len */
580 -static inline void tb_invalidate_phys_page_fast(target_ulong start, int len) 584 +static inline void tb_invalidate_phys_page_fast(target_ulong start, int len, target_ulong vaddr)
581 { 585 {
582 PageDesc *p; 586 PageDesc *p;
583 int offset, b; 587 int offset, b;
@@ -592,7 +596,7 @@ static inline void tb_invalidate_phys_page_fast(target_ulong start, int len) @@ -592,7 +596,7 @@ static inline void tb_invalidate_phys_page_fast(target_ulong start, int len)
592 goto do_invalidate; 596 goto do_invalidate;
593 } else { 597 } else {
594 do_invalidate: 598 do_invalidate:
595 - tb_invalidate_phys_page_range(start, start + len); 599 + tb_invalidate_phys_page_range(start, start + len, vaddr);
596 } 600 }
597 } 601 }
598 602
@@ -1088,8 +1092,7 @@ static inline void tlb_protect_code1(CPUTLBEntry *tlb_entry, uint32_t addr) @@ -1088,8 +1092,7 @@ static inline void tlb_protect_code1(CPUTLBEntry *tlb_entry, uint32_t addr)
1088 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) && 1092 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) &&
1089 (tlb_entry->address & ~TARGET_PAGE_MASK) != IO_MEM_CODE && 1093 (tlb_entry->address & ~TARGET_PAGE_MASK) != IO_MEM_CODE &&
1090 (tlb_entry->address & ~TARGET_PAGE_MASK) != IO_MEM_ROM) { 1094 (tlb_entry->address & ~TARGET_PAGE_MASK) != IO_MEM_ROM) {
1091 - tlb_entry->address |= IO_MEM_CODE;  
1092 - tlb_entry->addend -= (unsigned long)phys_ram_base; 1095 + tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_CODE;
1093 } 1096 }
1094 } 1097 }
1095 1098
@@ -1116,8 +1119,7 @@ static inline void tlb_unprotect_code1(CPUTLBEntry *tlb_entry, uint32_t addr) @@ -1116,8 +1119,7 @@ static inline void tlb_unprotect_code1(CPUTLBEntry *tlb_entry, uint32_t addr)
1116 if (addr == (tlb_entry->address & 1119 if (addr == (tlb_entry->address &
1117 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) && 1120 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) &&
1118 (tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_CODE) { 1121 (tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_CODE) {
1119 - tlb_entry->address &= TARGET_PAGE_MASK;  
1120 - tlb_entry->addend += (unsigned long)phys_ram_base; 1122 + tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
1121 } 1123 }
1122 } 1124 }
1123 1125
@@ -1138,23 +1140,84 @@ static inline void tlb_unprotect_code2(CPUTLBEntry *tlb_entry, @@ -1138,23 +1140,84 @@ static inline void tlb_unprotect_code2(CPUTLBEntry *tlb_entry,
1138 { 1140 {
1139 if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_CODE && 1141 if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_CODE &&
1140 ((tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend) == phys_addr) { 1142 ((tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend) == phys_addr) {
1141 - tlb_entry->address &= TARGET_PAGE_MASK;  
1142 - tlb_entry->addend += (unsigned long)phys_ram_base; 1143 + tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
1143 } 1144 }
1144 } 1145 }
1145 1146
1146 /* update the TLB so that writes in physical page 'phys_addr' are no longer 1147 /* update the TLB so that writes in physical page 'phys_addr' are no longer
1147 tested self modifying code */ 1148 tested self modifying code */
1148 -/* XXX: find a way to improve it */  
1149 -static void tlb_unprotect_code_phys(CPUState *env, uint32_t phys_addr) 1149 +static void tlb_unprotect_code_phys(CPUState *env, uint32_t phys_addr, target_ulong vaddr)
1150 { 1150 {
1151 int i; 1151 int i;
1152 1152
1153 phys_addr &= TARGET_PAGE_MASK; 1153 phys_addr &= TARGET_PAGE_MASK;
  1154 + phys_addr += (long)phys_ram_base;
  1155 + i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  1156 + tlb_unprotect_code2(&env->tlb_write[0][i], phys_addr);
  1157 + tlb_unprotect_code2(&env->tlb_write[1][i], phys_addr);
  1158 +}
  1159 +
  1160 +static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
  1161 + unsigned long start, unsigned long length)
  1162 +{
  1163 + unsigned long addr;
  1164 + if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
  1165 + addr = (tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend;
  1166 + if ((addr - start) < length) {
  1167 + tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
  1168 + }
  1169 + }
  1170 +}
  1171 +
  1172 +void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end)
  1173 +{
  1174 + CPUState *env;
  1175 + target_ulong length;
  1176 + int i;
  1177 +
  1178 + start &= TARGET_PAGE_MASK;
  1179 + end = TARGET_PAGE_ALIGN(end);
  1180 +
  1181 + length = end - start;
  1182 + if (length == 0)
  1183 + return;
  1184 + memset(phys_ram_dirty + (start >> TARGET_PAGE_BITS), 0, length >> TARGET_PAGE_BITS);
  1185 +
  1186 + env = cpu_single_env;
  1187 + /* we modify the TLB cache so that the dirty bit will be set again
  1188 + when accessing the range */
  1189 + start += (unsigned long)phys_ram_base;
1154 for(i = 0; i < CPU_TLB_SIZE; i++) 1190 for(i = 0; i < CPU_TLB_SIZE; i++)
1155 - tlb_unprotect_code2(&env->tlb_write[0][i], phys_addr); 1191 + tlb_reset_dirty_range(&env->tlb_write[0][i], start, length);
1156 for(i = 0; i < CPU_TLB_SIZE; i++) 1192 for(i = 0; i < CPU_TLB_SIZE; i++)
1157 - tlb_unprotect_code2(&env->tlb_write[1][i], phys_addr); 1193 + tlb_reset_dirty_range(&env->tlb_write[1][i], start, length);
  1194 +}
  1195 +
  1196 +static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry,
  1197 + unsigned long start)
  1198 +{
  1199 + unsigned long addr;
  1200 + if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) {
  1201 + addr = (tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend;
  1202 + if (addr == start) {
  1203 + tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_RAM;
  1204 + }
  1205 + }
  1206 +}
  1207 +
  1208 +/* update the TLB corresponding to virtual page vaddr and phys addr
  1209 + addr so that it is no longer dirty */
  1210 +static inline void tlb_set_dirty(unsigned long addr, target_ulong vaddr)
  1211 +{
  1212 + CPUState *env = cpu_single_env;
  1213 + int i;
  1214 +
  1215 + phys_ram_dirty[(addr - (unsigned long)phys_ram_base) >> TARGET_PAGE_BITS] = 1;
  1216 +
  1217 + addr &= TARGET_PAGE_MASK;
  1218 + i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  1219 + tlb_set_dirty1(&env->tlb_write[0][i], addr);
  1220 + tlb_set_dirty1(&env->tlb_write[1][i], addr);
1158 } 1221 }
1159 1222
1160 /* add a new TLB entry. At most one entry for a given virtual 1223 /* add a new TLB entry. At most one entry for a given virtual
@@ -1210,12 +1273,16 @@ int tlb_set_page(CPUState *env, uint32_t vaddr, uint32_t paddr, int prot, @@ -1210,12 +1273,16 @@ int tlb_set_page(CPUState *env, uint32_t vaddr, uint32_t paddr, int prot,
1210 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) { 1273 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) {
1211 /* ROM: access is ignored (same as unassigned) */ 1274 /* ROM: access is ignored (same as unassigned) */
1212 env->tlb_write[is_user][index].address = vaddr | IO_MEM_ROM; 1275 env->tlb_write[is_user][index].address = vaddr | IO_MEM_ROM;
1213 - env->tlb_write[is_user][index].addend = addend - (unsigned long)phys_ram_base; 1276 + env->tlb_write[is_user][index].addend = addend;
1214 } else if (first_tb) { 1277 } else if (first_tb) {
1215 /* if code is present, we use a specific memory 1278 /* if code is present, we use a specific memory
1216 handler. It works only for physical memory access */ 1279 handler. It works only for physical memory access */
1217 env->tlb_write[is_user][index].address = vaddr | IO_MEM_CODE; 1280 env->tlb_write[is_user][index].address = vaddr | IO_MEM_CODE;
1218 - env->tlb_write[is_user][index].addend = addend - (unsigned long)phys_ram_base; 1281 + env->tlb_write[is_user][index].addend = addend;
  1282 + } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
  1283 + !cpu_physical_memory_is_dirty(pd)) {
  1284 + env->tlb_write[is_user][index].address = vaddr | IO_MEM_NOTDIRTY;
  1285 + env->tlb_write[is_user][index].addend = addend;
1219 } else { 1286 } else {
1220 env->tlb_write[is_user][index].address = address; 1287 env->tlb_write[is_user][index].address = address;
1221 env->tlb_write[is_user][index].addend = addend; 1288 env->tlb_write[is_user][index].addend = addend;
@@ -1446,6 +1513,10 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size) @@ -1446,6 +1513,10 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size)
1446 } 1513 }
1447 } 1514 }
1448 1515
  1516 +static inline void tlb_set_dirty(unsigned long addr, target_ulong vaddr)
  1517 +{
  1518 +}
  1519 +
1449 #endif /* defined(CONFIG_USER_ONLY) */ 1520 #endif /* defined(CONFIG_USER_ONLY) */
1450 1521
1451 /* register physical memory. 'size' must be a multiple of the target 1522 /* register physical memory. 'size' must be a multiple of the target
@@ -1471,7 +1542,7 @@ static uint32_t unassigned_mem_readb(uint32_t addr) @@ -1471,7 +1542,7 @@ static uint32_t unassigned_mem_readb(uint32_t addr)
1471 return 0; 1542 return 0;
1472 } 1543 }
1473 1544
1474 -static void unassigned_mem_writeb(uint32_t addr, uint32_t val) 1545 +static void unassigned_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
1475 { 1546 {
1476 } 1547 }
1477 1548
@@ -1490,28 +1561,40 @@ static CPUWriteMemoryFunc *unassigned_mem_write[3] = { @@ -1490,28 +1561,40 @@ static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
1490 /* self modifying code support in soft mmu mode : writing to a page 1561 /* self modifying code support in soft mmu mode : writing to a page
1491 containing code comes to these functions */ 1562 containing code comes to these functions */
1492 1563
1493 -static void code_mem_writeb(uint32_t addr, uint32_t val) 1564 +static void code_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
1494 { 1565 {
  1566 + unsigned long phys_addr;
  1567 +
  1568 + phys_addr = addr - (long)phys_ram_base;
1495 #if !defined(CONFIG_USER_ONLY) 1569 #if !defined(CONFIG_USER_ONLY)
1496 - tb_invalidate_phys_page_fast(addr, 1); 1570 + tb_invalidate_phys_page_fast(phys_addr, 1, vaddr);
1497 #endif 1571 #endif
1498 - stb_raw(phys_ram_base + addr, val); 1572 + stb_raw((uint8_t *)addr, val);
  1573 + phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 1;
1499 } 1574 }
1500 1575
1501 -static void code_mem_writew(uint32_t addr, uint32_t val) 1576 +static void code_mem_writew(uint32_t addr, uint32_t val, uint32_t vaddr)
1502 { 1577 {
  1578 + unsigned long phys_addr;
  1579 +
  1580 + phys_addr = addr - (long)phys_ram_base;
1503 #if !defined(CONFIG_USER_ONLY) 1581 #if !defined(CONFIG_USER_ONLY)
1504 - tb_invalidate_phys_page_fast(addr, 2); 1582 + tb_invalidate_phys_page_fast(phys_addr, 2, vaddr);
1505 #endif 1583 #endif
1506 - stw_raw(phys_ram_base + addr, val); 1584 + stw_raw((uint8_t *)addr, val);
  1585 + phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 1;
1507 } 1586 }
1508 1587
1509 -static void code_mem_writel(uint32_t addr, uint32_t val) 1588 +static void code_mem_writel(uint32_t addr, uint32_t val, uint32_t vaddr)
1510 { 1589 {
  1590 + unsigned long phys_addr;
  1591 +
  1592 + phys_addr = addr - (long)phys_ram_base;
1511 #if !defined(CONFIG_USER_ONLY) 1593 #if !defined(CONFIG_USER_ONLY)
1512 - tb_invalidate_phys_page_fast(addr, 4); 1594 + tb_invalidate_phys_page_fast(phys_addr, 4, vaddr);
1513 #endif 1595 #endif
1514 - stl_raw(phys_ram_base + addr, val); 1596 + stl_raw((uint8_t *)addr, val);
  1597 + phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 1;
1515 } 1598 }
1516 1599
1517 static CPUReadMemoryFunc *code_mem_read[3] = { 1600 static CPUReadMemoryFunc *code_mem_read[3] = {
@@ -1526,12 +1609,40 @@ static CPUWriteMemoryFunc *code_mem_write[3] = { @@ -1526,12 +1609,40 @@ static CPUWriteMemoryFunc *code_mem_write[3] = {
1526 code_mem_writel, 1609 code_mem_writel,
1527 }; 1610 };
1528 1611
  1612 +static void notdirty_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
  1613 +{
  1614 + stb_raw((uint8_t *)addr, val);
  1615 + tlb_set_dirty(addr, vaddr);
  1616 +}
  1617 +
  1618 +static void notdirty_mem_writew(uint32_t addr, uint32_t val, uint32_t vaddr)
  1619 +{
  1620 + stw_raw((uint8_t *)addr, val);
  1621 + tlb_set_dirty(addr, vaddr);
  1622 +}
  1623 +
  1624 +static void notdirty_mem_writel(uint32_t addr, uint32_t val, uint32_t vaddr)
  1625 +{
  1626 + stl_raw((uint8_t *)addr, val);
  1627 + tlb_set_dirty(addr, vaddr);
  1628 +}
  1629 +
  1630 +static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
  1631 + notdirty_mem_writeb,
  1632 + notdirty_mem_writew,
  1633 + notdirty_mem_writel,
  1634 +};
  1635 +
1529 static void io_mem_init(void) 1636 static void io_mem_init(void)
1530 { 1637 {
1531 cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, code_mem_read, unassigned_mem_write); 1638 cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, code_mem_read, unassigned_mem_write);
1532 cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write); 1639 cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write);
1533 cpu_register_io_memory(IO_MEM_CODE >> IO_MEM_SHIFT, code_mem_read, code_mem_write); 1640 cpu_register_io_memory(IO_MEM_CODE >> IO_MEM_SHIFT, code_mem_read, code_mem_write);
1534 - io_mem_nb = 4; 1641 + cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, code_mem_read, notdirty_mem_write);
  1642 + io_mem_nb = 5;
  1643 +
  1644 + /* alloc dirty bits array */
  1645 + phys_ram_dirty = malloc(phys_ram_size >> TARGET_PAGE_BITS);
1535 } 1646 }
1536 1647
1537 /* mem_read and mem_write are arrays of functions containing the 1648 /* mem_read and mem_write are arrays of functions containing the
@@ -1620,17 +1731,17 @@ void cpu_physical_memory_rw(CPUState *env, uint8_t *buf, target_ulong addr, @@ -1620,17 +1731,17 @@ void cpu_physical_memory_rw(CPUState *env, uint8_t *buf, target_ulong addr,
1620 if (l >= 4 && ((addr & 3) == 0)) { 1731 if (l >= 4 && ((addr & 3) == 0)) {
1621 /* 32 bit read access */ 1732 /* 32 bit read access */
1622 val = ldl_raw(buf); 1733 val = ldl_raw(buf);
1623 - io_mem_write[io_index][2](addr, val); 1734 + io_mem_write[io_index][2](addr, val, 0);
1624 l = 4; 1735 l = 4;
1625 } else if (l >= 2 && ((addr & 1) == 0)) { 1736 } else if (l >= 2 && ((addr & 1) == 0)) {
1626 /* 16 bit read access */ 1737 /* 16 bit read access */
1627 val = lduw_raw(buf); 1738 val = lduw_raw(buf);
1628 - io_mem_write[io_index][1](addr, val); 1739 + io_mem_write[io_index][1](addr, val, 0);
1629 l = 2; 1740 l = 2;
1630 } else { 1741 } else {
1631 /* 8 bit access */ 1742 /* 8 bit access */
1632 val = ldub_raw(buf); 1743 val = ldub_raw(buf);
1633 - io_mem_write[io_index][0](addr, val); 1744 + io_mem_write[io_index][0](addr, val, 0);
1634 l = 1; 1745 l = 1;
1635 } 1746 }
1636 } else { 1747 } else {
softmmu_template.h
@@ -76,14 +76,14 @@ static inline void glue(io_write, SUFFIX)(unsigned long physaddr, @@ -76,14 +76,14 @@ static inline void glue(io_write, SUFFIX)(unsigned long physaddr,
76 76
77 index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); 77 index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
78 #if SHIFT <= 2 78 #if SHIFT <= 2
79 - io_mem_write[index][SHIFT](physaddr, val); 79 + io_mem_write[index][SHIFT](physaddr, val, tlb_addr);
80 #else 80 #else
81 #ifdef TARGET_WORDS_BIGENDIAN 81 #ifdef TARGET_WORDS_BIGENDIAN
82 - io_mem_write[index][2](physaddr, val >> 32);  
83 - io_mem_write[index][2](physaddr + 4, val); 82 + io_mem_write[index][2](physaddr, val >> 32, tlb_addr);
  83 + io_mem_write[index][2](physaddr + 4, val, tlb_addr);
84 #else 84 #else
85 - io_mem_write[index][2](physaddr, val);  
86 - io_mem_write[index][2](physaddr + 4, val >> 32); 85 + io_mem_write[index][2](physaddr, val, tlb_addr);
  86 + io_mem_write[index][2](physaddr + 4, val >> 32, tlb_addr);
87 #endif 87 #endif
88 #endif /* SHIFT > 2 */ 88 #endif /* SHIFT > 2 */
89 } 89 }
@@ -233,6 +233,7 @@ int nographic; @@ -233,6 +233,7 @@ int nographic;
233 int term_inited; 233 int term_inited;
234 int64_t ticks_per_sec; 234 int64_t ticks_per_sec;
235 int boot_device = 'c'; 235 int boot_device = 'c';
  236 +static int ram_size;
236 237
237 /***********************************************************/ 238 /***********************************************************/
238 /* x86 io ports */ 239 /* x86 io ports */
@@ -610,7 +611,7 @@ void cmos_init(void) @@ -610,7 +611,7 @@ void cmos_init(void)
610 cmos_data[REG_EQUIPMENT_BYTE] |= 0x04; /* PS/2 mouse installed */ 611 cmos_data[REG_EQUIPMENT_BYTE] |= 0x04; /* PS/2 mouse installed */
611 612
612 /* memory size */ 613 /* memory size */
613 - val = (phys_ram_size / 1024) - 1024; 614 + val = (ram_size / 1024) - 1024;
614 if (val > 65535) 615 if (val > 65535)
615 val = 65535; 616 val = 65535;
616 cmos_data[0x17] = val; 617 cmos_data[0x17] = val;
@@ -618,7 +619,7 @@ void cmos_init(void) @@ -618,7 +619,7 @@ void cmos_init(void)
618 cmos_data[0x30] = val; 619 cmos_data[0x30] = val;
619 cmos_data[0x31] = val >> 8; 620 cmos_data[0x31] = val >> 8;
620 621
621 - val = (phys_ram_size / 65536) - ((16 * 1024 * 1024) / 65536); 622 + val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536);
622 if (val > 65535) 623 if (val > 65535)
623 val = 65535; 624 val = 65535;
624 cmos_data[0x34] = val; 625 cmos_data[0x34] = val;
@@ -3312,7 +3313,7 @@ extern void __sigaction(); @@ -3312,7 +3313,7 @@ extern void __sigaction();
3312 int main(int argc, char **argv) 3313 int main(int argc, char **argv)
3313 { 3314 {
3314 int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; 3315 int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index;
3315 - int snapshot, linux_boot, total_ram_size; 3316 + int snapshot, linux_boot;
3316 #if defined (TARGET_I386) 3317 #if defined (TARGET_I386)
3317 struct linux_params *params; 3318 struct linux_params *params;
3318 #endif 3319 #endif
@@ -3331,7 +3332,7 @@ int main(int argc, char **argv) @@ -3331,7 +3332,7 @@ int main(int argc, char **argv)
3331 fd_filename[i] = NULL; 3332 fd_filename[i] = NULL;
3332 for(i = 0; i < MAX_DISKS; i++) 3333 for(i = 0; i < MAX_DISKS; i++)
3333 hd_filename[i] = NULL; 3334 hd_filename[i] = NULL;
3334 - phys_ram_size = 32 * 1024 * 1024; 3335 + ram_size = 32 * 1024 * 1024;
3335 vga_ram_size = VGA_RAM_SIZE; 3336 vga_ram_size = VGA_RAM_SIZE;
3336 #if defined (TARGET_I386) 3337 #if defined (TARGET_I386)
3337 pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); 3338 pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT);
@@ -3425,10 +3426,10 @@ int main(int argc, char **argv) @@ -3425,10 +3426,10 @@ int main(int argc, char **argv)
3425 help(); 3426 help();
3426 break; 3427 break;
3427 case 'm': 3428 case 'm':
3428 - phys_ram_size = atoi(optarg) * 1024 * 1024;  
3429 - if (phys_ram_size <= 0) 3429 + ram_size = atoi(optarg) * 1024 * 1024;
  3430 + if (ram_size <= 0)
3430 help(); 3431 help();
3431 - if (phys_ram_size > PHYS_RAM_MAX_SIZE) { 3432 + if (ram_size > PHYS_RAM_MAX_SIZE) {
3432 fprintf(stderr, "qemu: at most %d MB RAM can be simulated\n", 3433 fprintf(stderr, "qemu: at most %d MB RAM can be simulated\n",
3433 PHYS_RAM_MAX_SIZE / (1024 * 1024)); 3434 PHYS_RAM_MAX_SIZE / (1024 * 1024));
3434 exit(1); 3435 exit(1);
@@ -3489,10 +3490,10 @@ int main(int argc, char **argv) @@ -3489,10 +3490,10 @@ int main(int argc, char **argv)
3489 #endif 3490 #endif
3490 3491
3491 /* init the memory */ 3492 /* init the memory */
3492 - total_ram_size = phys_ram_size + vga_ram_size; 3493 + phys_ram_size = ram_size + vga_ram_size;
3493 3494
3494 #ifdef CONFIG_SOFTMMU 3495 #ifdef CONFIG_SOFTMMU
3495 - phys_ram_base = malloc(total_ram_size); 3496 + phys_ram_base = memalign(TARGET_PAGE_SIZE, phys_ram_size);
3496 if (!phys_ram_base) { 3497 if (!phys_ram_base) {
3497 fprintf(stderr, "Could not allocate physical memory\n"); 3498 fprintf(stderr, "Could not allocate physical memory\n");
3498 exit(1); 3499 exit(1);
@@ -3518,10 +3519,10 @@ int main(int argc, char **argv) @@ -3518,10 +3519,10 @@ int main(int argc, char **argv)
3518 phys_ram_file); 3519 phys_ram_file);
3519 exit(1); 3520 exit(1);
3520 } 3521 }
3521 - ftruncate(phys_ram_fd, total_ram_size); 3522 + ftruncate(phys_ram_fd, phys_ram_size);
3522 unlink(phys_ram_file); 3523 unlink(phys_ram_file);
3523 - phys_ram_base = mmap(get_mmap_addr(total_ram_size),  
3524 - total_ram_size, 3524 + phys_ram_base = mmap(get_mmap_addr(phys_ram_size),
  3525 + phys_ram_size,
3525 PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED, 3526 PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED,
3526 phys_ram_fd, 0); 3527 phys_ram_fd, 0);
3527 if (phys_ram_base == MAP_FAILED) { 3528 if (phys_ram_base == MAP_FAILED) {
@@ -3551,7 +3552,7 @@ int main(int argc, char **argv) @@ -3551,7 +3552,7 @@ int main(int argc, char **argv)
3551 init_ioports(); 3552 init_ioports();
3552 3553
3553 /* allocate RAM */ 3554 /* allocate RAM */
3554 - cpu_register_physical_memory(0, phys_ram_size, 0); 3555 + cpu_register_physical_memory(0, ram_size, 0);
3555 3556
3556 if (linux_boot) { 3557 if (linux_boot) {
3557 /* now we can load the kernel */ 3558 /* now we can load the kernel */
@@ -3580,7 +3581,7 @@ int main(int argc, char **argv) @@ -3580,7 +3581,7 @@ int main(int argc, char **argv)
3580 params->mount_root_rdonly = 0; 3581 params->mount_root_rdonly = 0;
3581 stw_raw(&params->cl_magic, 0xA33F); 3582 stw_raw(&params->cl_magic, 0xA33F);
3582 stw_raw(&params->cl_offset, params->commandline - (uint8_t *)params); 3583 stw_raw(&params->cl_offset, params->commandline - (uint8_t *)params);
3583 - stl_raw(&params->alt_mem_k, (phys_ram_size / 1024) - 1024); 3584 + stl_raw(&params->alt_mem_k, (ram_size / 1024) - 1024);
3584 pstrcat(params->commandline, sizeof(params->commandline), kernel_cmdline); 3585 pstrcat(params->commandline, sizeof(params->commandline), kernel_cmdline);
3585 params->loader_type = 0x01; 3586 params->loader_type = 0x01;
3586 if (initrd_size > 0) { 3587 if (initrd_size > 0) {
@@ -3617,7 +3618,7 @@ int main(int argc, char **argv) @@ -3617,7 +3618,7 @@ int main(int argc, char **argv)
3617 env->regs[R_ESI] = KERNEL_PARAMS_ADDR; 3618 env->regs[R_ESI] = KERNEL_PARAMS_ADDR;
3618 env->eflags = 0x2; 3619 env->eflags = 0x2;
3619 #elif defined (TARGET_PPC) 3620 #elif defined (TARGET_PPC)
3620 - PPC_init_hw(env, phys_ram_size, KERNEL_LOAD_ADDR, ret, 3621 + PPC_init_hw(env, ram_size, KERNEL_LOAD_ADDR, ret,
3621 KERNEL_STACK_ADDR, boot_device); 3622 KERNEL_STACK_ADDR, boot_device);
3622 #endif 3623 #endif
3623 } else { 3624 } else {
@@ -3669,7 +3670,7 @@ int main(int argc, char **argv) @@ -3669,7 +3670,7 @@ int main(int argc, char **argv)
3669 /* init basic PC hardware */ 3670 /* init basic PC hardware */
3670 register_ioport_write(0x80, 1, ioport80_write, 1); 3671 register_ioport_write(0x80, 1, ioport80_write, 1);
3671 3672
3672 - vga_initialize(ds, phys_ram_base + phys_ram_size, phys_ram_size, 3673 + vga_initialize(ds, phys_ram_base + ram_size, ram_size,
3673 vga_ram_size); 3674 vga_ram_size);
3674 #if defined (TARGET_I386) 3675 #if defined (TARGET_I386)
3675 cmos_init(); 3676 cmos_init();