Commit 7dbe11acd807b7a1566b2fe665333a49f8358de0

Authored by j_mayer
1 parent 578bb252

Handle all MMU models in switches, even if it's just to abort because of lack

of supporting code.
Implement 74xx software TLB model.
Keep 74xx with software TLB disabled, as Linux is not able to handle TLB miss
  on those processors.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3307 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/helper.c
... ... @@ -664,7 +664,8 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
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,7 +731,8 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
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,9 +1094,11 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx,
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,9 +1133,6 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx,
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,6 +1163,7 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
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,6 +1264,9 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
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,6 +1351,19 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
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,13 +1589,31 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
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,6 +1625,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
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,7 +1634,22 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
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,6 +1671,15 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
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,6 +2378,8 @@ static always_inline void powerpc_excp (CPUState *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,6 +2399,8 @@ static always_inline void powerpc_excp (CPUState *env,
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,6 +2455,34 @@ static always_inline void powerpc_excp (CPUState *env,
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;
... ...
target-ppc/op.c
... ... @@ -2025,8 +2025,8 @@ void OPPROTO op_slbie_64 (void)
2025 2025 #endif
2026 2026 #endif
2027 2027  
2028   -/* PowerPC 602/603/755 software TLB load instructions */
2029 2028 #if !defined(CONFIG_USER_ONLY)
  2029 +/* PowerPC 602/603/755 software TLB load instructions */
2030 2030 void OPPROTO op_6xx_tlbld (void)
2031 2031 {
2032 2032 do_load_6xx_tlb(0);
... ... @@ -2038,6 +2038,19 @@ void OPPROTO op_6xx_tlbli (void)
2038 2038 do_load_6xx_tlb(1);
2039 2039 RETURN();
2040 2040 }
  2041 +
  2042 +/* PowerPC 74xx software TLB load instructions */
  2043 +void OPPROTO op_74xx_tlbld (void)
  2044 +{
  2045 + do_load_74xx_tlb(0);
  2046 + RETURN();
  2047 +}
  2048 +
  2049 +void OPPROTO op_74xx_tlbli (void)
  2050 +{
  2051 + do_load_74xx_tlb(1);
  2052 + RETURN();
  2053 +}
2041 2054 #endif
2042 2055  
2043 2056 /* 601 specific */
... ...
target-ppc/op_helper.c
... ... @@ -2363,6 +2363,27 @@ void do_load_6xx_tlb (int is_code)
2363 2363 way, is_code, CMP, RPN);
2364 2364 }
2365 2365  
  2366 +void do_load_74xx_tlb (int is_code)
  2367 +{
  2368 + target_ulong RPN, CMP, EPN;
  2369 + int way;
  2370 +
  2371 + RPN = env->spr[SPR_PTELO];
  2372 + CMP = env->spr[SPR_PTEHI];
  2373 + EPN = env->spr[SPR_TLBMISS] & ~0x3;
  2374 + way = env->spr[SPR_TLBMISS] & 0x3;
  2375 +#if defined (DEBUG_SOFTWARE_TLB)
  2376 + if (loglevel != 0) {
  2377 + fprintf(logfile, "%s: EPN %08lx %08lx PTE0 %08lx PTE1 %08lx way %d\n",
  2378 + __func__, (unsigned long)T0, (unsigned long)EPN,
  2379 + (unsigned long)CMP, (unsigned long)RPN, way);
  2380 + }
  2381 +#endif
  2382 + /* Store this TLB */
  2383 + ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
  2384 + way, is_code, CMP, RPN);
  2385 +}
  2386 +
2366 2387 static target_ulong booke_tlb_to_page_size (int size)
2367 2388 {
2368 2389 return 1024 << (2 * size);
... ...
target-ppc/op_helper.h
... ... @@ -135,6 +135,7 @@ void do_rfid (void);
135 135 void do_hrfid (void);
136 136 #endif
137 137 void do_load_6xx_tlb (int is_code);
  138 +void do_load_74xx_tlb (int is_code);
138 139 #endif
139 140  
140 141 /* POWER / PowerPC 601 specific helpers */
... ...
target-ppc/translate.c
... ... @@ -4299,7 +4299,7 @@ GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
4299 4299  
4300 4300 /* 602 - 603 - G2 TLB management */
4301 4301 /* tlbld */
4302   -GEN_HANDLER(tlbld, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
  4302 +GEN_HANDLER(tlbld_6xx, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
4303 4303 {
4304 4304 #if defined(CONFIG_USER_ONLY)
4305 4305 GEN_EXCP_PRIVOPC(ctx);
... ... @@ -4314,7 +4314,7 @@ GEN_HANDLER(tlbld, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
4314 4314 }
4315 4315  
4316 4316 /* tlbli */
4317   -GEN_HANDLER(tlbli, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
  4317 +GEN_HANDLER(tlbli_6xx, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
4318 4318 {
4319 4319 #if defined(CONFIG_USER_ONLY)
4320 4320 GEN_EXCP_PRIVOPC(ctx);
... ... @@ -4328,6 +4328,37 @@ GEN_HANDLER(tlbli, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
4328 4328 #endif
4329 4329 }
4330 4330  
  4331 +/* 74xx TLB management */
  4332 +/* tlbld */
  4333 +GEN_HANDLER(tlbld_74xx, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
  4334 +{
  4335 +#if defined(CONFIG_USER_ONLY)
  4336 + GEN_EXCP_PRIVOPC(ctx);
  4337 +#else
  4338 + if (unlikely(!ctx->supervisor)) {
  4339 + GEN_EXCP_PRIVOPC(ctx);
  4340 + return;
  4341 + }
  4342 + gen_op_load_gpr_T0(rB(ctx->opcode));
  4343 + gen_op_74xx_tlbld();
  4344 +#endif
  4345 +}
  4346 +
  4347 +/* tlbli */
  4348 +GEN_HANDLER(tlbli_74xx, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
  4349 +{
  4350 +#if defined(CONFIG_USER_ONLY)
  4351 + GEN_EXCP_PRIVOPC(ctx);
  4352 +#else
  4353 + if (unlikely(!ctx->supervisor)) {
  4354 + GEN_EXCP_PRIVOPC(ctx);
  4355 + return;
  4356 + }
  4357 + gen_op_load_gpr_T0(rB(ctx->opcode));
  4358 + gen_op_74xx_tlbli();
  4359 +#endif
  4360 +}
  4361 +
4331 4362 /* POWER instructions not in PowerPC 601 */
4332 4363 /* clf */
4333 4364 GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
... ...