]> Git Repo - qemu.git/commitdiff
PowerPC 4xx software driven TLB fixes + debug traces.
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 16 Apr 2007 09:21:46 +0000 (09:21 +0000)
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 16 Apr 2007 09:21:46 +0000 (09:21 +0000)
Add code provision for more MMU models support.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2683 c046a42c-6fe2-441c-8c8c-71466251a162

target-ppc/cpu.h
target-ppc/helper.c
target-ppc/op_helper.c

index 5cd1b6008c670b440da751f0a4524b3dd14558e0..eb3340c52846234198c00cfebaf242003b4fb812 100644 (file)
@@ -581,12 +581,12 @@ struct ppc6xx_tlb_t {
 
 typedef struct ppcemb_tlb_t ppcemb_tlb_t;
 struct ppcemb_tlb_t {
-    target_ulong RPN;
+    target_phys_addr_t RPN;
     target_ulong EPN;
     target_ulong PID;
-    int size;
-    int prot;
-    int attr; /* Storage attributes */
+    target_ulong size;
+    uint32_t prot;
+    uint32_t attr; /* Storage attributes */
 };
 
 union ppc_tlb_t {
@@ -765,10 +765,6 @@ struct CPUPPCState {
     int id_tlbs;     /* If 1, MMU has separated TLBs for instructions & data */
     int nb_pids;     /* Number of available PID registers                    */
     ppc_tlb_t *tlb;  /* TLB is optional. Allocate them only if needed        */
-    /* Callbacks for specific checks on some implementations */
-    int (*tlb_check_more)(CPUPPCState *env, ppc_tlb_t *tlb, int *prot,
-                          target_ulong vaddr, int rw, int acc_type,
-                          int is_user);
     /* 403 dedicated access protection registers */
     target_ulong pb[4];
 
index 5f46ae0fdc6484bdc1ab3733089b109247874155..2fc5ecd12085b7ecfb49d7ece99d833db78a014d 100644 (file)
@@ -657,7 +657,8 @@ int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
     target_ulong mask;
     int i, ret, zsel, zpr;
             
-    ret = -6;
+    ret = -1;
+    raddr = -1;
     for (i = 0; i < env->nb_tlb; i++) {
         tlb = &env->tlb[i].tlbe;
         /* Check valid flag */
@@ -691,8 +692,8 @@ int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
             switch (zpr) {
             case 0x0:
                 if (msr_pr) {
-                    ret = -3;
                     ctx->prot = 0;
+                    ret = -3;
                     break;
                 }
                 /* No break here */
@@ -702,25 +703,26 @@ int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
                 if (!(tlb->prot & PAGE_EXEC)) {
                     ret = -3;
                 } else {
-                    if (tlb->prot & PAGE_WRITE)
+                    if (tlb->prot & PAGE_WRITE) {
                         ctx->prot = PAGE_READ | PAGE_WRITE;
-                    else
+                    } else {
                         ctx->prot = PAGE_READ;
+                    }
                     ret = 0;
                 }
                 break;
             case 0x3:
                 /* All accesses granted */
-                ret = 0;
                 ctx->prot = PAGE_READ | PAGE_WRITE;
+                ret = 0;
                 break;
             }
         } else {
             switch (zpr) {
             case 0x0:
                 if (msr_pr) {
-                    ret = -2;
                     ctx->prot = 0;
+                    ret = -2;
                     break;
                 }
                 /* No break here */
@@ -728,20 +730,21 @@ int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
             case 0x2:
                 /* Check from TLB entry */
                 /* Check write protection bit */
-                if (rw && !(tlb->prot & PAGE_WRITE)) {
-                    ret = -2;
+                if (tlb->prot & PAGE_WRITE) {
+                    ctx->prot = PAGE_READ | PAGE_WRITE;
+                    ret = 0;
                 } else {
-                    ret = 2;
-                    if (tlb->prot & PAGE_WRITE)
-                        ctx->prot = PAGE_READ | PAGE_WRITE;
+                    ctx->prot = PAGE_READ;
+                    if (rw)
+                        ret = -2;
                     else
-                        ctx->prot = PAGE_READ;
+                        ret = 0;
                 }
                 break;
             case 0x3:
                 /* All accesses granted */
-                ret = 2;
                 ctx->prot = PAGE_READ | PAGE_WRITE;
+                ret = 0;
                 break;
             }
         }
@@ -749,11 +752,17 @@ int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
             ctx->raddr = raddr;
             if (loglevel) {
                 fprintf(logfile, "%s: access granted " ADDRX " => " REGX
-                        " %d\n", __func__, address, ctx->raddr, ctx->prot);
+                        " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
+                        ret);
             }
-            return i;
+            return 0;
         }
     }
+    if (loglevel) {
+        fprintf(logfile, "%s: access refused " ADDRX " => " REGX
+                " %d %d\n", __func__, address, raddr, ctx->prot,
+                ret);
+    }
     
     return ret;
 }
