]> git.proxmox.com Git - qemu.git/blobdiff - target-sparc/helper.c
Get rid of _t suffix
[qemu.git] / target-sparc / helper.c
index e249c64b0ac2bd8fc80a7002cc067cdb3c509b89..7d4811baefb7a2ef0858dcd18528f9b39ba73ddc 100644 (file)
@@ -14,8 +14,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include <stdarg.h>
 #include <stdlib.h>
@@ -23,7 +22,6 @@
 #include <string.h>
 #include <inttypes.h>
 #include <signal.h>
-#include <assert.h>
 
 #include "cpu.h"
 #include "exec-all.h"
@@ -38,7 +36,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
 
 /* thread support */
 
-static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
+static a_spinlock global_cpu_lock = SPIN_LOCK_UNLOCKED;
 
 void cpu_lock(void)
 {
@@ -102,12 +100,12 @@ static const int perm_table[2][8] = {
     }
 };
 
-static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
+static int get_physical_address(CPUState *env, a_target_phys_addr *physical,
                                 int *prot, int *access_index,
                                 target_ulong address, int rw, int mmu_idx)
 {
     int access_perms = 0;
-    target_phys_addr_t pde_ptr;
+    a_target_phys_addr pde_ptr;
     uint32_t pde;
     target_ulong virt_addr;
     int error_code = 0, is_dirty, is_user;
@@ -216,7 +214,7 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
 
     /* Even if large ptes, we map only one 4KB page in the cache to
        avoid filling it too fast */
-    *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
+    *physical = ((a_target_phys_addr)(pde & PTE_ADDR_MASK) << 4) + page_offset;
     return error_code;
 }
 
