summary refs log tree commit diff stats
path: root/target-sparc/helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-sparc/helper.c')
-rw-r--r--target-sparc/helper.c130
1 files changed, 86 insertions, 44 deletions
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 582de1082c..96a22f3475 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -30,6 +30,13 @@
 //#define DEBUG_MMU
 //#define DEBUG_FEATURES
 
+#ifdef DEBUG_MMU
+#define DPRINTF_MMU(fmt, ...) \
+    do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF_MMU(fmt, ...) do {} while (0)
+#endif
+
 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
 
 /* Sparc MMU emulation */
@@ -451,42 +458,50 @@ static int get_physical_address_data(CPUState *env,
 
     for (i = 0; i < 64; i++) {
         // ctx match, vaddr match, valid?
-        if (ultrasparc_tag_match(&env->dtlb[i],
-                                 address, context, physical)) {
+        if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
+
+            uint8_t fault_type = 0;
+
             // access ok?
-            if (((env->dtlb[i].tte & 0x4) && is_user) ||
-                (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
-                uint8_t fault_type = 0;
+            if ((env->dtlb[i].tte & 0x4) && is_user) {
+                fault_type |= 1; /* privilege violation */
+                env->exception_index = TT_DFAULT;
 
-                if ((env->dtlb[i].tte & 0x4) && is_user) {
-                    fault_type |= 1; /* privilege violation */
-                }
+                DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
+                            " mmu_idx=%d tl=%d\n",
+                            address, context, mmu_idx, env->tl);
+            } else if (!(env->dtlb[i].tte & 0x2) && (rw == 1)) {
+                env->exception_index = TT_DPROT;
+
+                DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64
+                            " mmu_idx=%d tl=%d\n",
+                            address, context, mmu_idx, env->tl);
+            } else {
+                *prot = PAGE_READ;
+                if (env->dtlb[i].tte & 0x2)
+                    *prot |= PAGE_WRITE;
 
-                if (env->dmmu.sfsr & 1) /* Fault status register */
-                    env->dmmu.sfsr = 2; /* overflow (not read before
+                TTE_SET_USED(env->dtlb[i].tte);
+
+                return 0;
+            }
+
+            if (env->dmmu.sfsr & 1) /* Fault status register */
+                env->dmmu.sfsr = 2; /* overflow (not read before
                                              another fault) */
 
-                env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
+            env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
 
-                env->dmmu.sfsr |= (fault_type << 7);
+            env->dmmu.sfsr |= (fault_type << 7);
 
-                env->dmmu.sfar = address; /* Fault address register */
-                env->exception_index = TT_DFAULT;
-#ifdef DEBUG_MMU
-                printf("DFAULT at 0x%" PRIx64 "\n", address);
-#endif
-                return 1;
-            }
-            *prot = PAGE_READ;
-            if (env->dtlb[i].tte & 0x2)
-                *prot |= PAGE_WRITE;
-            TTE_SET_USED(env->dtlb[i].tte);
-            return 0;
+            env->dmmu.sfar = address; /* Fault address register */
+            return 1;
         }
     }
-#ifdef DEBUG_MMU
-    printf("DMISS at 0x%" PRIx64 "\n", address);
-#endif
+
+    DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
+                address, context);
+
     env->dmmu.tag_access = (address & ~0x1fffULL) | context;
     env->exception_index = TT_DMISS;
     return 1;
@@ -528,9 +543,10 @@ static int get_physical_address_code(CPUState *env,
                                              another fault) */
                 env->immu.sfsr |= (is_user << 3) | 1;
                 env->exception_index = TT_TFAULT;
-#ifdef DEBUG_MMU
-                printf("TFAULT at 0x%" PRIx64 "\n", address);
-#endif
+
+                DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
+                            address, context);
+
                 return 1;
             }
             *prot = PAGE_EXEC;
@@ -538,9 +554,10 @@ static int get_physical_address_code(CPUState *env,
             return 0;
         }
     }
-#ifdef DEBUG_MMU
-    printf("TMISS at 0x%" PRIx64 "\n", address);
-#endif
+
+    DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n",
+                address, context);
+
     /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
     env->immu.tag_access = (address & ~0x1fffULL) | context;
     env->exception_index = TT_TMISS;
