PowerPC 620 MMU do not have the same exact behavior as standard
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 19 Nov 2007 11:41:10 +0000 (11:41 +0000)
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 19 Nov 2007 11:41:10 +0000 (11:41 +0000)
  64 bits PowerPC ones.

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

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

index d2faf61e8e3748cbfb75eac4b95061e00b650f69..6f3ff86a1c5a24227144178ddde86462fd959e7b 100644 (file)
@@ -93,30 +93,33 @@ typedef uint32_t ppc_gpr_t;
 /* MMU model                                                                 */
 typedef enum powerpc_mmu_t powerpc_mmu_t;
 enum powerpc_mmu_t {
-    POWERPC_MMU_UNKNOWN    = 0,
+    POWERPC_MMU_UNKNOWN    = 0x00000000,
     /* Standard 32 bits PowerPC MMU                            */
-    POWERPC_MMU_32B,
+    POWERPC_MMU_32B        = 0x00000001,
     /* PowerPC 6xx MMU with software TLB                       */
-    POWERPC_MMU_SOFT_6xx,
+    POWERPC_MMU_SOFT_6xx   = 0x00000002,
     /* PowerPC 74xx MMU with software TLB                      */
-    POWERPC_MMU_SOFT_74xx,
+    POWERPC_MMU_SOFT_74xx  = 0x00000003,
     /* PowerPC 4xx MMU with software TLB                       */
-    POWERPC_MMU_SOFT_4xx,
+    POWERPC_MMU_SOFT_4xx   = 0x00000004,
     /* PowerPC 4xx MMU with software TLB and zones protections */
-    POWERPC_MMU_SOFT_4xx_Z,
+    POWERPC_MMU_SOFT_4xx_Z = 0x00000005,
     /* PowerPC MMU in real mode only                           */
-    POWERPC_MMU_REAL,
+    POWERPC_MMU_REAL       = 0x00000006,
     /* Freescale MPC8xx MMU model                              */
-    POWERPC_MMU_MPC8xx,
+    POWERPC_MMU_MPC8xx     = 0x00000007,
     /* BookE MMU model                                         */
-    POWERPC_MMU_BOOKE,
+    POWERPC_MMU_BOOKE      = 0x00000008,
     /* BookE FSL MMU model                                     */
-    POWERPC_MMU_BOOKE_FSL,
+    POWERPC_MMU_BOOKE_FSL  = 0x00000009,
     /* PowerPC 601 MMU model (specific BATs format)            */
-    POWERPC_MMU_601,
+    POWERPC_MMU_601        = 0x0000000A,
 #if defined(TARGET_PPC64)
+#define POWERPC_MMU_64       0x00010000
     /* 64 bits PowerPC MMU                                     */
-    POWERPC_MMU_64B,
+    POWERPC_MMU_64B        = POWERPC_MMU_64 | 0x00000001,
+    /* 620 variant (no segment exceptions)                     */
+    POWERPC_MMU_620        = POWERPC_MMU_64 | 0x00000002,
 #endif /* defined(TARGET_PPC64) */
 };
 
