qemu-commits
[Top][All Lists]
Advanced

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

[Qemu-commits] [COMMIT f707726] sparc64 really implement itlb/dtlb autom


From: Anthony Liguori
Subject: [Qemu-commits] [COMMIT f707726] sparc64 really implement itlb/dtlb automaticreplacement writes
Date: Mon, 27 Jul 2009 07:21:59 -0000

From: Igor Kovalenko <address@hidden>

- implement "used" bit in tlb translation entry
- mark tlb entry used if qemu code/data translation succeeds
- fold i/d mmu replacement writes code into replace_tlb_1bit_lru which
adds 1bit lru replacement algorithm; previously code tried to replace
first unlocked entry only

- extract more bitmasks to named macros
- add "immu" or "dmmu" type name to debugging output where appropriate

Signed-off-by: address@hidden

--
Kind regards,
Igor V. Kovalenko

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 98c185f..490fd7b 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -273,6 +273,17 @@ enum {
 };
 #endif
 
+#define TTE_VALID_BIT       (1ULL << 63)
+#define TTE_USED_BIT        (1ULL << 41)
+#define TTE_LOCKED_BIT      (1ULL <<  6)
+
+#define TTE_IS_VALID(tte)   ((tte) & TTE_VALID_BIT)
+#define TTE_IS_USED(tte)    ((tte) & TTE_USED_BIT)
+#define TTE_IS_LOCKED(tte)  ((tte) & TTE_LOCKED_BIT)
+
+#define TTE_SET_USED(tte)   ((tte) |= TTE_USED_BIT)
+#define TTE_SET_UNUSED(tte) ((tte) &= ~TTE_USED_BIT)
+
 typedef struct SparcTLBEntry {
     uint64_t tag;
     uint64_t tte;
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 429be37..70343e3 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -409,7 +409,7 @@ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
     }
 
     // valid, context match, virtual address match?
-    if ((tlb->tte & 0x8000000000000000ULL) &&
+    if (TTE_IS_VALID(tlb->tte) &&
             compare_masked(context, tlb->tag, 0x1fff) &&
             compare_masked(address, tlb->tag, mask))
     {
@@ -468,6 +468,7 @@ static int get_physical_address_data(CPUState *env,
             *prot = PAGE_READ;
             if (env->dtlb[i].tte & 0x2)
                 *prot |= PAGE_WRITE;
+            TTE_SET_USED(env->dtlb[i].tte);
             return 0;
         }
     }
@@ -513,6 +514,7 @@ static int get_physical_address_code(CPUState *env,
                 return 1;
             }
             *prot = PAGE_EXEC;
+            TTE_SET_USED(env->itlb[i].tte);
             return 0;
         }
     }
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 5acaa0d..9b959fe 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -87,13 +87,14 @@ static uint64_t ultrasparc_tag_target(uint64_t 
tag_access_register)
     return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 
22);
 }
 
-static void replace_tlb_entry(SparcTLBEntry *tlb, CPUState *env1,
-                              uint64_t tlb_tag, uint64_t tlb_tte)
+static void replace_tlb_entry(SparcTLBEntry *tlb,
+                              uint64_t tlb_tag, uint64_t tlb_tte,
+                              CPUState *env1)
 {
     target_ulong mask, size, va, offset;
 
     // flush page range if translation is valid
-    if (tlb->tte & 0x8000000000000000ULL) {
+    if (TTE_IS_VALID(tlb->tte)) {
 
         mask = 0xffffffffffffe000ULL;
         mask <<= 3 * ((tlb->tte >> 61) & 3);
@@ -111,23 +112,22 @@ static void replace_tlb_entry(SparcTLBEntry *tlb, 
CPUState *env1,
 }
 
 static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
-                      CPUState *env1)
+                      const char* strmmu, CPUState *env1)
 {
     unsigned int i;
     target_ulong mask;
 
     for (i = 0; i < 64; i++) {
-        if (tlb[i].tte & 0x8000000000000000ULL) {
+        if (TTE_IS_VALID(tlb[i].tte)) {
 
             mask = 0xffffffffffffe000ULL;
             mask <<= 3 * ((tlb[i].tte >> 61) & 3);
 
             if ((demap_addr & mask) == (tlb[i].tag & mask)) {
-                replace_tlb_entry(&tlb[i], env1, 0, 0);
+                replace_tlb_entry(&tlb[i], 0, 0, env1);
 #ifdef DEBUG_MMU
-                DPRINTF_MMU("mmu demap invalidated entry [%02u]\n",
-                            i);
-                dump_mmu(env);
+                DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
+                dump_mmu(env1);
 #endif
             }
             //return;
@@ -136,6 +136,56 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong 
demap_addr,
 
 }
 
+static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
+                                 uint64_t tlb_tag, uint64_t tlb_tte,
+                                 const char* strmmu, CPUState *env1)
+{
+    unsigned int i, replace_used;
+
+    // Try replacing invalid entry
+    for (i = 0; i < 64; i++) {
+        if (!TTE_IS_VALID(tlb[i].tte)) {
+            replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
+#ifdef DEBUG_MMU
+            DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
+            dump_mmu(env1);
+#endif
+            return;
+        }
+    }
+
+    // All entries are valid, try replacing unlocked entry
+
+    for (replace_used = 0; replace_used < 2; ++replace_used) {
+
+        // Used entries are not replaced on first pass
+
+        for (i = 0; i < 64; i++) {
+            if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
+
+                replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
+#ifdef DEBUG_MMU
+                DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
+                            strmmu, (replace_used?"used":"unused"), i);
+                dump_mmu(env1);
+#endif
+                return;
+            }
+        }
+
+        // Now reset used bit and search for unused entries again
+
+        for (i = 0; i < 64; i++) {
+            TTE_SET_UNUSED(tlb[i].tte);
+        }
+    }
+
+#ifdef DEBUG_MMU
+    DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
+#endif
+    // error state?
+}
+
 #endif
 
 static inline void address_mask(CPUState *env1, target_ulong *addr)
@@ -2547,59 +2597,24 @@ void helper_st_asi(target_ulong addr, target_ulong val, 
int asi, int size)
             return;
         }
     case 0x54: // I-MMU data in