@@ -555,6 +572,23 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
     /* ??? We treat everything as a small page, then explicitly flush
        everything when an entry is evicted.  */
     *page_size = TARGET_PAGE_SIZE;
+
+#if defined (DEBUG_MMU)
+    /* safety net to catch wrong softmmu index use from dynamic code */
+    if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
+        DPRINTF_MMU("get_physical_address %s tl=%d mmu_idx=%d"
+                    " primary context=%" PRIx64
+                    " secondary context=%" PRIx64
+                " address=%" PRIx64
+                "\n",
+                (rw == 2 ? "CODE" : "DATA"),
+                env->tl, mmu_idx,
+                env->dmmu.mmu_primary_context,
+                env->dmmu.mmu_secondary_context,
+                address);
+    }
+#endif
+
     if (rw == 2)
         return get_physical_address_code(env, physical, prot, address,
                                          mmu_idx);
@@ -578,10 +612,18 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
         virt_addr = address & TARGET_PAGE_MASK;
         vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
                              (TARGET_PAGE_SIZE - 1));
-#ifdef DEBUG_MMU
-        printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
-               "\n", address, paddr, vaddr);
-#endif
+
+        DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
+                    " vaddr %" PRIx64
+                    " mmu_idx=%d"
+                    " tl=%d"
+                    " primary context=%" PRIx64
+                    " secondary context=%" PRIx64
+                    "\n",
+                    address, paddr, vaddr, mmu_idx, env->tl,
+                    env->dmmu.mmu_primary_context,
+                    env->dmmu.mmu_secondary_context);
+
         tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
         return 0;
     }
@@ -628,7 +670,7 @@ void dump_mmu(CPUState *env)
                        env->dtlb[i].tte & 0x2? "RW": "RO",
                        env->dtlb[i].tte & 0x40? "locked": "unlocked",
                        env->dtlb[i].tag & (uint64_t)0x1fffULL,
-                       TTE_IS_GLOBAL(env->dtlb[i].tag)? "global" : "local");
+                       TTE_IS_GLOBAL(env->dtlb[i].tte)? "global" : "local");
             }
         }
     }
@@ -662,7 +704,7 @@ void dump_mmu(CPUState *env)
                        env->itlb[i].tte & 0x4? "priv": "user",
                        env->itlb[i].tte & 0x40? "locked": "unlocked",
                        env->itlb[i].tag & (uint64_t)0x1fffULL,
-                       TTE_IS_GLOBAL(env->itlb[i].tag)? "global" : "local");
+                       TTE_IS_GLOBAL(env->itlb[i].tte)? "global" : "local");
             }
         }
     }
@@ -693,7 +735,7 @@ target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
 
 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
-    return cpu_get_phys_page_nofault(env, addr, MMU_KERNEL_IDX);
+    return cpu_get_phys_page_nofault(env, addr, cpu_mmu_index(env));
 }
 #endif
 
@@ -721,12 +763,12 @@ void cpu_reset(CPUSPARCState *env)
 #else
 #if !defined(TARGET_SPARC64)
     env->psret = 0;
-#endif
     env->psrs = 1;
     env->psrps = 1;
+#endif
 #ifdef TARGET_SPARC64
     env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
-    env->hpstate = HS_PRIV;
+    env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
     env->tl = env->maxtl;
     cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
     env->lsu = 0;
@@ -1310,7 +1352,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
     char *featurestr, *name = strtok(s, ",");
     uint32_t plus_features = 0;
     uint32_t minus_features = 0;
-    long long iu_version;
+    uint64_t iu_version;
     uint32_t fpu_version, mmu_version, nwindows;
 
     for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
@@ -1342,7 +1384,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
                 }
                 cpu_def->iu_version = iu_version;
 #ifdef DEBUG_FEATURES
-                fprintf(stderr, "iu_version %llx\n", iu_version);
+                fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
 #endif
             } else if (!strcmp(featurestr, "fpu_version")) {
                 char *err;