@@ -808,32 +817,49 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
         /* No address translation */
         ret = check_physical(env, ctx, eaddr, rw);
     } else {
+        ret = -1;
         switch (PPC_MMU(env)) {
         case PPC_FLAGS_MMU_32B:
         case PPC_FLAGS_MMU_SOFT_6xx:
             /* Try to find a BAT */
-            ret = -1;
             if (check_BATs)
                 ret = get_bat(env, ctx, eaddr, rw, access_type);
+            /* No break here */
+#if defined(TARGET_PPC64)
+        case PPC_FLAGS_MMU_64B:
+        case PPC_FLAGS_MMU_64BRIDGE:
+#endif
             if (ret < 0) {
-                /* We didn't match any BAT entry */
+                /* We didn't match any BAT entry or don't have BATs */
                 ret = get_segment(env, ctx, eaddr, rw, access_type);
             }
             break;
         case PPC_FLAGS_MMU_SOFT_4xx:
+        case PPC_FLAGS_MMU_403:
             ret = mmu4xx_get_physical_address(env, ctx, eaddr,
                                               rw, access_type);
             break;
-        default:
+        case PPC_FLAGS_MMU_601:
+            /* XXX: TODO */
+            cpu_abort(env, "601 MMU model not implemented\n");
+            return -1;
+        case PPC_FLAGS_MMU_BOOKE:
             /* XXX: TODO */
-            cpu_abort(env, "MMU model not implemented\n");
+            cpu_abort(env, "BookeE MMU model not implemented\n");
+            return -1;
+        case PPC_FLAGS_MMU_BOOKE_FSL:
+            /* XXX: TODO */
+            cpu_abort(env, "BookE FSL MMU model not implemented\n");
+            return -1;
+        default:
+            cpu_abort(env, "Unknown or invalid MMU model\n");
             return -1;
         }
     }
 #if 0
     if (loglevel > 0) {
-        fprintf(logfile, "%s address " ADDRX " => " ADDRX "\n",
-                __func__, eaddr, ctx->raddr);
+        fprintf(logfile, "%s address " ADDRX " => %d " ADDRX "\n",
+                __func__, eaddr, ret, ctx->raddr);
     }
 #endif
 
@@ -885,19 +911,48 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
             switch (ret) {
             case -1:
                 /* No matches in page tables or TLB */
-                if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
+                switch (PPC_MMU(env)) {
+                case PPC_FLAGS_MMU_SOFT_6xx:
                     exception = EXCP_I_TLBMISS;
                     env->spr[SPR_IMISS] = address;
                     env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
                     error_code = 1 << 18;
                     goto tlb_miss;
-                } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
+                case PPC_FLAGS_MMU_SOFT_4xx:
+                case PPC_FLAGS_MMU_403:
                     exception = EXCP_40x_ITLBMISS;
                     error_code = 0;
                     env->spr[SPR_40x_DEAR] = address;
                     env->spr[SPR_40x_ESR] = 0x00000000;
-                } else {
+                    break;
+                case PPC_FLAGS_MMU_32B:
                     error_code = 0x40000000;
+                    break;
+#if defined(TARGET_PPC64)
+                case PPC_FLAGS_MMU_64B:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                case PPC_FLAGS_MMU_64BRIDGE:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+#endif
+                case PPC_FLAGS_MMU_601:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                case PPC_FLAGS_MMU_BOOKE:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                case PPC_FLAGS_MMU_BOOKE_FSL:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                default:
+                    cpu_abort(env, "Unknown or invalid MMU model\n");
+                    return -1;
                 }
                 break;
             case -2:
