]> xenbits.xensource.com Git - qemu-xen-4.1-testing.git/commitdiff
Handle all MMU models in switches, even if it's just to abort because of lack
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 1 Oct 2007 05:16:57 +0000 (05:16 +0000)
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 1 Oct 2007 05:16:57 +0000 (05:16 +0000)
  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
target-ppc/op.c
target-ppc/op_helper.c
target-ppc/op_helper.h
target-ppc/translate.c

index 66dc7b22a8b72a94e1b741ffb5758defb75509ce..5b0fd09b9c9df627bf7c0124966715aaeca3f865 100644 (file)
@@ -664,7 +664,8 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
     int ret, ret2;
 
 #if defined(TARGET_PPC64)
-    if (env->mmu_model == POWERPC_MMU_64B) {
+    if (env->mmu_model == POWERPC_MMU_64B ||
+        env->mmu_model == POWERPC_MMU_64BRIDGE) {
         ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr);
         if (ret < 0)
             return ret;
@@ -730,7 +731,8 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
             }
             /* Initialize real address with an invalid value */
             ctx->raddr = (target_ulong)-1;
-            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) {
+            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
+                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
                 /* Software TLB search */
                 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
             } else {
@@ -1092,9 +1094,11 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx,
     switch (env->mmu_model) {
     case POWERPC_MMU_32B:
     case POWERPC_MMU_SOFT_6xx:
+    case POWERPC_MMU_SOFT_74xx:
     case POWERPC_MMU_601:
     case POWERPC_MMU_SOFT_4xx:
     case POWERPC_MMU_REAL_4xx:
+    case POWERPC_MMU_BOOKE:
         ctx->prot |= PAGE_WRITE;
         break;
 #if defined(TARGET_PPC64)
@@ -1129,9 +1133,6 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx,
             }
         }
         break;
