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;
|