qemu-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-commits] [COMMIT 536ba01] sparc64: unify mmu tag matching code


From: Anthony Liguori
Subject: [Qemu-commits] [COMMIT 536ba01] sparc64: unify mmu tag matching code
Date: Sun, 12 Jul 2009 07:55:26 -0000

From: Igor Kovalenko <address@hidden>

This patch extracts common part of sparc64 tag
matching code used by IMMU and DMMU lookups.

Signed-off-by: address@hidden

--
Kind regards,
Igor V. Kovalenko

diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index cd067df..d133294 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -379,12 +379,55 @@ static inline target_phys_addr_t 
ultrasparc_truncate_physical(uint64_t x)
 /*
  * 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(uint64_t tlb_tag, uint64_t tlb_tte,
+                                       uint64_t address, uint64_t context,
+                                       target_phys_addr_t *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 ((tlb_tte & 0x8000000000000000ULL) &&
+            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,
                                      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 = ultrasparc_truncate_physical(address);
@@ -392,26 +435,13 @@ static int get_physical_address_data(CPUState *env,
         return 0;
     }
 
+    context = env->dmmuregs[1] & 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_tag[i], env->dtlb_tte[i],
+                                 address, context, physical)
+        ) {
             // access ok?
             if (((env->dtlb_tte[i] & 0x4) && is_user) ||
                 (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
@@ -426,8 +456,6 @@ static int get_physical_address_data(CPUState *env,
 #endif
                 return 1;
             }
-            *physical = ((env->dtlb_tte[i] & mask) | (address & ~mask)) &
-                        0x1ffffffe000ULL;
             *prot = PAGE_READ;
             if (env->dtlb_tte[i] & 0x2)
                 *prot |= PAGE_WRITE;
@@ -437,7 +465,7 @@ static int get_physical_address_data(CPUState *env,
 #ifdef DEBUG_MMU
     printf("DMISS at 0x%" PRIx64 "\n", address);
 #endif
-    env->dmmuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
+    env->dmmuregs[6] = (address & ~0x1fffULL) | context;
     env->exception_index = TT_DMISS;
     return 1;
 }
@@ -446,8 +474,8 @@ static int get_physical_address_code(CPUState *env,
                                      target_phys_addr_t *physical, int *prot,
                                      target_ulong address, int is_user)
 {
-    target_ulong mask;
     unsigned int i;
+    uint64_t context;
 
     if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
         /* IMMU disabled */
@@ -456,26 +484,13 @@ static int get_physical_address_code(CPUState *env,
         return 0;
     }
 
+    context = env->dmmuregs[1] & 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_tag[i], env->itlb_tte[i],
+                                 address, context, physical)
+        ) {
             // access ok?
             if ((env->itlb_tte[i] & 0x4) && is_user) {
                 if (env->immuregs[3]) /* Fault status register */
@@ -488,8 +503,6 @@ static int get_physical_address_code(CPUState *env,
 #endif
                 return 1;
             }
-            *physical = ((env->itlb_tte[i] & mask) | (address & ~mask)) &
-                        0x1ffffffe000ULL;
             *prot = PAGE_EXEC;
             return 0;
         }
@@ -498,7 +511,7 @@ static int get_physical_address_code(CPUState *env,
     printf("TMISS at 0x%" PRIx64 "\n", address);
 #endif
     /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
-    env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
+    env->immuregs[6] = (address & ~0x1fffULL) | context;
     env->exception_index = TT_TMISS;
     return 1;
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]