-        {
-            unsigned int i;
-
-            // Try finding an invalid entry
-            for (i = 0; i < 64; i++) {
-                if ((env->itlb[i].tte & 0x8000000000000000ULL) == 0) {
-                    replace_tlb_entry(&env->itlb[i], env,
-                                      env->immu.tag_access, val);
-#ifdef DEBUG_MMU
-                    DPRINTF_MMU("immu data map replaced invalid entry [%i]\n",
-                                i);
-                    dump_mmu(env);
-#endif
-                    return;
-                }
-            }
-            // Try finding an unlocked entry
-            for (i = 0; i < 64; i++) {
-                if ((env->itlb[i].tte & 0x40) == 0) {
-                    replace_tlb_entry(&env->itlb[i], env,
-                                      env->immu.tag_access, val);
-#ifdef DEBUG_MMU
-                    DPRINTF_MMU("immu data map replaced unlocked entry [%i]\n",
-                                i);
-                    dump_mmu(env);
-#endif
-                    return;
-                }
-            }
-#ifdef DEBUG_MMU
-            DPRINTF_MMU("immu data map failed: no entries available\n");
-#endif
-            // error state?
-            return;
-        }
+        replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", 
env);
+        return;
     case 0x55: // I-MMU data access
         {
             // TODO: auto demap
 
             unsigned int i = (addr >> 3) & 0x3f;
 
-            replace_tlb_entry(&env->itlb[i], env,
-                              env->immu.tag_access, val);
+            replace_tlb_entry(&env->itlb[i], env->immu.tag_access, val, env);
 
 #ifdef DEBUG_MMU
-            DPRINTF_MMU("immu data access replaced entry [%i]\n",
-                        i);
+            DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
             dump_mmu(env);
 #endif
             return;
         }
     case 0x57: // I-MMU demap
-        demap_tlb(env->itlb, val, env);
+        demap_tlb(env->itlb, val, "immu", env);
         return;
     case 0x58: // D-MMU regs
         {
@@ -2649,56 +2664,22 @@ void helper_st_asi(target_ulong addr, target_ulong val, 
int asi, int size)
             return;
         }
     case 0x5c: // D-MMU data in
-        {
-            unsigned int i;
-
-            // Try finding an invalid entry
-            for (i = 0; i < 64; i++) {
-                if ((env->dtlb[i].tte & 0x8000000000000000ULL) == 0) {
-                    replace_tlb_entry(&env->dtlb[i], env,
-                                      env->dmmu.tag_access, val);
-#ifdef DEBUG_MMU
-                    DPRINTF_MMU("dmmu data map replaced invalid entry [%i]\n",
-                                i);
-                    dump_mmu(env);
-#endif
-                    return;
-                }
-            }
-            // Try finding an unlocked entry
-            for (i = 0; i < 64; i++) {
-                if ((env->dtlb[i].tte & 0x40) == 0) {
-                    replace_tlb_entry(&env->dtlb[i], env,
-                                      env->dmmu.tag_access, val);
-#ifdef DEBUG_MMU
-                    DPRINTF_MMU("dmmu data map replaced unlocked entry [%i]\n",
-                                i);
-                    dump_mmu(env);
-#endif
-                    return;
-                }
-            }
-#ifdef DEBUG_MMU
-            DPRINTF_MMU("dmmu data map failed: no entries available\n");
-#endif
-            // error state?
-            return;
-        }
+        replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", 
env);
+        return;
     case 0x5d: // D-MMU data access
         {
             unsigned int i = (addr >> 3) & 0x3f;
 
-            replace_tlb_entry(&env->dtlb[i], env,
-                              env->dmmu.tag_access, val);
+            replace_tlb_entry(&env->dtlb[i], env->dmmu.tag_access, val, env);
+
 #ifdef DEBUG_MMU
-            DPRINTF_MMU("dmmu data access replaced entry [%i]\n",
-                        i);
+            DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
             dump_mmu(env);
 #endif
             return;
         }
     case 0x5f: // D-MMU demap
-        demap_tlb(env->dtlb, val, env);
+        demap_tlb(env->dtlb, val, "dmmu", env);
         return;
     case 0x49: // Interrupt data receive
         // XXX




reply via email to

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