@@ -924,7 +979,8 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
             switch (ret) {
             case -1:
                 /* No matches in page tables or TLB */
-                if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
+                switch (PPC_MMU(env)) {
+                case PPC_FLAGS_MMU_SOFT_6xx:
                     if (rw == 1) {
                         exception = EXCP_DS_TLBMISS;
                         error_code = 1 << 16;
@@ -940,7 +996,8 @@ 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;
-                } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
+                case PPC_FLAGS_MMU_SOFT_4xx:
+                case PPC_FLAGS_MMU_403:
                     exception = EXCP_40x_DTLBMISS;
                     error_code = 0;
                     env->spr[SPR_40x_DEAR] = address;
@@ -948,8 +1005,35 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                         env->spr[SPR_40x_ESR] = 0x00800000;
                     else
                         env->spr[SPR_40x_ESR] = 0x00000000;
-                } else {
+                    break;
+                case PPC_FLAGS_MMU_32B:
                     error_code = 0x40000000;
+                    break;
+#if defined(TARGET_PPC64)
+                case PPC_FLAGS_MMU_64B:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                case PPC_FLAGS_MMU_64BRIDGE:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+#endif
+                case PPC_FLAGS_MMU_601:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                case PPC_FLAGS_MMU_BOOKE:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                case PPC_FLAGS_MMU_BOOKE_FSL:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                default:
+                    cpu_abort(env, "Unknown or invalid MMU model\n");
+                    return -1;
                 }
                 break;
             case -2:
index 590b31e725eafd8d8fb7c4944ba8d2b233e58d8c..e994486cf5e69a1079e8f4d4ec931241ff1fdd52 100644 (file)
@@ -2537,39 +2537,72 @@ void do_4xx_tlbsx_ (void)
     env->crf[0] = tmp;
 }
 
-void do_4xx_tlbwe_lo (void)
+void do_4xx_tlbwe_hi (void)
 {
     ppcemb_tlb_t *tlb;
     target_ulong page, end;
 
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel) {
+        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
+    }
+#endif
     T0 &= 0x3F;
     tlb = &env->tlb[T0].tlbe;
     /* Invalidate previous TLB (if it's valid) */
     if (tlb->prot & PAGE_VALID) {
         end = tlb->EPN + tlb->size;
+#if defined (DEBUG_SOFTWARE_TLB)
+        if (loglevel) {
+            fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
+                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
+        }
+#endif
         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
             tlb_flush_page(env, page);
     }
     tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
     tlb->EPN = (T1 & 0xFFFFFC00) & ~(tlb->size - 1);
-    if (T1 & 0x400)
+    if (T1 & 0x40)
         tlb->prot |= PAGE_VALID;
     else
         tlb->prot &= ~PAGE_VALID;
-    tlb->PID = env->spr[SPR_BOOKE_PID]; /* PID */
+    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
     tlb->attr = T1 & 0xFF;
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel) {
+        fprintf(logfile, "%s: set up TLB %d RPN " ADDRX " EPN " ADDRX
+                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
+                (int)T0, tlb->RPN, tlb->EPN, tlb->size, 
+                tlb->prot & PAGE_READ ? 'r' : '-',
+                tlb->prot & PAGE_WRITE ? 'w' : '-',
+                tlb->prot & PAGE_EXEC ? 'x' : '-',
+                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
+    }
+#endif
     /* Invalidate new TLB (if valid) */
     if (tlb->prot & PAGE_VALID) {
         end = tlb->EPN + tlb->size;
+#if defined (DEBUG_SOFTWARE_TLB)
+        if (loglevel) {
+            fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
+                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
+        }
+#endif
         for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
             tlb_flush_page(env, page);
     }
 }
 
-void do_4xx_tlbwe_hi (void)
+void do_4xx_tlbwe_lo (void)
 {
     ppcemb_tlb_t *tlb;
 
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel) {
+        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
+    }
+#endif
     T0 &= 0x3F;
     tlb = &env->tlb[T0].tlbe;
     tlb->RPN = T1 & 0xFFFFFC00;
@@ -2578,5 +2611,16 @@ void do_4xx_tlbwe_hi (void)
         tlb->prot |= PAGE_EXEC;
     if (T1 & 0x100)
         tlb->prot |= PAGE_WRITE;
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel) {
+        fprintf(logfile, "%s: set up TLB %d RPN " ADDRX " EPN " ADDRX
+                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
+                (int)T0, tlb->RPN, tlb->EPN, tlb->size, 
+                tlb->prot & PAGE_READ ? 'r' : '-',
+                tlb->prot & PAGE_WRITE ? 'w' : '-',
+                tlb->prot & PAGE_EXEC ? 'x' : '-',
+                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
+    }
+#endif
 }
 #endif /* !CONFIG_USER_ONLY */
This page took 0.050039 seconds and 4 git commands to generate.