-    case POWERPC_MMU_BOOKE:
-        ctx->prot |= PAGE_WRITE;
-        break;
     case POWERPC_MMU_BOOKE_FSL:
         /* XXX: TODO */
         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,
         switch (env->mmu_model) {
         case POWERPC_MMU_32B:
         case POWERPC_MMU_SOFT_6xx:
+        case POWERPC_MMU_SOFT_74xx:
             /* Try to find a BAT */
             if (check_BATs)
                 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,
                     env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
                     error_code = 1 << 18;
                     goto tlb_miss;
+                case POWERPC_MMU_SOFT_74xx:
+                    exception = POWERPC_EXCP_IFTLB;
+                    goto tlb_miss_74xx;
                 case POWERPC_MMU_SOFT_4xx:
                 case POWERPC_MMU_SOFT_4xx_Z:
                     exception = POWERPC_EXCP_ITLB;
@@ -1346,6 +1351,19 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                     env->spr[SPR_HASH2] = ctx.pg_addr[1];
                     /* Do not alter DAR nor DSISR */
                     goto out;
+                case POWERPC_MMU_SOFT_74xx:
+                    if (rw == 1) {
+                        exception = POWERPC_EXCP_DSTLB;
+                    } else {
+                        exception = POWERPC_EXCP_DLTLB;
+                    }
+                tlb_miss_74xx:
+                    /* Implement LRU algorithm */
+                    env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
+                        ((env->last_way + 1) & (env->nb_ways - 1));
+                    env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
+                    error_code = ctx.key << 19;
+                    break;
                 case POWERPC_MMU_SOFT_4xx:
                 case POWERPC_MMU_SOFT_4xx_Z:
                     exception = POWERPC_EXCP_DTLB;
@@ -1571,13 +1589,31 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
 {
     switch (env->mmu_model) {
     case POWERPC_MMU_SOFT_6xx:
+    case POWERPC_MMU_SOFT_74xx:
         ppc6xx_tlb_invalidate_all(env);
         break;
     case POWERPC_MMU_SOFT_4xx:
     case POWERPC_MMU_SOFT_4xx_Z:
         ppc4xx_tlb_invalidate_all(env);
         break;
-    default:
+    case POWERPC_MMU_REAL_4xx:
+        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
+        break;
+    case POWERPC_MMU_BOOKE:
+        /* XXX: TODO */
+        cpu_abort(env, "MMU model not implemented\n");
+        break;
+    case POWERPC_MMU_BOOKE_FSL:
+        /* XXX: TODO */
+        cpu_abort(env, "MMU model not implemented\n");
+        break;
+    case POWERPC_MMU_601:
+        /* XXX: TODO */
+        cpu_abort(env, "MMU model not implemented\n");
+        break;
+    case POWERPC_MMU_32B:
+    case POWERPC_MMU_64B:
+    case POWERPC_MMU_64BRIDGE:
         tlb_flush(env, 1);
         break;
     }
@@ -1589,6 +1625,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
     addr &= TARGET_PAGE_MASK;
     switch (env->mmu_model) {
     case POWERPC_MMU_SOFT_6xx:
+    case POWERPC_MMU_SOFT_74xx:
         ppc6xx_tlb_invalidate_virt(env, addr, 0);
         if (env->id_tlbs == 1)
             ppc6xx_tlb_invalidate_virt(env, addr, 1);
@@ -1597,7 +1634,22 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
     case POWERPC_MMU_SOFT_4xx_Z:
         ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
         break;
-    default:
+    case POWERPC_MMU_REAL_4xx:
+        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
+        break;
+    case POWERPC_MMU_BOOKE:
+        /* XXX: TODO */
+        cpu_abort(env, "MMU model not implemented\n");
+        break;
+    case POWERPC_MMU_BOOKE_FSL:
+        /* XXX: TODO */
+        cpu_abort(env, "MMU model not implemented\n");
+        break;
+    case POWERPC_MMU_601:
+        /* XXX: TODO */
+        cpu_abort(env, "MMU model not implemented\n");
+        break;
+    case POWERPC_MMU_32B:
         /* tlbie invalidate TLBs for all segments */
         addr &= ~((target_ulong)-1 << 28);
         /* XXX: this case should be optimized,
@@ -1619,6 +1671,15 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
         tlb_flush_page(env, addr | (0xD << 28));
         tlb_flush_page(env, addr | (0xE << 28));
         tlb_flush_page(env, addr | (0xF << 28));
+        break;
+    case POWERPC_MMU_64B:
+    case POWERPC_MMU_64BRIDGE:
+        /* tlbie invalidate TLBs for all segments */
+        /* XXX: given the fact that there are too many segments to invalidate,
+         *      we just invalidate all TLBs
+         */
+        tlb_flush(env, 1);
+        break;
     }
 #else
     ppc_tlb_invalidate_all(env);
@@ -2317,6 +2378,8 @@ static always_inline void powerpc_excp (CPUState *env,
             goto tlb_miss_tgpr;
         case POWERPC_EXCP_7x5:
             goto tlb_miss;
+        case POWERPC_EXCP_74xx:
+            goto tlb_miss_74xx;
         default:
             cpu_abort(env, "Invalid instruction TLB miss exception\n");
             break;
@@ -2336,6 +2399,8 @@ static always_inline void powerpc_excp (CPUState *env,
             goto tlb_miss_tgpr;
         case POWERPC_EXCP_7x5:
             goto tlb_miss;
+        case POWERPC_EXCP_74xx:
+            goto tlb_miss_74xx;
         default:
             cpu_abort(env, "Invalid data load TLB miss exception\n");
             break;
@@ -2390,6 +2455,34 @@ static always_inline void powerpc_excp (CPUState *env,
             /* Set way using a LRU mechanism */
             msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
             break;
+        case POWERPC_EXCP_74xx:
+        tlb_miss_74xx:
+#if defined (DEBUG_SOFTWARE_TLB)
+            if (loglevel != 0) {
+                const unsigned char *es;
+                target_ulong *miss, *cmp;
+                int en;
+                if (excp == POWERPC_EXCP_IFTLB) {
+                    es = "I";
+                    en = 'I';
+                    miss = &env->spr[SPR_IMISS];
+                    cmp = &env->spr[SPR_ICMP];
+                } else {
+                    if (excp == POWERPC_EXCP_DLTLB)
+                        es = "DL";
+                    else
+                        es = "DS";
+                    en = 'D';
+                    miss = &env->spr[SPR_TLBMISS];
+                    cmp = &env->spr[SPR_PTEHI];
+                }
+                fprintf(logfile, "74xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
+                        " %08x\n",
+                        es, en, *miss, en, *cmp, env->error_code);
+            }
+#endif
+            msr |= env->error_code; /* key bit */
+            break;
         default:
             cpu_abort(env, "Invalid data store TLB miss exception\n");
             break;
index 6ad68eabaabc63d930239072fcce998a5f0290d9..822c267695f9b9c353e14c6fdbec51cdb07a394a 100644 (file)
@@ -2025,8 +2025,8 @@ void OPPROTO op_slbie_64 (void)
 #endif
 #endif
 
-/* PowerPC 602/603/755 software TLB load instructions */
 #if !defined(CONFIG_USER_ONLY)
+/* PowerPC 602/603/755 software TLB load instructions */
 void OPPROTO op_6xx_tlbld (void)
 {
     do_load_6xx_tlb(0);
@@ -2038,6 +2038,19 @@ void OPPROTO op_6xx_tlbli (void)
     do_load_6xx_tlb(1);
     RETURN();
 }
+
+/* PowerPC 74xx software TLB load instructions */
+void OPPROTO op_74xx_tlbld (void)
+{
+    do_load_74xx_tlb(0);
+    RETURN();
+}
+
+void OPPROTO op_74xx_tlbli (void)
+{
+    do_load_74xx_tlb(1);
+    RETURN();
+}
 #endif
 
 /* 601 specific */
index a7c81776fdfc7733043768658872b8eafceefdda..8bb93ed36b7826c59c9c56d341a5f2e9d36fc9db 100644 (file)
@@ -2363,6 +2363,27 @@ void do_load_6xx_tlb (int is_code)
                      way, is_code, CMP, RPN);
 }
 
+void do_load_74xx_tlb (int is_code)
+{
+    target_ulong RPN, CMP, EPN;
+    int way;
+
+    RPN = env->spr[SPR_PTELO];
+    CMP = env->spr[SPR_PTEHI];
+    EPN = env->spr[SPR_TLBMISS] & ~0x3;
+    way = env->spr[SPR_TLBMISS] & 0x3;
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: EPN %08lx %08lx PTE0 %08lx PTE1 %08lx way %d\n",
+                __func__, (unsigned long)T0, (unsigned long)EPN,
+                (unsigned long)CMP, (unsigned long)RPN, way);
+    }
+#endif
+    /* Store this TLB */
+    ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
+                     way, is_code, CMP, RPN);
+}
+
 static target_ulong booke_tlb_to_page_size (int size)
 {
     return 1024 << (2 * size);
index 6f79cad9127e5bb57092dcb353487c83132eabe9..0406682c76be0ad8d548a4e034daf14159cd0a6b 100644 (file)
@@ -135,6 +135,7 @@ void do_rfid (void);
 void do_hrfid (void);
 #endif
 void do_load_6xx_tlb (int is_code);
+void do_load_74xx_tlb (int is_code);
 #endif
 
 /* POWER / PowerPC 601 specific helpers */
index e599243b7348dea5c30bdb65a8f1ed4cc563a216..d8f6e95c9eb621c4cae83a8eb76acd65ee9f587b 100644 (file)
@@ -4299,7 +4299,7 @@ GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
 
 /* 602 - 603 - G2 TLB management */
 /* tlbld */
-GEN_HANDLER(tlbld, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
+GEN_HANDLER(tlbld_6xx, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
 {
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVOPC(ctx);
@@ -4314,7 +4314,7 @@ GEN_HANDLER(tlbld, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
 }
 
 /* tlbli */
-GEN_HANDLER(tlbli, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
+GEN_HANDLER(tlbli_6xx, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
 {
 #if defined(CONFIG_USER_ONLY)
     GEN_EXCP_PRIVOPC(ctx);
@@ -4328,6 +4328,37 @@ GEN_HANDLER(tlbli, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
 #endif
 }
 
+/* 74xx TLB management */
+/* tlbld */
+GEN_HANDLER(tlbld_74xx, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
+{
+#if defined(CONFIG_USER_ONLY)
+    GEN_EXCP_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        GEN_EXCP_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rB(ctx->opcode));
+    gen_op_74xx_tlbld();
+#endif
+}
+
+/* tlbli */
+GEN_HANDLER(tlbli_74xx, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
+{
+#if defined(CONFIG_USER_ONLY)
+    GEN_EXCP_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        GEN_EXCP_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rB(ctx->opcode));
+    gen_op_74xx_tlbli();
+#endif
+}
+
 /* POWER instructions not in PowerPC 601 */
 /* clf */
 GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)