Commit 1ccde1cb942f77958776578939bbcfc4c9bdf362
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
Showing
5 changed files
with
185 additions
and
55 deletions
cpu-all.h
... | ... | @@ -500,6 +500,7 @@ int cpu_inl(CPUState *env, int addr); |
500 | 500 | extern int phys_ram_size; |
501 | 501 | extern int phys_ram_fd; |
502 | 502 | extern uint8_t *phys_ram_base; |
503 | +extern uint8_t *phys_ram_dirty; | |
503 | 504 | |
504 | 505 | /* physical memory access */ |
505 | 506 | #define IO_MEM_NB_ENTRIES 256 |
... | ... | @@ -509,9 +510,11 @@ extern uint8_t *phys_ram_base; |
509 | 510 | #define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */ |
510 | 511 | #define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ |
511 | 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 | 518 | typedef uint32_t CPUReadMemoryFunc(uint32_t addr); |
516 | 519 | |
517 | 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 | 528 | int cpu_memory_rw_debug(CPUState *env, |
526 | 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 | 544 | /* gdb stub API */ |
529 | 545 | extern int gdbstub_fd; |
530 | 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 | 530 | } |
531 | 531 | #else |
532 | 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 | 535 | /* XXX: i386 target specific */ |
534 | 536 | static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) |
535 | 537 | { | ... | ... |
exec.c
... | ... | @@ -59,6 +59,7 @@ uint8_t *code_gen_ptr; |
59 | 59 | int phys_ram_size; |
60 | 60 | int phys_ram_fd; |
61 | 61 | uint8_t *phys_ram_base; |
62 | +uint8_t *phys_ram_dirty; | |
62 | 63 | |
63 | 64 | typedef struct PageDesc { |
64 | 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 | 163 | #if !defined(CONFIG_USER_ONLY) |
163 | 164 | static void tlb_protect_code(CPUState *env, uint32_t addr); |
164 | 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 | 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 | 529 | |
529 | 530 | /* invalidate all TBs which intersect with the target physical page |
530 | 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 | 538 | int n; |
535 | 539 | PageDesc *p; |
... | ... | @@ -571,13 +575,13 @@ static void tb_invalidate_phys_page_range(target_ulong start, target_ulong end) |
571 | 575 | /* if no code remaining, no need to continue to use slow writes */ |
572 | 576 | if (!p->first_tb) { |
573 | 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 | 580 | #endif |
577 | 581 | } |
578 | 582 | |
579 | 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 | 586 | PageDesc *p; |
583 | 587 | int offset, b; |
... | ... | @@ -592,7 +596,7 @@ static inline void tb_invalidate_phys_page_fast(target_ulong start, int len) |
592 | 596 | goto do_invalidate; |
593 | 597 | } else { |
594 | 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 | 1092 | (TARGET_PAGE_MASK | TLB_INVALID_MASK)) && |
1089 | 1093 | (tlb_entry->address & ~TARGET_PAGE_MASK) != IO_MEM_CODE && |
1090 | 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 | 1119 | if (addr == (tlb_entry->address & |
1117 | 1120 | (TARGET_PAGE_MASK | TLB_INVALID_MASK)) && |
1118 | 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 | 1140 | { |
1139 | 1141 | if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_CODE && |
1140 | 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 | 1147 | /* update the TLB so that writes in physical page 'phys_addr' are no longer |
1147 | 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 | 1151 | int i; |
1152 | 1152 | |
1153 | 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 | 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 | 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 | 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 | 1273 | if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) { |
1211 | 1274 | /* ROM: access is ignored (same as unassigned) */ |
1212 | 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 | 1277 | } else if (first_tb) { |
1215 | 1278 | /* if code is present, we use a specific memory |
1216 | 1279 | handler. It works only for physical memory access */ |
1217 | 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 | 1286 | } else { |
1220 | 1287 | env->tlb_write[is_user][index].address = address; |
1221 | 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 | 1513 | } |
1447 | 1514 | } |
1448 | 1515 | |
1516 | +static inline void tlb_set_dirty(unsigned long addr, target_ulong vaddr) | |
1517 | +{ | |
1518 | +} | |
1519 | + | |
1449 | 1520 | #endif /* defined(CONFIG_USER_ONLY) */ |
1450 | 1521 | |
1451 | 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 | 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 | 1561 | /* self modifying code support in soft mmu mode : writing to a page |
1491 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 1600 | static CPUReadMemoryFunc *code_mem_read[3] = { |
... | ... | @@ -1526,12 +1609,40 @@ static CPUWriteMemoryFunc *code_mem_write[3] = { |
1526 | 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 | 1636 | static void io_mem_init(void) |
1530 | 1637 | { |
1531 | 1638 | cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, code_mem_read, unassigned_mem_write); |
1532 | 1639 | cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write); |
1533 | 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 | 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 | 1731 | if (l >= 4 && ((addr & 3) == 0)) { |
1621 | 1732 | /* 32 bit read access */ |
1622 | 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 | 1735 | l = 4; |
1625 | 1736 | } else if (l >= 2 && ((addr & 1) == 0)) { |
1626 | 1737 | /* 16 bit read access */ |
1627 | 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 | 1740 | l = 2; |
1630 | 1741 | } else { |
1631 | 1742 | /* 8 bit access */ |
1632 | 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 | 1745 | l = 1; |
1635 | 1746 | } |
1636 | 1747 | } else { | ... | ... |
softmmu_template.h
... | ... | @@ -76,14 +76,14 @@ static inline void glue(io_write, SUFFIX)(unsigned long physaddr, |
76 | 76 | |
77 | 77 | index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); |
78 | 78 | #if SHIFT <= 2 |
79 | - io_mem_write[index][SHIFT](physaddr, val); | |
79 | + io_mem_write[index][SHIFT](physaddr, val, tlb_addr); | |
80 | 80 | #else |
81 | 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 | 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 | 87 | #endif |
88 | 88 | #endif /* SHIFT > 2 */ |
89 | 89 | } | ... | ... |
vl.c
... | ... | @@ -233,6 +233,7 @@ int nographic; |
233 | 233 | int term_inited; |
234 | 234 | int64_t ticks_per_sec; |
235 | 235 | int boot_device = 'c'; |
236 | +static int ram_size; | |
236 | 237 | |
237 | 238 | /***********************************************************/ |
238 | 239 | /* x86 io ports */ |
... | ... | @@ -610,7 +611,7 @@ void cmos_init(void) |
610 | 611 | cmos_data[REG_EQUIPMENT_BYTE] |= 0x04; /* PS/2 mouse installed */ |
611 | 612 | |
612 | 613 | /* memory size */ |
613 | - val = (phys_ram_size / 1024) - 1024; | |
614 | + val = (ram_size / 1024) - 1024; | |
614 | 615 | if (val > 65535) |
615 | 616 | val = 65535; |
616 | 617 | cmos_data[0x17] = val; |
... | ... | @@ -618,7 +619,7 @@ void cmos_init(void) |
618 | 619 | cmos_data[0x30] = val; |
619 | 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 | 623 | if (val > 65535) |
623 | 624 | val = 65535; |
624 | 625 | cmos_data[0x34] = val; |
... | ... | @@ -3312,7 +3313,7 @@ extern void __sigaction(); |
3312 | 3313 | int main(int argc, char **argv) |
3313 | 3314 | { |
3314 | 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 | 3317 | #if defined (TARGET_I386) |
3317 | 3318 | struct linux_params *params; |
3318 | 3319 | #endif |
... | ... | @@ -3331,7 +3332,7 @@ int main(int argc, char **argv) |
3331 | 3332 | fd_filename[i] = NULL; |
3332 | 3333 | for(i = 0; i < MAX_DISKS; i++) |
3333 | 3334 | hd_filename[i] = NULL; |
3334 | - phys_ram_size = 32 * 1024 * 1024; | |
3335 | + ram_size = 32 * 1024 * 1024; | |
3335 | 3336 | vga_ram_size = VGA_RAM_SIZE; |
3336 | 3337 | #if defined (TARGET_I386) |
3337 | 3338 | pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); |
... | ... | @@ -3425,10 +3426,10 @@ int main(int argc, char **argv) |
3425 | 3426 | help(); |
3426 | 3427 | break; |
3427 | 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 | 3431 | help(); |
3431 | - if (phys_ram_size > PHYS_RAM_MAX_SIZE) { | |
3432 | + if (ram_size > PHYS_RAM_MAX_SIZE) { | |
3432 | 3433 | fprintf(stderr, "qemu: at most %d MB RAM can be simulated\n", |
3433 | 3434 | PHYS_RAM_MAX_SIZE / (1024 * 1024)); |
3434 | 3435 | exit(1); |
... | ... | @@ -3489,10 +3490,10 @@ int main(int argc, char **argv) |
3489 | 3490 | #endif |
3490 | 3491 | |
3491 | 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 | 3495 | #ifdef CONFIG_SOFTMMU |
3495 | - phys_ram_base = malloc(total_ram_size); | |
3496 | + phys_ram_base = memalign(TARGET_PAGE_SIZE, phys_ram_size); | |
3496 | 3497 | if (!phys_ram_base) { |
3497 | 3498 | fprintf(stderr, "Could not allocate physical memory\n"); |
3498 | 3499 | exit(1); |
... | ... | @@ -3518,10 +3519,10 @@ int main(int argc, char **argv) |
3518 | 3519 | phys_ram_file); |
3519 | 3520 | exit(1); |
3520 | 3521 | } |
3521 | - ftruncate(phys_ram_fd, total_ram_size); | |
3522 | + ftruncate(phys_ram_fd, phys_ram_size); | |
3522 | 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 | 3526 | PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED, |
3526 | 3527 | phys_ram_fd, 0); |
3527 | 3528 | if (phys_ram_base == MAP_FAILED) { |
... | ... | @@ -3551,7 +3552,7 @@ int main(int argc, char **argv) |
3551 | 3552 | init_ioports(); |
3552 | 3553 | |
3553 | 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 | 3557 | if (linux_boot) { |
3557 | 3558 | /* now we can load the kernel */ |
... | ... | @@ -3580,7 +3581,7 @@ int main(int argc, char **argv) |
3580 | 3581 | params->mount_root_rdonly = 0; |
3581 | 3582 | stw_raw(¶ms->cl_magic, 0xA33F); |
3582 | 3583 | stw_raw(¶ms->cl_offset, params->commandline - (uint8_t *)params); |
3583 | - stl_raw(¶ms->alt_mem_k, (phys_ram_size / 1024) - 1024); | |
3584 | + stl_raw(¶ms->alt_mem_k, (ram_size / 1024) - 1024); | |
3584 | 3585 | pstrcat(params->commandline, sizeof(params->commandline), kernel_cmdline); |
3585 | 3586 | params->loader_type = 0x01; |
3586 | 3587 | if (initrd_size > 0) { |
... | ... | @@ -3617,7 +3618,7 @@ int main(int argc, char **argv) |
3617 | 3618 | env->regs[R_ESI] = KERNEL_PARAMS_ADDR; |
3618 | 3619 | env->eflags = 0x2; |
3619 | 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 | 3622 | KERNEL_STACK_ADDR, boot_device); |
3622 | 3623 | #endif |
3623 | 3624 | } else { |
... | ... | @@ -3669,7 +3670,7 @@ int main(int argc, char **argv) |
3669 | 3670 | /* init basic PC hardware */ |
3670 | 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 | 3674 | vga_ram_size); |
3674 | 3675 | #if defined (TARGET_I386) |
3675 | 3676 | cmos_init(); | ... | ... |