index b4c38395f51a00a1d5285fd913911c314245fb44..cb9b778cc74e1246998f7951400996db1076723a 100644 (file)
@@ -706,7 +706,7 @@ static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx,
                                    int h, int rw, int type)
 {
 #if defined(TARGET_PPC64)
-    if (env->mmu_model == POWERPC_MMU_64B)
+    if (env->mmu_model & POWERPC_MMU_64)
         return find_pte64(ctx, h, rw, type);
 #endif
 
@@ -916,7 +916,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
 
     pr = msr_pr;
 #if defined(TARGET_PPC64)
-    if (env->mmu_model == POWERPC_MMU_64B) {
+    if (env->mmu_model & POWERPC_MMU_64) {
 #if defined (DEBUG_MMU)
         if (loglevel != 0) {
             fprintf(logfile, "Check SLBs\n");
@@ -973,7 +973,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
             sdr = env->sdr1;
             pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;
 #if defined(TARGET_PPC64)
-            if (env->mmu_model == POWERPC_MMU_64B) {
+            if (env->mmu_model & POWERPC_MMU_64) {
                 htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
                 /* XXX: this is false for 1 TB segments */
                 hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
@@ -1002,7 +1002,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
 #endif
             ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
 #if defined(TARGET_PPC64)
-            if (env->mmu_model == POWERPC_MMU_64B) {
+            if (env->mmu_model & POWERPC_MMU_64) {
                 /* Only 5 bits of the page index are used in the AVPN */
                 ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
             } else
@@ -1362,6 +1362,7 @@ static always_inline int check_physical (CPUState *env, mmu_ctx_t *ctx,
         ctx->prot |= PAGE_WRITE;
         break;
 #if defined(TARGET_PPC64)
+    case POWERPC_MMU_620:
     case POWERPC_MMU_64B:
         /* Real address are 60 bits long */
         ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
@@ -1430,6 +1431,7 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
         case POWERPC_MMU_SOFT_6xx:
         case POWERPC_MMU_SOFT_74xx:
 #if defined(TARGET_PPC64)
+        case POWERPC_MMU_620:
         case POWERPC_MMU_64B:
 #endif
             /* Try to find a BAT */
@@ -1538,6 +1540,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                 case POWERPC_MMU_32B:
                 case POWERPC_MMU_601:
 #if defined(TARGET_PPC64)
+                case POWERPC_MMU_620:
                 case POWERPC_MMU_64B:
 #endif
                     env->exception_index = POWERPC_EXCP_ISI;
@@ -1583,8 +1586,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 #if defined(TARGET_PPC64)
             case -5:
                 /* No match in segment table */
-                env->exception_index = POWERPC_EXCP_ISEG;
-                env->error_code = 0;
+                if (env->mmu_model == POWERPC_MMU_620) {
+                    env->exception_index = POWERPC_EXCP_ISI;
+                    /* XXX: this might be incorrect */
+                    env->error_code = 0x40000000;
+                } else {
+                    env->exception_index = POWERPC_EXCP_ISEG;
+                    env->error_code = 0;
+                }
                 break;
 #endif
             }
@@ -1634,6 +1643,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                 case POWERPC_MMU_32B:
                 case POWERPC_MMU_601:
 #if defined(TARGET_PPC64)
+                case POWERPC_MMU_620:
                 case POWERPC_MMU_64B:
 #endif
                     env->exception_index = POWERPC_EXCP_DSI;
@@ -1716,9 +1726,20 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 #if defined(TARGET_PPC64)
             case -5:
                 /* No match in segment table */
-                env->exception_index = POWERPC_EXCP_DSEG;
-                env->error_code = 0;
-                env->spr[SPR_DAR] = address;
+                if (env->mmu_model == POWERPC_MMU_620) {
+                    env->exception_index = POWERPC_EXCP_DSI;
+                    env->error_code = 0;
+                    env->spr[SPR_DAR] = address;
+                    /* XXX: this might be incorrect */
+                    if (rw == 1)
+                        env->spr[SPR_DSISR] = 0x42000000;
+                    else
+                        env->spr[SPR_DSISR] = 0x40000000;
+                } else {
+                    env->exception_index = POWERPC_EXCP_DSEG;
+                    env->error_code = 0;
+                    env->spr[SPR_DAR] = address;
+                }
                 break;
 #endif
             }
@@ -1955,6 +1976,7 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
     case POWERPC_MMU_32B:
     case POWERPC_MMU_601:
 #if defined(TARGET_PPC64)
+    case POWERPC_MMU_620:
     case POWERPC_MMU_64B:
 #endif /* defined(TARGET_PPC64) */
         tlb_flush(env, 1);
@@ -2021,6 +2043,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
         tlb_flush_page(env, addr | (0xF << 28));
         break;
 #if defined(TARGET_PPC64)
+    case POWERPC_MMU_620:
     case POWERPC_MMU_64B:
         /* tlbie invalidate TLBs for all segments */
         /* XXX: given the fact that there are too many segments to invalidate,
index ce0027cc3921e78de8ce5dc077ff407376e651af..f3bc1f5f7f75c7400792c31057d0ae34d0783f29 100644 (file)
@@ -5237,13 +5237,13 @@ static void init_proc_970MP (CPUPPCState *env)
 /* PowerPC 620                                                               */
 #define POWERPC_INSNS_620    (POWERPC_INSNS_WORKS | PPC_FLOAT_FSQRT |         \
                               PPC_64B | PPC_SLBI)
-#define POWERPC_MSRM_620     (0x800000000005FF73ULL)
-#define POWERPC_MMU_620      (POWERPC_MMU_64B)
+#define POWERPC_MSRM_620     (0x800000000005FF77ULL)
+//#define POWERPC_MMU_620      (POWERPC_MMU_620)
 #define POWERPC_EXCP_620     (POWERPC_EXCP_970)
 #define POWERPC_INPUT_620    (PPC_FLAGS_INPUT_6xx)
 #define POWERPC_BFDM_620     (bfd_mach_ppc64)
 #define POWERPC_FLAG_620     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |            \
-                              POWERPC_FLAG_BUS_CLK)
+                              POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
 #define check_pow_620        check_pow_nocheck /* Check this */
 
 __attribute__ (( unused ))
@@ -8313,6 +8313,9 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
         case POWERPC_MMU_64B:
             mmu_model = "PowerPC 64";
             break;
+        case POWERPC_MMU_620:
+            mmu_model = "PowerPC 620";
+            break;
 #endif
         default:
             mmu_model = "Unknown or invalid";