Revision 7dbe11ac target-ppc/helper.c
b/target-ppc/helper.c | ||
---|---|---|
664 | 664 |
int ret, ret2; |
665 | 665 |
|
666 | 666 |
#if defined(TARGET_PPC64) |
667 |
if (env->mmu_model == POWERPC_MMU_64B) { |
|
667 |
if (env->mmu_model == POWERPC_MMU_64B || |
|
668 |
env->mmu_model == POWERPC_MMU_64BRIDGE) { |
|
668 | 669 |
ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr); |
669 | 670 |
if (ret < 0) |
670 | 671 |
return ret; |
... | ... | |
730 | 731 |
} |
731 | 732 |
/* Initialize real address with an invalid value */ |
732 | 733 |
ctx->raddr = (target_ulong)-1; |
733 |
if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) { |
|
734 |
if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx || |
|
735 |
env->mmu_model == POWERPC_MMU_SOFT_74xx)) { |
|
734 | 736 |
/* Software TLB search */ |
735 | 737 |
ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type); |
736 | 738 |
} else { |
... | ... | |
1092 | 1094 |
switch (env->mmu_model) { |
1093 | 1095 |
case POWERPC_MMU_32B: |
1094 | 1096 |
case POWERPC_MMU_SOFT_6xx: |
1097 |
case POWERPC_MMU_SOFT_74xx: |
|
1095 | 1098 |
case POWERPC_MMU_601: |
1096 | 1099 |
case POWERPC_MMU_SOFT_4xx: |
1097 | 1100 |
case POWERPC_MMU_REAL_4xx: |
1101 |
case POWERPC_MMU_BOOKE: |
|
1098 | 1102 |
ctx->prot |= PAGE_WRITE; |
1099 | 1103 |
break; |
1100 | 1104 |
#if defined(TARGET_PPC64) |
... | ... | |
1129 | 1133 |
} |
1130 | 1134 |
} |
1131 | 1135 |
break; |
1132 |
case POWERPC_MMU_BOOKE: |
|
1133 |
ctx->prot |= PAGE_WRITE; |
|
1134 |
break; |
|
1135 | 1136 |
case POWERPC_MMU_BOOKE_FSL: |
1136 | 1137 |
/* XXX: TODO */ |
1137 | 1138 |
cpu_abort(env, "BookE FSL MMU model not implemented\n"); |
... | ... | |
1162 | 1163 |
switch (env->mmu_model) { |
1163 | 1164 |
case POWERPC_MMU_32B: |
1164 | 1165 |
case POWERPC_MMU_SOFT_6xx: |
1166 |
case POWERPC_MMU_SOFT_74xx: |
|
1165 | 1167 |
/* Try to find a BAT */ |
1166 | 1168 |
if (check_BATs) |
1167 | 1169 |
ret = get_bat(env, ctx, eaddr, rw, access_type); |
... | ... | |
1262 | 1264 |
env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem; |
1263 | 1265 |
error_code = 1 << 18; |
1264 | 1266 |
goto tlb_miss; |
1267 |
case POWERPC_MMU_SOFT_74xx: |
|
1268 |
exception = POWERPC_EXCP_IFTLB; |
|
1269 |
goto tlb_miss_74xx; |
|
1265 | 1270 |
case POWERPC_MMU_SOFT_4xx: |
1266 | 1271 |
case POWERPC_MMU_SOFT_4xx_Z: |
1267 | 1272 |
exception = POWERPC_EXCP_ITLB; |
... | ... | |
1346 | 1351 |
env->spr[SPR_HASH2] = ctx.pg_addr[1]; |
1347 | 1352 |
/* Do not alter DAR nor DSISR */ |
1348 | 1353 |
goto out; |
1354 |
case POWERPC_MMU_SOFT_74xx: |
|
1355 |
if (rw == 1) { |
|
1356 |
exception = POWERPC_EXCP_DSTLB; |
|
1357 |
} else { |
|
1358 |
exception = POWERPC_EXCP_DLTLB; |
|
1359 |
} |
|
1360 |
tlb_miss_74xx: |
|
1361 |
/* Implement LRU algorithm */ |
|
1362 |
env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) | |
|
1363 |
((env->last_way + 1) & (env->nb_ways - 1)); |
|
1364 |
env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem; |
|
1365 |
error_code = ctx.key << 19; |
|
1366 |
break; |
|
1349 | 1367 |
case POWERPC_MMU_SOFT_4xx: |
1350 | 1368 |
case POWERPC_MMU_SOFT_4xx_Z: |
1351 | 1369 |
exception = POWERPC_EXCP_DTLB; |
... | ... | |
1571 | 1589 |
{ |
1572 | 1590 |
switch (env->mmu_model) { |
1573 | 1591 |
case POWERPC_MMU_SOFT_6xx: |
1592 |
case POWERPC_MMU_SOFT_74xx: |
|
1574 | 1593 |
ppc6xx_tlb_invalidate_all(env); |
1575 | 1594 |
break; |
1576 | 1595 |
case POWERPC_MMU_SOFT_4xx: |
1577 | 1596 |
case POWERPC_MMU_SOFT_4xx_Z: |
1578 | 1597 |
ppc4xx_tlb_invalidate_all(env); |
1579 | 1598 |
break; |
1580 |
default: |
|
1599 |
case POWERPC_MMU_REAL_4xx: |
|
1600 |
cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n"); |
|
1601 |
break; |
|
1602 |
case POWERPC_MMU_BOOKE: |
|
1603 |
/* XXX: TODO */ |
|
1604 |
cpu_abort(env, "MMU model not implemented\n"); |
|
1605 |
break; |
|
1606 |
case POWERPC_MMU_BOOKE_FSL: |
|
1607 |
/* XXX: TODO */ |
|
1608 |
cpu_abort(env, "MMU model not implemented\n"); |
|
1609 |
break; |
|
1610 |
case POWERPC_MMU_601: |
|
1611 |
/* XXX: TODO */ |
|
1612 |
cpu_abort(env, "MMU model not implemented\n"); |
|
1613 |
break; |
|
1614 |
case POWERPC_MMU_32B: |
|
1615 |
case POWERPC_MMU_64B: |
|
1616 |
case POWERPC_MMU_64BRIDGE: |
|
1581 | 1617 |
tlb_flush(env, 1); |
1582 | 1618 |
break; |
1583 | 1619 |
} |
... | ... | |
1589 | 1625 |
addr &= TARGET_PAGE_MASK; |
1590 | 1626 |
switch (env->mmu_model) { |
1591 | 1627 |
case POWERPC_MMU_SOFT_6xx: |
1628 |
case POWERPC_MMU_SOFT_74xx: |
|
1592 | 1629 |
ppc6xx_tlb_invalidate_virt(env, addr, 0); |
1593 | 1630 |
if (env->id_tlbs == 1) |
1594 | 1631 |
ppc6xx_tlb_invalidate_virt(env, addr, 1); |
... | ... | |
1597 | 1634 |
case POWERPC_MMU_SOFT_4xx_Z: |
1598 | 1635 |
ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]); |
1599 | 1636 |
break; |
1600 |
default: |
|
1637 |
case POWERPC_MMU_REAL_4xx: |
|
1638 |
cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n"); |
|
1639 |
break; |
|
1640 |
case POWERPC_MMU_BOOKE: |
|
1641 |
/* XXX: TODO */ |
|
1642 |
cpu_abort(env, "MMU model not implemented\n"); |
|
1643 |
break; |
|
1644 |
case POWERPC_MMU_BOOKE_FSL: |
|
1645 |
/* XXX: TODO */ |
|
1646 |
cpu_abort(env, "MMU model not implemented\n"); |
|
1647 |
break; |
|
1648 |
case POWERPC_MMU_601: |
|
1649 |
/* XXX: TODO */ |
|
1650 |
cpu_abort(env, "MMU model not implemented\n"); |
|
1651 |
break; |
|
1652 |
case POWERPC_MMU_32B: |
|
1601 | 1653 |
/* tlbie invalidate TLBs for all segments */ |
1602 | 1654 |
addr &= ~((target_ulong)-1 << 28); |
1603 | 1655 |
/* XXX: this case should be optimized, |
... | ... | |
1619 | 1671 |
tlb_flush_page(env, addr | (0xD << 28)); |
1620 | 1672 |
tlb_flush_page(env, addr | (0xE << 28)); |
1621 | 1673 |
tlb_flush_page(env, addr | (0xF << 28)); |
1674 |
break; |
|
1675 |
case POWERPC_MMU_64B: |
|
1676 |
case POWERPC_MMU_64BRIDGE: |
|
1677 |
/* tlbie invalidate TLBs for all segments */ |
|
1678 |
/* XXX: given the fact that there are too many segments to invalidate, |
|
1679 |
* we just invalidate all TLBs |
|
1680 |
*/ |
|
1681 |
tlb_flush(env, 1); |
|
1682 |
break; |
|
1622 | 1683 |
} |
1623 | 1684 |
#else |
1624 | 1685 |
ppc_tlb_invalidate_all(env); |
... | ... | |
2317 | 2378 |
goto tlb_miss_tgpr; |
2318 | 2379 |
case POWERPC_EXCP_7x5: |
2319 | 2380 |
goto tlb_miss; |
2381 |
case POWERPC_EXCP_74xx: |
|
2382 |
goto tlb_miss_74xx; |
|
2320 | 2383 |
default: |
2321 | 2384 |
cpu_abort(env, "Invalid instruction TLB miss exception\n"); |
2322 | 2385 |
break; |
... | ... | |
2336 | 2399 |
goto tlb_miss_tgpr; |
2337 | 2400 |
case POWERPC_EXCP_7x5: |
2338 | 2401 |
goto tlb_miss; |
2402 |
case POWERPC_EXCP_74xx: |
|
2403 |
goto tlb_miss_74xx; |
|
2339 | 2404 |
default: |
2340 | 2405 |
cpu_abort(env, "Invalid data load TLB miss exception\n"); |
2341 | 2406 |
break; |
... | ... | |
2390 | 2455 |
/* Set way using a LRU mechanism */ |
2391 | 2456 |
msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; |
2392 | 2457 |
break; |
2458 |
case POWERPC_EXCP_74xx: |
|
2459 |
tlb_miss_74xx: |
|
2460 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
2461 |
if (loglevel != 0) { |
|
2462 |
const unsigned char *es; |
|
2463 |
target_ulong *miss, *cmp; |
|
2464 |
int en; |
|
2465 |
if (excp == POWERPC_EXCP_IFTLB) { |
|
2466 |
es = "I"; |
|
2467 |
en = 'I'; |
|
2468 |
miss = &env->spr[SPR_IMISS]; |
|
2469 |
cmp = &env->spr[SPR_ICMP]; |
|
2470 |
} else { |
|
2471 |
if (excp == POWERPC_EXCP_DLTLB) |
|
2472 |
es = "DL"; |
|
2473 |
else |
|
2474 |
es = "DS"; |
|
2475 |
en = 'D'; |
|
2476 |
miss = &env->spr[SPR_TLBMISS]; |
|
2477 |
cmp = &env->spr[SPR_PTEHI]; |
|
2478 |
} |
|
2479 |
fprintf(logfile, "74xx %sTLB miss: %cM " ADDRX " %cC " ADDRX |
|
2480 |
" %08x\n", |
|
2481 |
es, en, *miss, en, *cmp, env->error_code); |
|
2482 |
} |
|
2483 |
#endif |
|
2484 |
msr |= env->error_code; /* key bit */ |
|
2485 |
break; |
|
2393 | 2486 |
default: |
2394 | 2487 |
cpu_abort(env, "Invalid data store TLB miss exception\n"); |
2395 | 2488 |
break; |
Also available in: Unified diff