@@ -224,7 +222,7 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
 int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                               int mmu_idx, int is_softmmu)
 {
-    target_phys_addr_t paddr;
+    a_target_phys_addr paddr;
     target_ulong vaddr;
     int error_code = 0, prot, ret = 0, access_index;
 
@@ -266,11 +264,11 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 
 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
 {
-    target_phys_addr_t pde_ptr;
+    a_target_phys_addr pde_ptr;
     uint32_t pde;
 
     /* Context base + context number */
-    pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
+    pde_ptr = (a_target_phys_addr)(env->mmuregs[1] << 4) +
         (env->mmuregs[2] << 2);
     pde = ldl_phys(pde_ptr);
 
@@ -332,14 +330,14 @@ void dump_mmu(CPUState *env)
 {
     target_ulong va, va1, va2;
     unsigned int n, m, o;
-    target_phys_addr_t pde_ptr, pa;
+    a_target_phys_addr pde_ptr, pa;
     uint32_t pde;
 
     printf("MMU dump:\n");
     pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
     pde = ldl_phys(pde_ptr);
     printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
-           (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
+           (a_target_phys_addr)env->mmuregs[1] << 4, env->mmuregs[2]);
     for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
         pde = mmu_probe(env, va, 2);
         if (pde) {
@@ -370,132 +368,166 @@ void dump_mmu(CPUState *env)
 #endif /* DEBUG_MMU */
 
 #else /* !TARGET_SPARC64 */
+
+// 41 bit physical address space
+static inline a_target_phys_addr ultrasparc_truncate_physical(uint64_t x)
+{
+    return x & 0x1ffffffffffULL;
+}
+
 /*
  * UltraSparc IIi I/DMMUs
  */
+
+static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
+{
+    return (x & mask) == (y & mask);
+}
+
+// Returns true if TTE tag is valid and matches virtual address value in context
+// requires virtual address mask value calculated from TTE entry size
+static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
+                                       uint64_t address, uint64_t context,
+                                       a_target_phys_addr *physical)
+{
+    uint64_t mask;
+
+    switch ((tlb->tte >> 61) & 3) {
+    default:
+    case 0x0: // 8k
+        mask = 0xffffffffffffe000ULL;
+        break;
+    case 0x1: // 64k
+        mask = 0xffffffffffff0000ULL;
+        break;
+    case 0x2: // 512k
+        mask = 0xfffffffffff80000ULL;
+        break;
+    case 0x3: // 4M
+        mask = 0xffffffffffc00000ULL;
+        break;
+    }
+
+    // valid, context match, virtual address match?
+    if (TTE_IS_VALID(tlb->tte) &&
+            compare_masked(context, tlb->tag, 0x1fff) &&
+            compare_masked(address, tlb->tag, mask))
+    {
+        // decode physical address
+        *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
+        return 1;
+    }
+
+    return 0;
+}
+
 static int get_physical_address_data(CPUState *env,
-                                     target_phys_addr_t *physical, int *prot,
+                                     a_target_phys_addr *physical, int *prot,
                                      target_ulong address, int rw, int is_user)
 {
-    target_ulong mask;
     unsigned int i;
+    uint64_t context;
 
     if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
-        *physical = address;
+        *physical = ultrasparc_truncate_physical(address);
         *prot = PAGE_READ | PAGE_WRITE;
         return 0;
     }
 
+    context = env->dmmu.mmu_primary_context & 0x1fff;
+
     for (i = 0; i < 64; i++) {
-        switch ((env->dtlb_tte[i] >> 61) & 3) {
-        default:
-        case 0x0: // 8k
-            mask = 0xffffffffffffe000ULL;
-            break;
-        case 0x1: // 64k
-            mask = 0xffffffffffff0000ULL;
-            break;
-        case 0x2: // 512k
-            mask = 0xfffffffffff80000ULL;
-            break;
-        case 0x3: // 4M
-            mask = 0xffffffffffc00000ULL;
-            break;
-        }
         // ctx match, vaddr match, valid?
-        if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
-            (address & mask) == (env->dtlb_tag[i] & mask) &&
-            (env->dtlb_tte[i] & 0x8000000000000000ULL)) {
+        if (ultrasparc_tag_match(&env->dtlb[i],
+                                 address, context, physical)
+        ) {
             // access ok?
-            if (((env->dtlb_tte[i] & 0x4) && is_user) ||
-                (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
-                if (env->dmmuregs[3]) /* Fault status register */
-                    env->dmmuregs[3] = 2; /* overflow (not read before
+            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 */
+                }
+
+                if (env->dmmu.sfsr & 1) /* Fault status register */
+                    env->dmmu.sfsr = 2; /* overflow (not read before
                                              another fault) */
-                env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
-                env->dmmuregs[4] = address; /* Fault address register */
+
+                env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
+
+                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;
             }
-            *physical = ((env->dtlb_tte[i] & mask) | (address & ~mask)) &
-                        0x1ffffffe000ULL;
             *prot = PAGE_READ;
-            if (env->dtlb_tte[i] & 0x2)
+            if (env->dtlb[i].tte & 0x2)
                 *prot |= PAGE_WRITE;
+            TTE_SET_USED(env->dtlb[i].tte);
             return 0;
         }
     }
 #ifdef DEBUG_MMU
     printf("DMISS at 0x%" PRIx64 "\n", address);
 #endif
-    env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
+    env->dmmu.tag_access = (address & ~0x1fffULL) | context;
     env->exception_index = TT_DMISS;
     return 1;
 }
 
 static int get_physical_address_code(CPUState *env,
-                                     target_phys_addr_t *physical, int *prot,
+                                     a_target_phys_addr *physical, int *prot,
                                      target_ulong address, int is_user)
 {
-    target_ulong mask;
     unsigned int i;
+    uint64_t context;
 
-    if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
-        *physical = address;
+    if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
+        /* IMMU disabled */
+        *physical = ultrasparc_truncate_physical(address);
         *prot = PAGE_EXEC;
         return 0;
     }
 
+    context = env->dmmu.mmu_primary_context & 0x1fff;
+
     for (i = 0; i < 64; i++) {
-        switch ((env->itlb_tte[i] >> 61) & 3) {
-        default:
-        case 0x0: // 8k
-            mask = 0xffffffffffffe000ULL;
-            break;
-        case 0x1: // 64k
-            mask = 0xffffffffffff0000ULL;
-            break;
-        case 0x2: // 512k
-            mask = 0xfffffffffff80000ULL;
-            break;
-        case 0x3: // 4M
-            mask = 0xffffffffffc00000ULL;
-                break;
-        }
         // ctx match, vaddr match, valid?
-        if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
-            (address & mask) == (env->itlb_tag[i] & mask) &&
-            (env->itlb_tte[i] & 0x8000000000000000ULL)) {
+        if (ultrasparc_tag_match(&env->itlb[i],
+                                 address, context, physical)
+        ) {
             // access ok?
-            if ((env->itlb_tte[i] & 0x4) && is_user) {
-                if (env->immuregs[3]) /* Fault status register */
-                    env->immuregs[3] = 2; /* overflow (not read before
+            if ((env->itlb[i].tte & 0x4) && is_user) {
+                if (env->immu.sfsr) /* Fault status register */
+                    env->immu.sfsr = 2; /* overflow (not read before
                                              another fault) */
-                env->immuregs[3] |= (is_user << 3) | 1;
+                env->immu.sfsr |= (is_user << 3) | 1;
                 env->exception_index = TT_TFAULT;
 #ifdef DEBUG_MMU
                 printf("TFAULT at 0x%" PRIx64 "\n", address);
 #endif
                 return 1;
             }
-            *physical = ((env->itlb_tte[i] & mask) | (address & ~mask)) &
-                        0x1ffffffe000ULL;
             *prot = PAGE_EXEC;
+            TTE_SET_USED(env->itlb[i].tte);
             return 0;
         }
     }
 #ifdef DEBUG_MMU
     printf("TMISS at 0x%" PRIx64 "\n", address);
 #endif
-    env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
+    /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
+    env->immu.tag_access = (address & ~0x1fffULL) | context;
     env->exception_index = TT_TMISS;
     return 1;
 }
 
-static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
+static int get_physical_address(CPUState *env, a_target_phys_addr *physical,
                                 int *prot, int *access_index,
                                 target_ulong address, int rw, int mmu_idx)
 {
@@ -514,7 +546,7 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                               int mmu_idx, int is_softmmu)
 {
     target_ulong virt_addr, vaddr;
-    target_phys_addr_t paddr;
+    a_target_phys_addr paddr;
     int error_code = 0, prot, ret = 0, access_index;
 
     error_code = get_physical_address(env, &paddr, &prot, &access_index,
@@ -541,7 +573,7 @@ void dump_mmu(CPUState *env)
     const char *mask;
 
     printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
-           env->dmmuregs[1], env->dmmuregs[2]);
+           env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
     if ((env->lsu & DMMU_E) == 0) {
         printf("DMMU disabled\n");
     } else {
@@ -563,15 +595,16 @@ void dump_mmu(CPUState *env)
                 break;
             }
             if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
-                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
+                printf("[%02u] VA: " PRIx64 ", PA: " PRIx64
                        ", %s, %s, %s, %s, ctx %" PRId64 "\n",
-                       env->dtlb_tag[i] & ~0x1fffULL,
-                       env->dtlb_tte[i] & 0x1ffffffe000ULL,
+                       i,
+                       env->dtlb_tag[i] & (uint64_t)~0x1fffULL,
+                       env->dtlb_tte[i] & (uint64_t)0x1ffffffe000ULL,
                        mask,
                        env->dtlb_tte[i] & 0x4? "priv": "user",
                        env->dtlb_tte[i] & 0x2? "RW": "RO",
                        env->dtlb_tte[i] & 0x40? "locked": "unlocked",
-                       env->dtlb_tag[i] & 0x1fffULL);
+                       env->dtlb_tag[i] & (uint64_t)0x1fffULL);
             }
         }
     }
