1209 |
env->current_tb = NULL; |
env->current_tb = NULL; |
1210 |
|
|
1211 |
for(i = 0; i < CPU_TLB_SIZE; i++) { |
for(i = 0; i < CPU_TLB_SIZE; i++) { |
1212 |
env->tlb_read[0][i].address = -1; |
env->tlb_table[0][i].addr_read = -1; |
1213 |
env->tlb_write[0][i].address = -1; |
env->tlb_table[0][i].addr_write = -1; |
1214 |
env->tlb_read[1][i].address = -1; |
env->tlb_table[0][i].addr_code = -1; |
1215 |
env->tlb_write[1][i].address = -1; |
env->tlb_table[1][i].addr_read = -1; |
1216 |
|
env->tlb_table[1][i].addr_write = -1; |
1217 |
|
env->tlb_table[1][i].addr_code = -1; |
1218 |
} |
} |
1219 |
|
|
1220 |
memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *)); |
memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *)); |
1232 |
|
|
1233 |
static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr) |
static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr) |
1234 |
{ |
{ |
1235 |
if (addr == (tlb_entry->address & |
if (addr == (tlb_entry->addr_read & |
1236 |
(TARGET_PAGE_MASK | TLB_INVALID_MASK))) |
(TARGET_PAGE_MASK | TLB_INVALID_MASK)) || |
1237 |
tlb_entry->address = -1; |
addr == (tlb_entry->addr_write & |
1238 |
|
(TARGET_PAGE_MASK | TLB_INVALID_MASK)) || |
1239 |
|
addr == (tlb_entry->addr_code & |
1240 |
|
(TARGET_PAGE_MASK | TLB_INVALID_MASK))) { |
1241 |
|
tlb_entry->addr_read = -1; |
1242 |
|
tlb_entry->addr_write = -1; |
1243 |
|
tlb_entry->addr_code = -1; |
1244 |
|
} |
1245 |
} |
} |
1246 |
|
|
1247 |
void tlb_flush_page(CPUState *env, target_ulong addr) |
void tlb_flush_page(CPUState *env, target_ulong addr) |
1258 |
|
|
1259 |
addr &= TARGET_PAGE_MASK; |
addr &= TARGET_PAGE_MASK; |
1260 |
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
1261 |
tlb_flush_entry(&env->tlb_read[0][i], addr); |
tlb_flush_entry(&env->tlb_table[0][i], addr); |
1262 |
tlb_flush_entry(&env->tlb_write[0][i], addr); |
tlb_flush_entry(&env->tlb_table[1][i], addr); |
|
tlb_flush_entry(&env->tlb_read[1][i], addr); |
|
|
tlb_flush_entry(&env->tlb_write[1][i], addr); |
|
1263 |
|
|
1264 |
for(i = 0; i < TB_JMP_CACHE_SIZE; i++) { |
for(i = 0; i < TB_JMP_CACHE_SIZE; i++) { |
1265 |
tb = env->tb_jmp_cache[i]; |
tb = env->tb_jmp_cache[i]; |
1302 |
unsigned long start, unsigned long length) |
unsigned long start, unsigned long length) |
1303 |
{ |
{ |
1304 |
unsigned long addr; |
unsigned long addr; |
1305 |
if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { |
if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { |
1306 |
addr = (tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend; |
addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend; |
1307 |
if ((addr - start) < length) { |
if ((addr - start) < length) { |
1308 |
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; |
1309 |
} |
} |
1310 |
} |
} |
1311 |
} |
} |
1347 |
start1 = start + (unsigned long)phys_ram_base; |
start1 = start + (unsigned long)phys_ram_base; |
1348 |
for(env = first_cpu; env != NULL; env = env->next_cpu) { |
for(env = first_cpu; env != NULL; env = env->next_cpu) { |
1349 |
for(i = 0; i < CPU_TLB_SIZE; i++) |
for(i = 0; i < CPU_TLB_SIZE; i++) |
1350 |
tlb_reset_dirty_range(&env->tlb_write[0][i], start1, length); |
tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length); |
1351 |
for(i = 0; i < CPU_TLB_SIZE; i++) |
for(i = 0; i < CPU_TLB_SIZE; i++) |
1352 |
tlb_reset_dirty_range(&env->tlb_write[1][i], start1, length); |
tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length); |
1353 |
} |
} |
1354 |
|
|
1355 |
#if !defined(CONFIG_SOFTMMU) |
#if !defined(CONFIG_SOFTMMU) |
1385 |
{ |
{ |
1386 |
ram_addr_t ram_addr; |
ram_addr_t ram_addr; |
1387 |
|
|
1388 |
if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { |
if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { |
1389 |
ram_addr = (tlb_entry->address & TARGET_PAGE_MASK) + |
ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + |
1390 |
tlb_entry->addend - (unsigned long)phys_ram_base; |
tlb_entry->addend - (unsigned long)phys_ram_base; |
1391 |
if (!cpu_physical_memory_is_dirty(ram_addr)) { |
if (!cpu_physical_memory_is_dirty(ram_addr)) { |
1392 |
tlb_entry->address |= IO_MEM_NOTDIRTY; |
tlb_entry->addr_write |= IO_MEM_NOTDIRTY; |
1393 |
} |
} |
1394 |
} |
} |
1395 |
} |
} |
1399 |
{ |
{ |
1400 |
int i; |
int i; |
1401 |
for(i = 0; i < CPU_TLB_SIZE; i++) |
for(i = 0; i < CPU_TLB_SIZE; i++) |
1402 |
tlb_update_dirty(&env->tlb_write[0][i]); |
tlb_update_dirty(&env->tlb_table[0][i]); |
1403 |
for(i = 0; i < CPU_TLB_SIZE; i++) |
for(i = 0; i < CPU_TLB_SIZE; i++) |
1404 |
tlb_update_dirty(&env->tlb_write[1][i]); |
tlb_update_dirty(&env->tlb_table[1][i]); |
1405 |
} |
} |
1406 |
|
|
1407 |
static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, |
static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, |
1408 |
unsigned long start) |
unsigned long start) |
1409 |
{ |
{ |
1410 |
unsigned long addr; |
unsigned long addr; |
1411 |
if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) { |
if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) { |
1412 |
addr = (tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend; |
addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend; |
1413 |
if (addr == start) { |
if (addr == start) { |
1414 |
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; |
1415 |
} |
} |
1416 |
} |
} |
1417 |
} |
} |
1425 |
|
|
1426 |
addr &= TARGET_PAGE_MASK; |
addr &= TARGET_PAGE_MASK; |
1427 |
i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
1428 |
tlb_set_dirty1(&env->tlb_write[0][i], addr); |
tlb_set_dirty1(&env->tlb_table[0][i], addr); |
1429 |
tlb_set_dirty1(&env->tlb_write[1][i], addr); |
tlb_set_dirty1(&env->tlb_table[1][i], addr); |
1430 |
} |
} |
1431 |
|
|
1432 |
/* add a new TLB entry. At most one entry for a given virtual address |
/* add a new TLB entry. At most one entry for a given virtual address |
1433 |
is permitted. Return 0 if OK or 2 if the page could not be mapped |
is permitted. Return 0 if OK or 2 if the page could not be mapped |
1434 |
(can only happen in non SOFTMMU mode for I/O pages or pages |
(can only happen in non SOFTMMU mode for I/O pages or pages |
1435 |
conflicting with the host address space). */ |
conflicting with the host address space). */ |
1436 |
int tlb_set_page(CPUState *env, target_ulong vaddr, |
int tlb_set_page_exec(CPUState *env, target_ulong vaddr, |
1437 |
target_phys_addr_t paddr, int prot, |
target_phys_addr_t paddr, int prot, |
1438 |
int is_user, int is_softmmu) |
int is_user, int is_softmmu) |
1439 |
{ |
{ |
1440 |
PhysPageDesc *p; |
PhysPageDesc *p; |
1441 |
unsigned long pd; |
unsigned long pd; |
1443 |
target_ulong address; |
target_ulong address; |
1444 |
target_phys_addr_t addend; |
target_phys_addr_t addend; |
1445 |
int ret; |
int ret; |
1446 |
|
CPUTLBEntry *te; |
1447 |
|
|
1448 |
p = phys_page_find(paddr >> TARGET_PAGE_BITS); |
p = phys_page_find(paddr >> TARGET_PAGE_BITS); |
1449 |
if (!p) { |
if (!p) { |
1453 |
} |
} |
1454 |
#if defined(DEBUG_TLB) |
#if defined(DEBUG_TLB) |
1455 |
printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n", |
printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n", |
1456 |
vaddr, paddr, prot, is_user, is_softmmu, pd); |
vaddr, (int)paddr, prot, is_user, is_softmmu, pd); |
1457 |
#endif |
#endif |
1458 |
|
|
1459 |
ret = 0; |
ret = 0; |
1473 |
|
|
1474 |
index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
1475 |
addend -= vaddr; |
addend -= vaddr; |
1476 |
|
te = &env->tlb_table[is_user][index]; |
1477 |
|
te->addend = addend; |
1478 |
if (prot & PAGE_READ) { |
if (prot & PAGE_READ) { |
1479 |
env->tlb_read[is_user][index].address = address; |
te->addr_read = address; |
1480 |
env->tlb_read[is_user][index].addend = addend; |
} else { |
1481 |
|
te->addr_read = -1; |
1482 |
|
} |
1483 |
|
if (prot & PAGE_EXEC) { |
1484 |
|
te->addr_code = address; |
1485 |
} else { |
} else { |
1486 |
env->tlb_read[is_user][index].address = -1; |
te->addr_code = -1; |
|
env->tlb_read[is_user][index].addend = -1; |
|
1487 |
} |
} |
1488 |
if (prot & PAGE_WRITE) { |
if (prot & PAGE_WRITE) { |
1489 |
if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) { |
if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) { |
1490 |
/* ROM: access is ignored (same as unassigned) */ |
/* ROM: access is ignored (same as unassigned) */ |
1491 |
env->tlb_write[is_user][index].address = vaddr | IO_MEM_ROM; |
te->addr_write = vaddr | IO_MEM_ROM; |
|
env->tlb_write[is_user][index].addend = addend; |
|
1492 |
} else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && |
} else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && |
1493 |
!cpu_physical_memory_is_dirty(pd)) { |
!cpu_physical_memory_is_dirty(pd)) { |
1494 |
env->tlb_write[is_user][index].address = vaddr | IO_MEM_NOTDIRTY; |
te->addr_write = vaddr | IO_MEM_NOTDIRTY; |
|
env->tlb_write[is_user][index].addend = addend; |
|
1495 |
} else { |
} else { |
1496 |
env->tlb_write[is_user][index].address = address; |
te->addr_write = address; |
|
env->tlb_write[is_user][index].addend = addend; |
|
1497 |
} |
} |
1498 |
} else { |
} else { |
1499 |
env->tlb_write[is_user][index].address = -1; |
te->addr_write = -1; |
|
env->tlb_write[is_user][index].addend = -1; |
|
1500 |
} |
} |
1501 |
} |
} |
1502 |
#if !defined(CONFIG_SOFTMMU) |
#if !defined(CONFIG_SOFTMMU) |
1595 |
{ |
{ |
1596 |
} |
} |
1597 |
|
|
1598 |
int tlb_set_page(CPUState *env, target_ulong vaddr, |
int tlb_set_page_exec(CPUState *env, target_ulong vaddr, |
1599 |
target_phys_addr_t paddr, int prot, |
target_phys_addr_t paddr, int prot, |
1600 |
int is_user, int is_softmmu) |
int is_user, int is_softmmu) |
1601 |
{ |
{ |
1602 |
return 0; |
return 0; |
1603 |
} |
} |
2061 |
return val; |
return val; |
2062 |
} |
} |
2063 |
|
|
2064 |
|
/* warning: addr must be aligned */ |
2065 |
|
uint64_t ldq_phys(target_phys_addr_t addr) |
2066 |
|
{ |
2067 |
|
int io_index; |
2068 |
|
uint8_t *ptr; |
2069 |
|
uint64_t val; |
2070 |
|
unsigned long pd; |
2071 |
|
PhysPageDesc *p; |
2072 |
|
|
2073 |
|
p = phys_page_find(addr >> TARGET_PAGE_BITS); |
2074 |
|
if (!p) { |
2075 |
|
pd = IO_MEM_UNASSIGNED; |
2076 |
|
} else { |
2077 |
|
pd = p->phys_offset; |
2078 |
|
} |
2079 |
|
|
2080 |
|
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { |
2081 |
|
/* I/O case */ |
2082 |
|
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); |
2083 |
|
#ifdef TARGET_WORDS_BIGENDIAN |
2084 |
|
val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32; |
2085 |
|
val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4); |
2086 |
|
#else |
2087 |
|
val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr); |
2088 |
|
val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32; |
2089 |
|
#endif |
2090 |
|
} else { |
2091 |
|
/* RAM case */ |
2092 |
|
ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + |
2093 |
|
(addr & ~TARGET_PAGE_MASK); |
2094 |
|
val = ldq_p(ptr); |
2095 |
|
} |
2096 |
|
return val; |
2097 |
|
} |
2098 |
|
|
2099 |
/* XXX: optimize */ |
/* XXX: optimize */ |
2100 |
uint32_t ldub_phys(target_phys_addr_t addr) |
uint32_t ldub_phys(target_phys_addr_t addr) |
2101 |
{ |
{ |
2112 |
return tswap16(val); |
return tswap16(val); |
2113 |
} |
} |
2114 |
|
|
|
/* 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); |
|
|
} |
|
|
|
|
2115 |
/* warning: addr must be aligned. The ram page is not masked as dirty |
/* warning: addr must be aligned. The ram page is not masked as dirty |
2116 |
and the code inside is not invalidated. It is useful if the dirty |
and the code inside is not invalidated. It is useful if the dirty |
2117 |
bits are used to track modified PTEs */ |
bits are used to track modified PTEs */ |