Commit 84b7b8e778937f1ec3cbdb8914261a2fe0067ef2
1 parent
5cf38396
PAGE_EXEC support in TLBs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1676 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
155 additions
and
90 deletions
cpu-defs.h
| ... | ... | @@ -80,7 +80,8 @@ typedef unsigned long ram_addr_t; |
| 80 | 80 | #define TB_JMP_CACHE_BITS 12 |
| 81 | 81 | #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) |
| 82 | 82 | |
| 83 | -#define CPU_TLB_SIZE 256 | |
| 83 | +#define CPU_TLB_BITS 8 | |
| 84 | +#define CPU_TLB_SIZE (1 << CPU_TLB_BITS) | |
| 84 | 85 | |
| 85 | 86 | typedef struct CPUTLBEntry { |
| 86 | 87 | /* bit 31 to TARGET_PAGE_BITS : virtual address |
| ... | ... | @@ -89,7 +90,9 @@ typedef struct CPUTLBEntry { |
| 89 | 90 | bit 3 : indicates that the entry is invalid |
| 90 | 91 | bit 2..0 : zero |
| 91 | 92 | */ |
| 92 | - target_ulong address; | |
| 93 | + target_ulong addr_read; | |
| 94 | + target_ulong addr_write; | |
| 95 | + target_ulong addr_code; | |
| 93 | 96 | /* addend to virtual address to get physical address */ |
| 94 | 97 | target_phys_addr_t addend; |
| 95 | 98 | } CPUTLBEntry; |
| ... | ... | @@ -105,8 +108,7 @@ typedef struct CPUTLBEntry { |
| 105 | 108 | target_ulong mem_write_vaddr; /* target virtual addr at which the \ |
| 106 | 109 | memory was written */ \ |
| 107 | 110 | /* 0 = kernel, 1 = user */ \ |
| 108 | - CPUTLBEntry tlb_read[2][CPU_TLB_SIZE]; \ | |
| 109 | - CPUTLBEntry tlb_write[2][CPU_TLB_SIZE]; \ | |
| 111 | + CPUTLBEntry tlb_table[2][CPU_TLB_SIZE]; \ | |
| 110 | 112 | struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \ |
| 111 | 113 | \ |
| 112 | 114 | /* from this point: preserved by CPU reset */ \ | ... | ... |
exec-all.h
| ... | ... | @@ -98,9 +98,17 @@ void tb_invalidate_phys_page_range(target_ulong start, target_ulong end, |
| 98 | 98 | void tb_invalidate_page_range(target_ulong start, target_ulong end); |
| 99 | 99 | void tlb_flush_page(CPUState *env, target_ulong addr); |
| 100 | 100 | void tlb_flush(CPUState *env, int flush_global); |
| 101 | -int tlb_set_page(CPUState *env, target_ulong vaddr, | |
| 102 | - target_phys_addr_t paddr, int prot, | |
| 103 | - int is_user, int is_softmmu); | |
| 101 | +int tlb_set_page_exec(CPUState *env, target_ulong vaddr, | |
| 102 | + target_phys_addr_t paddr, int prot, | |
| 103 | + int is_user, int is_softmmu); | |
| 104 | +static inline int tlb_set_page(CPUState *env, target_ulong vaddr, | |
| 105 | + target_phys_addr_t paddr, int prot, | |
| 106 | + int is_user, int is_softmmu) | |
| 107 | +{ | |
| 108 | + if (prot & PAGE_READ) | |
| 109 | + prot |= PAGE_EXEC; | |
| 110 | + return tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); | |
| 111 | +} | |
| 104 | 112 | |
| 105 | 113 | #define CODE_GEN_MAX_SIZE 65536 |
| 106 | 114 | #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ |
| ... | ... | @@ -554,15 +562,15 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) |
| 554 | 562 | #else |
| 555 | 563 | #error unimplemented CPU |
| 556 | 564 | #endif |
| 557 | - if (__builtin_expect(env->tlb_read[is_user][index].address != | |
| 565 | + if (__builtin_expect(env->tlb_table[is_user][index].addr_code != | |
| 558 | 566 | (addr & TARGET_PAGE_MASK), 0)) { |
| 559 | 567 | ldub_code(addr); |
| 560 | 568 | } |
| 561 | - pd = env->tlb_read[is_user][index].address & ~TARGET_PAGE_MASK; | |
| 569 | + pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK; | |
| 562 | 570 | if (pd > IO_MEM_ROM) { |
| 563 | 571 | cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x%08lx\n", addr); |
| 564 | 572 | } |
| 565 | - return addr + env->tlb_read[is_user][index].addend - (unsigned long)phys_ram_base; | |
| 573 | + return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base; | |
| 566 | 574 | } |
| 567 | 575 | #endif |
| 568 | 576 | ... | ... |
exec.c
| ... | ... | @@ -1209,10 +1209,12 @@ void tlb_flush(CPUState *env, int flush_global) |
| 1209 | 1209 | env->current_tb = NULL; |
| 1210 | 1210 | |
| 1211 | 1211 | for(i = 0; i < CPU_TLB_SIZE; i++) { |
| 1212 | - env->tlb_read[0][i].address = -1; | |
| 1213 | - env->tlb_write[0][i].address = -1; | |
| 1214 | - env->tlb_read[1][i].address = -1; | |
| 1215 | - env->tlb_write[1][i].address = -1; | |
| 1212 | + env->tlb_table[0][i].addr_read = -1; | |
| 1213 | + env->tlb_table[0][i].addr_write = -1; | |
| 1214 | + env->tlb_table[0][i].addr_code = -1; | |
| 1215 | + 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; | |
| 1216 | 1218 | } |
| 1217 | 1219 | |
| 1218 | 1220 | memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *)); |
| ... | ... | @@ -1230,9 +1232,16 @@ void tlb_flush(CPUState *env, int flush_global) |
| 1230 | 1232 | |
| 1231 | 1233 | static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr) |
| 1232 | 1234 | { |
| 1233 | - if (addr == (tlb_entry->address & | |
| 1234 | - (TARGET_PAGE_MASK | TLB_INVALID_MASK))) | |
| 1235 | - tlb_entry->address = -1; | |
| 1235 | + if (addr == (tlb_entry->addr_read & | |
| 1236 | + (TARGET_PAGE_MASK | TLB_INVALID_MASK)) || | |
| 1237 | + 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 | + } | |
| 1236 | 1245 | } |
| 1237 | 1246 | |
| 1238 | 1247 | void tlb_flush_page(CPUState *env, target_ulong addr) |
| ... | ... | @@ -1249,10 +1258,8 @@ void tlb_flush_page(CPUState *env, target_ulong addr) |
| 1249 | 1258 | |
| 1250 | 1259 | addr &= TARGET_PAGE_MASK; |
| 1251 | 1260 | i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 1252 | - tlb_flush_entry(&env->tlb_read[0][i], addr); | |
| 1253 | - tlb_flush_entry(&env->tlb_write[0][i], addr); | |
| 1254 | - tlb_flush_entry(&env->tlb_read[1][i], addr); | |
| 1255 | - tlb_flush_entry(&env->tlb_write[1][i], addr); | |
| 1261 | + tlb_flush_entry(&env->tlb_table[0][i], addr); | |
| 1262 | + tlb_flush_entry(&env->tlb_table[1][i], addr); | |
| 1256 | 1263 | |
| 1257 | 1264 | for(i = 0; i < TB_JMP_CACHE_SIZE; i++) { |
| 1258 | 1265 | tb = env->tb_jmp_cache[i]; |
| ... | ... | @@ -1295,10 +1302,10 @@ static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, |
| 1295 | 1302 | unsigned long start, unsigned long length) |
| 1296 | 1303 | { |
| 1297 | 1304 | unsigned long addr; |
| 1298 | - if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { | |
| 1299 | - addr = (tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend; | |
| 1305 | + if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { | |
| 1306 | + addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend; | |
| 1300 | 1307 | if ((addr - start) < length) { |
| 1301 | - tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY; | |
| 1308 | + tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY; | |
| 1302 | 1309 | } |
| 1303 | 1310 | } |
| 1304 | 1311 | } |
| ... | ... | @@ -1340,9 +1347,9 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, |
| 1340 | 1347 | start1 = start + (unsigned long)phys_ram_base; |
| 1341 | 1348 | for(env = first_cpu; env != NULL; env = env->next_cpu) { |
| 1342 | 1349 | for(i = 0; i < CPU_TLB_SIZE; i++) |
| 1343 | - tlb_reset_dirty_range(&env->tlb_write[0][i], start1, length); | |
| 1350 | + tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length); | |
| 1344 | 1351 | for(i = 0; i < CPU_TLB_SIZE; i++) |
| 1345 | - tlb_reset_dirty_range(&env->tlb_write[1][i], start1, length); | |
| 1352 | + tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length); | |
| 1346 | 1353 | } |
| 1347 | 1354 | |
| 1348 | 1355 | #if !defined(CONFIG_SOFTMMU) |
| ... | ... | @@ -1378,11 +1385,11 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry) |
| 1378 | 1385 | { |
| 1379 | 1386 | ram_addr_t ram_addr; |
| 1380 | 1387 | |
| 1381 | - if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { | |
| 1382 | - ram_addr = (tlb_entry->address & TARGET_PAGE_MASK) + | |
| 1388 | + if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) { | |
| 1389 | + ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + | |
| 1383 | 1390 | tlb_entry->addend - (unsigned long)phys_ram_base; |
| 1384 | 1391 | if (!cpu_physical_memory_is_dirty(ram_addr)) { |
| 1385 | - tlb_entry->address |= IO_MEM_NOTDIRTY; | |
| 1392 | + tlb_entry->addr_write |= IO_MEM_NOTDIRTY; | |
| 1386 | 1393 | } |
| 1387 | 1394 | } |
| 1388 | 1395 | } |
| ... | ... | @@ -1392,19 +1399,19 @@ void cpu_tlb_update_dirty(CPUState *env) |
| 1392 | 1399 | { |
| 1393 | 1400 | int i; |
| 1394 | 1401 | for(i = 0; i < CPU_TLB_SIZE; i++) |
| 1395 | - tlb_update_dirty(&env->tlb_write[0][i]); | |
| 1402 | + tlb_update_dirty(&env->tlb_table[0][i]); | |
| 1396 | 1403 | for(i = 0; i < CPU_TLB_SIZE; i++) |
| 1397 | - tlb_update_dirty(&env->tlb_write[1][i]); | |
| 1404 | + tlb_update_dirty(&env->tlb_table[1][i]); | |
| 1398 | 1405 | } |
| 1399 | 1406 | |
| 1400 | 1407 | static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, |
| 1401 | 1408 | unsigned long start) |
| 1402 | 1409 | { |
| 1403 | 1410 | unsigned long addr; |
| 1404 | - if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) { | |
| 1405 | - addr = (tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend; | |
| 1411 | + if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) { | |
| 1412 | + addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend; | |
| 1406 | 1413 | if (addr == start) { |
| 1407 | - tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_RAM; | |
| 1414 | + tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_RAM; | |
| 1408 | 1415 | } |
| 1409 | 1416 | } |
| 1410 | 1417 | } |
| ... | ... | @@ -1418,17 +1425,17 @@ static inline void tlb_set_dirty(CPUState *env, |
| 1418 | 1425 | |
| 1419 | 1426 | addr &= TARGET_PAGE_MASK; |
| 1420 | 1427 | i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 1421 | - tlb_set_dirty1(&env->tlb_write[0][i], addr); | |
| 1422 | - tlb_set_dirty1(&env->tlb_write[1][i], addr); | |
| 1428 | + tlb_set_dirty1(&env->tlb_table[0][i], addr); | |
| 1429 | + tlb_set_dirty1(&env->tlb_table[1][i], addr); | |
| 1423 | 1430 | } |
| 1424 | 1431 | |
| 1425 | 1432 | /* add a new TLB entry. At most one entry for a given virtual address |
| 1426 | 1433 | is permitted. Return 0 if OK or 2 if the page could not be mapped |
| 1427 | 1434 | (can only happen in non SOFTMMU mode for I/O pages or pages |
| 1428 | 1435 | conflicting with the host address space). */ |
| 1429 | -int tlb_set_page(CPUState *env, target_ulong vaddr, | |
| 1430 | - target_phys_addr_t paddr, int prot, | |
| 1431 | - int is_user, int is_softmmu) | |
| 1436 | +int tlb_set_page_exec(CPUState *env, target_ulong vaddr, | |
| 1437 | + target_phys_addr_t paddr, int prot, | |
| 1438 | + int is_user, int is_softmmu) | |
| 1432 | 1439 | { |
| 1433 | 1440 | PhysPageDesc *p; |
| 1434 | 1441 | unsigned long pd; |
| ... | ... | @@ -1436,6 +1443,7 @@ int tlb_set_page(CPUState *env, target_ulong vaddr, |
| 1436 | 1443 | target_ulong address; |
| 1437 | 1444 | target_phys_addr_t addend; |
| 1438 | 1445 | int ret; |
| 1446 | + CPUTLBEntry *te; | |
| 1439 | 1447 | |
| 1440 | 1448 | p = phys_page_find(paddr >> TARGET_PAGE_BITS); |
| 1441 | 1449 | if (!p) { |
| ... | ... | @@ -1445,7 +1453,7 @@ int tlb_set_page(CPUState *env, target_ulong vaddr, |
| 1445 | 1453 | } |
| 1446 | 1454 | #if defined(DEBUG_TLB) |
| 1447 | 1455 | printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n", |
| 1448 | - vaddr, paddr, prot, is_user, is_softmmu, pd); | |
| 1456 | + vaddr, (int)paddr, prot, is_user, is_softmmu, pd); | |
| 1449 | 1457 | #endif |
| 1450 | 1458 | |
| 1451 | 1459 | ret = 0; |
| ... | ... | @@ -1465,29 +1473,30 @@ int tlb_set_page(CPUState *env, target_ulong vaddr, |
| 1465 | 1473 | |
| 1466 | 1474 | index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 1467 | 1475 | addend -= vaddr; |
| 1476 | + te = &env->tlb_table[is_user][index]; | |
| 1477 | + te->addend = addend; | |
| 1468 | 1478 | if (prot & PAGE_READ) { |
| 1469 | - env->tlb_read[is_user][index].address = address; | |
| 1470 | - env->tlb_read[is_user][index].addend = addend; | |
| 1479 | + te->addr_read = address; | |
| 1480 | + } else { | |
| 1481 | + te->addr_read = -1; | |
| 1482 | + } | |
| 1483 | + if (prot & PAGE_EXEC) { | |
| 1484 | + te->addr_code = address; | |
| 1471 | 1485 | } else { |
| 1472 | - env->tlb_read[is_user][index].address = -1; | |
| 1473 | - env->tlb_read[is_user][index].addend = -1; | |
| 1486 | + te->addr_code = -1; | |
| 1474 | 1487 | } |
| 1475 | 1488 | if (prot & PAGE_WRITE) { |
| 1476 | 1489 | if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) { |
| 1477 | 1490 | /* ROM: access is ignored (same as unassigned) */ |
| 1478 | - env->tlb_write[is_user][index].address = vaddr | IO_MEM_ROM; | |
| 1479 | - env->tlb_write[is_user][index].addend = addend; | |
| 1491 | + te->addr_write = vaddr | IO_MEM_ROM; | |
| 1480 | 1492 | } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && |
| 1481 | 1493 | !cpu_physical_memory_is_dirty(pd)) { |
| 1482 | - env->tlb_write[is_user][index].address = vaddr | IO_MEM_NOTDIRTY; | |
| 1483 | - env->tlb_write[is_user][index].addend = addend; | |
| 1494 | + te->addr_write = vaddr | IO_MEM_NOTDIRTY; | |
| 1484 | 1495 | } else { |
| 1485 | - env->tlb_write[is_user][index].address = address; | |
| 1486 | - env->tlb_write[is_user][index].addend = addend; | |
| 1496 | + te->addr_write = address; | |
| 1487 | 1497 | } |
| 1488 | 1498 | } else { |
| 1489 | - env->tlb_write[is_user][index].address = -1; | |
| 1490 | - env->tlb_write[is_user][index].addend = -1; | |
| 1499 | + te->addr_write = -1; | |
| 1491 | 1500 | } |
| 1492 | 1501 | } |
| 1493 | 1502 | #if !defined(CONFIG_SOFTMMU) |
| ... | ... | @@ -1586,9 +1595,9 @@ void tlb_flush_page(CPUState *env, target_ulong addr) |
| 1586 | 1595 | { |
| 1587 | 1596 | } |
| 1588 | 1597 | |
| 1589 | -int tlb_set_page(CPUState *env, target_ulong vaddr, | |
| 1590 | - target_phys_addr_t paddr, int prot, | |
| 1591 | - int is_user, int is_softmmu) | |
| 1598 | +int tlb_set_page_exec(CPUState *env, target_ulong vaddr, | |
| 1599 | + target_phys_addr_t paddr, int prot, | |
| 1600 | + int is_user, int is_softmmu) | |
| 1592 | 1601 | { |
| 1593 | 1602 | return 0; |
| 1594 | 1603 | } |
| ... | ... | @@ -2052,6 +2061,41 @@ uint32_t ldl_phys(target_phys_addr_t addr) |
| 2052 | 2061 | return val; |
| 2053 | 2062 | } |
| 2054 | 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 | + | |
| 2055 | 2099 | /* XXX: optimize */ |
| 2056 | 2100 | uint32_t ldub_phys(target_phys_addr_t addr) |
| 2057 | 2101 | { |
| ... | ... | @@ -2068,14 +2112,6 @@ uint32_t lduw_phys(target_phys_addr_t addr) |
| 2068 | 2112 | return tswap16(val); |
| 2069 | 2113 | } |
| 2070 | 2114 | |
| 2071 | -/* XXX: optimize */ | |
| 2072 | -uint64_t ldq_phys(target_phys_addr_t addr) | |
| 2073 | -{ | |
| 2074 | - uint64_t val; | |
| 2075 | - cpu_physical_memory_read(addr, (uint8_t *)&val, 8); | |
| 2076 | - return tswap64(val); | |
| 2077 | -} | |
| 2078 | - | |
| 2079 | 2115 | /* warning: addr must be aligned. The ram page is not masked as dirty |
| 2080 | 2116 | and the code inside is not invalidated. It is useful if the dirty |
| 2081 | 2117 | bits are used to track modified PTEs */ | ... | ... |
softmmu_header.h
| ... | ... | @@ -93,6 +93,11 @@ |
| 93 | 93 | #define RES_TYPE int |
| 94 | 94 | #endif |
| 95 | 95 | |
| 96 | +#if ACCESS_TYPE == 3 | |
| 97 | +#define ADDR_READ addr_code | |
| 98 | +#else | |
| 99 | +#define ADDR_READ addr_read | |
| 100 | +#endif | |
| 96 | 101 | |
| 97 | 102 | DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, |
| 98 | 103 | int is_user); |
| ... | ... | @@ -101,6 +106,8 @@ void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE |
| 101 | 106 | #if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \ |
| 102 | 107 | (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU) |
| 103 | 108 | |
| 109 | +#define CPU_TLB_ENTRY_BITS 4 | |
| 110 | + | |
| 104 | 111 | static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr) |
| 105 | 112 | { |
| 106 | 113 | int res; |
| ... | ... | @@ -120,7 +127,7 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr) |
| 120 | 127 | "movl %%eax, %0\n" |
| 121 | 128 | "jmp 2f\n" |
| 122 | 129 | "1:\n" |
| 123 | - "addl 4(%%edx), %%eax\n" | |
| 130 | + "addl 12(%%edx), %%eax\n" | |
| 124 | 131 | #if DATA_SIZE == 1 |
| 125 | 132 | "movzbl (%%eax), %0\n" |
| 126 | 133 | #elif DATA_SIZE == 2 |
| ... | ... | @@ -133,10 +140,10 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr) |
| 133 | 140 | "2:\n" |
| 134 | 141 | : "=r" (res) |
| 135 | 142 | : "r" (ptr), |
| 136 | - "i" ((CPU_TLB_SIZE - 1) << 3), | |
| 137 | - "i" (TARGET_PAGE_BITS - 3), | |
| 143 | + "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), | |
| 144 | + "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), | |
| 138 | 145 | "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)), |
| 139 | - "m" (*(uint32_t *)offsetof(CPUState, tlb_read[CPU_MEM_INDEX][0].address)), | |
| 146 | + "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)), | |
| 140 | 147 | "i" (CPU_MEM_INDEX), |
| 141 | 148 | "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX)) |
| 142 | 149 | : "%eax", "%ecx", "%edx", "memory", "cc"); |
| ... | ... | @@ -169,7 +176,7 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr) |
| 169 | 176 | #endif |
| 170 | 177 | "jmp 2f\n" |
| 171 | 178 | "1:\n" |
| 172 | - "addl 4(%%edx), %%eax\n" | |
| 179 | + "addl 12(%%edx), %%eax\n" | |
| 173 | 180 | #if DATA_SIZE == 1 |
| 174 | 181 | "movsbl (%%eax), %0\n" |
| 175 | 182 | #elif DATA_SIZE == 2 |
| ... | ... | @@ -180,10 +187,10 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr) |
| 180 | 187 | "2:\n" |
| 181 | 188 | : "=r" (res) |
| 182 | 189 | : "r" (ptr), |
| 183 | - "i" ((CPU_TLB_SIZE - 1) << 3), | |
| 184 | - "i" (TARGET_PAGE_BITS - 3), | |
| 190 | + "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), | |
| 191 | + "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), | |
| 185 | 192 | "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)), |
| 186 | - "m" (*(uint32_t *)offsetof(CPUState, tlb_read[CPU_MEM_INDEX][0].address)), | |
| 193 | + "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)), | |
| 187 | 194 | "i" (CPU_MEM_INDEX), |
| 188 | 195 | "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX)) |
| 189 | 196 | : "%eax", "%ecx", "%edx", "memory", "cc"); |
| ... | ... | @@ -216,7 +223,7 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE |
| 216 | 223 | "popl %%eax\n" |
| 217 | 224 | "jmp 2f\n" |
| 218 | 225 | "1:\n" |
| 219 | - "addl 4(%%edx), %%eax\n" | |
| 226 | + "addl 8(%%edx), %%eax\n" | |
| 220 | 227 | #if DATA_SIZE == 1 |
| 221 | 228 | "movb %b1, (%%eax)\n" |
| 222 | 229 | #elif DATA_SIZE == 2 |
| ... | ... | @@ -232,10 +239,10 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE |
| 232 | 239 | /* NOTE: 'q' would be needed as constraint, but we could not use it |
| 233 | 240 | with T1 ! */ |
| 234 | 241 | "r" (v), |
| 235 | - "i" ((CPU_TLB_SIZE - 1) << 3), | |
| 236 | - "i" (TARGET_PAGE_BITS - 3), | |
| 242 | + "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), | |
| 243 | + "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), | |
| 237 | 244 | "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)), |
| 238 | - "m" (*(uint32_t *)offsetof(CPUState, tlb_write[CPU_MEM_INDEX][0].address)), | |
| 245 | + "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_write)), | |
| 239 | 246 | "i" (CPU_MEM_INDEX), |
| 240 | 247 | "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX)) |
| 241 | 248 | : "%eax", "%ecx", "%edx", "memory", "cc"); |
| ... | ... | @@ -256,11 +263,11 @@ static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr) |
| 256 | 263 | addr = ptr; |
| 257 | 264 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 258 | 265 | is_user = CPU_MEM_INDEX; |
| 259 | - if (__builtin_expect(env->tlb_read[is_user][index].address != | |
| 266 | + if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ != | |
| 260 | 267 | (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) { |
| 261 | 268 | res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user); |
| 262 | 269 | } else { |
| 263 | - physaddr = addr + env->tlb_read[is_user][index].addend; | |
| 270 | + physaddr = addr + env->tlb_table[is_user][index].addend; | |
| 264 | 271 | res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr); |
| 265 | 272 | } |
| 266 | 273 | return res; |
| ... | ... | @@ -277,17 +284,19 @@ static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr) |
| 277 | 284 | addr = ptr; |
| 278 | 285 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 279 | 286 | is_user = CPU_MEM_INDEX; |
| 280 | - if (__builtin_expect(env->tlb_read[is_user][index].address != | |
| 287 | + if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ != | |
| 281 | 288 | (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) { |
| 282 | 289 | res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user); |
| 283 | 290 | } else { |
| 284 | - physaddr = addr + env->tlb_read[is_user][index].addend; | |
| 291 | + physaddr = addr + env->tlb_table[is_user][index].addend; | |
| 285 | 292 | res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr); |
| 286 | 293 | } |
| 287 | 294 | return res; |
| 288 | 295 | } |
| 289 | 296 | #endif |
| 290 | 297 | |
| 298 | +#if ACCESS_TYPE != 3 | |
| 299 | + | |
| 291 | 300 | /* generic store macro */ |
| 292 | 301 | |
| 293 | 302 | static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v) |
| ... | ... | @@ -300,16 +309,20 @@ static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE |
| 300 | 309 | addr = ptr; |
| 301 | 310 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 302 | 311 | is_user = CPU_MEM_INDEX; |
| 303 | - if (__builtin_expect(env->tlb_write[is_user][index].address != | |
| 312 | + if (__builtin_expect(env->tlb_table[is_user][index].addr_write != | |
| 304 | 313 | (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) { |
| 305 | 314 | glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user); |
| 306 | 315 | } else { |
| 307 | - physaddr = addr + env->tlb_write[is_user][index].addend; | |
| 316 | + physaddr = addr + env->tlb_table[is_user][index].addend; | |
| 308 | 317 | glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v); |
| 309 | 318 | } |
| 310 | 319 | } |
| 311 | 320 | |
| 312 | -#endif | |
| 321 | +#endif /* ACCESS_TYPE != 3 */ | |
| 322 | + | |
| 323 | +#endif /* !asm */ | |
| 324 | + | |
| 325 | +#if ACCESS_TYPE != 3 | |
| 313 | 326 | |
| 314 | 327 | #if DATA_SIZE == 8 |
| 315 | 328 | static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr) |
| ... | ... | @@ -355,6 +368,8 @@ static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v) |
| 355 | 368 | } |
| 356 | 369 | #endif /* DATA_SIZE == 4 */ |
| 357 | 370 | |
| 371 | +#endif /* ACCESS_TYPE != 3 */ | |
| 372 | + | |
| 358 | 373 | #undef RES_TYPE |
| 359 | 374 | #undef DATA_TYPE |
| 360 | 375 | #undef DATA_STYPE |
| ... | ... | @@ -363,3 +378,4 @@ static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v) |
| 363 | 378 | #undef DATA_SIZE |
| 364 | 379 | #undef CPU_MEM_INDEX |
| 365 | 380 | #undef MMUSUFFIX |
| 381 | +#undef ADDR_READ | ... | ... |
softmmu_template.h
| ... | ... | @@ -41,8 +41,10 @@ |
| 41 | 41 | |
| 42 | 42 | #ifdef SOFTMMU_CODE_ACCESS |
| 43 | 43 | #define READ_ACCESS_TYPE 2 |
| 44 | +#define ADDR_READ addr_code | |
| 44 | 45 | #else |
| 45 | 46 | #define READ_ACCESS_TYPE 0 |
| 47 | +#define ADDR_READ addr_read | |
| 46 | 48 | #endif |
| 47 | 49 | |
| 48 | 50 | static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, |
| ... | ... | @@ -83,9 +85,9 @@ DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, |
| 83 | 85 | /* XXX: could done more in memory macro in a non portable way */ |
| 84 | 86 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 85 | 87 | redo: |
| 86 | - tlb_addr = env->tlb_read[is_user][index].address; | |
| 88 | + tlb_addr = env->tlb_table[is_user][index].ADDR_READ; | |
| 87 | 89 | if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { |
| 88 | - physaddr = addr + env->tlb_read[is_user][index].addend; | |
| 90 | + physaddr = addr + env->tlb_table[is_user][index].addend; | |
| 89 | 91 | if (tlb_addr & ~TARGET_PAGE_MASK) { |
| 90 | 92 | /* IO access */ |
| 91 | 93 | if ((addr & (DATA_SIZE - 1)) != 0) |
| ... | ... | @@ -122,9 +124,9 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, |
| 122 | 124 | |
| 123 | 125 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 124 | 126 | redo: |
| 125 | - tlb_addr = env->tlb_read[is_user][index].address; | |
| 127 | + tlb_addr = env->tlb_table[is_user][index].ADDR_READ; | |
| 126 | 128 | if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { |
| 127 | - physaddr = addr + env->tlb_read[is_user][index].addend; | |
| 129 | + physaddr = addr + env->tlb_table[is_user][index].addend; | |
| 128 | 130 | if (tlb_addr & ~TARGET_PAGE_MASK) { |
| 129 | 131 | /* IO access */ |
| 130 | 132 | if ((addr & (DATA_SIZE - 1)) != 0) |
| ... | ... | @@ -199,9 +201,9 @@ void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, |
| 199 | 201 | |
| 200 | 202 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 201 | 203 | redo: |
| 202 | - tlb_addr = env->tlb_write[is_user][index].address; | |
| 204 | + tlb_addr = env->tlb_table[is_user][index].addr_write; | |
| 203 | 205 | if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { |
| 204 | - physaddr = addr + env->tlb_write[is_user][index].addend; | |
| 206 | + physaddr = addr + env->tlb_table[is_user][index].addend; | |
| 205 | 207 | if (tlb_addr & ~TARGET_PAGE_MASK) { |
| 206 | 208 | /* IO access */ |
| 207 | 209 | if ((addr & (DATA_SIZE - 1)) != 0) |
| ... | ... | @@ -237,9 +239,9 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, |
| 237 | 239 | |
| 238 | 240 | index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
| 239 | 241 | redo: |
| 240 | - tlb_addr = env->tlb_write[is_user][index].address; | |
| 242 | + tlb_addr = env->tlb_table[is_user][index].addr_write; | |
| 241 | 243 | if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { |
| 242 | - physaddr = addr + env->tlb_write[is_user][index].addend; | |
| 244 | + physaddr = addr + env->tlb_table[is_user][index].addend; | |
| 243 | 245 | if (tlb_addr & ~TARGET_PAGE_MASK) { |
| 244 | 246 | /* IO access */ |
| 245 | 247 | if ((addr & (DATA_SIZE - 1)) != 0) |
| ... | ... | @@ -276,3 +278,4 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, |
| 276 | 278 | #undef SUFFIX |
| 277 | 279 | #undef USUFFIX |
| 278 | 280 | #undef DATA_SIZE |
| 281 | +#undef ADDR_READ | ... | ... |