@@ -596,14 +629,15 @@ void dump_mmu(CPUState *env)
                 break;
             }
             if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
-                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx
+                printf("[%02u] VA: " PRIx64 ", PA: " PRIx64
                        ", %s, %s, %s, ctx %" PRId64 "\n",
-                       env->itlb_tag[i] & ~0x1fffULL,
-                       env->itlb_tte[i] & 0x1ffffffe000ULL,
+                       i,
+                       env->itlb[i].tag & (uint64_t)~0x1fffULL,
+                       env->itlb_tte[i] & (uint64_t)0x1ffffffe000ULL,
                        mask,
                        env->itlb_tte[i] & 0x4? "priv": "user",
                        env->itlb_tte[i] & 0x40? "locked": "unlocked",
-                       env->itlb_tag[i] & 0x1fffULL);
+                       env->itlb[i].tag & (uint64_t)0x1fffULL);
             }
         }
     }
@@ -615,15 +649,15 @@ void dump_mmu(CPUState *env)
 
 
 #if defined(CONFIG_USER_ONLY)
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+a_target_phys_addr cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     return addr;
 }
 
 #else
-target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+a_target_phys_addr cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
-    target_phys_addr_t phys_addr;
+    a_target_phys_addr phys_addr;
     int prot, access_index;
 
     if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
@@ -646,8 +680,11 @@ void cpu_reset(CPUSPARCState *env)
 
     tlb_flush(env, 1);
     env->cwp = 0;
+#ifndef TARGET_SPARC64
     env->wim = 1;
+#endif
     env->regwptr = env->regbase + (env->cwp * 16);
+    CC_OP = CC_OP_FLAGS;
 #if defined(CONFIG_USER_ONLY)
 #ifdef TARGET_SPARC64
     env->cleanwin = env->nwindows - 2;
@@ -656,13 +693,16 @@ void cpu_reset(CPUSPARCState *env)
     env->asi = 0x82; // Primary no-fault
 #endif
 #else
+#if !defined(TARGET_SPARC64)
     env->psret = 0;
+#endif
     env->psrs = 1;
     env->psrps = 1;
 #ifdef TARGET_SPARC64
-    env->pstate = PS_PRIV;
+    env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
     env->hpstate = HS_PRIV;
-    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
+    env->tl = env->maxtl;
+    cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
     env->lsu = 0;
 #else
     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
@@ -1289,7 +1329,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
                 }
                 cpu_def->fpu_version = fpu_version;
 #ifdef DEBUG_FEATURES
-                fprintf(stderr, "fpu_version %llx\n", fpu_version);
+                fprintf(stderr, "fpu_version %x\n", fpu_version);
 #endif
             } else if (!strcmp(featurestr, "mmu_version")) {
                 char *err;
@@ -1301,7 +1341,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
                 }
                 cpu_def->mmu_version = mmu_version;
 #ifdef DEBUG_FEATURES
-                fprintf(stderr, "mmu_version %llx\n", mmu_version);
+                fprintf(stderr, "mmu_version %x\n", mmu_version);
 #endif
             } else if (!strcmp(featurestr, "nwindows")) {
                 char *err;