qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 1/6] A cumulative MIPS patchset
@ 2006-11-21 14:36 Thiemo Seufer
  2006-11-21 14:42 ` Daniel Jacobowitz
  0 siblings, 1 reply; 2+ messages in thread
From: Thiemo Seufer @ 2006-11-21 14:36 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 87 bytes --]

Hello All,

the attached patch is an update of Daniel's MIPS TLB improvements


Thiemo

[-- Attachment #2: qemu.drow-performance --]
[-- Type: text/plain, Size: 6117 bytes --]

Date: Sun, 12 Nov 2006 12:49:44 -0500
From: Daniel Jacobowitz <drow@false.org>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] Huge TLB performance improvement

 target-mips/cpu.h       |    3 ++-
 target-mips/exec.h      |    1 +
 target-mips/helper.c    |    2 +-
 target-mips/mips-defs.h |    1 +
 target-mips/op_helper.c |   43 +++++++++++++++++++++++++++++++++++++------
 target-mips/translate.c |    1 +
 6 files changed, 43 insertions(+), 8 deletions(-)

Index: qemu-work/target-mips/cpu.h
===================================================================
--- qemu-work.orig/target-mips/cpu.h	2006-11-15 22:40:28.000000000 +0000
+++ qemu-work/target-mips/cpu.h	2006-11-15 22:41:04.000000000 +0000
@@ -94,7 +94,8 @@
 		
 #endif
 #if defined(MIPS_USES_R4K_TLB)
-    tlb_t tlb[MIPS_TLB_NB];
+    tlb_t tlb[MIPS_TLB_MAX];
+    uint32_t tlb_in_use;
 #endif
     uint32_t CP0_index;
     uint32_t CP0_random;
Index: qemu-work/target-mips/exec.h
===================================================================
--- qemu-work.orig/target-mips/exec.h	2006-11-15 22:40:28.000000000 +0000
+++ qemu-work/target-mips/exec.h	2006-11-15 22:41:04.000000000 +0000
@@ -115,5 +115,6 @@
 void cpu_mips_store_count (CPUState *env, uint32_t value);
 void cpu_mips_store_compare (CPUState *env, uint32_t value);
 void cpu_mips_clock_init (CPUState *env);
+void cpu_mips_tlb_flush (CPUState *env, int flush_global);
 
 #endif /* !defined(__QEMU_MIPS_EXEC_H__) */
Index: qemu-work/target-mips/helper.c
===================================================================
--- qemu-work.orig/target-mips/helper.c	2006-11-15 15:13:46.000000000 +0000
+++ qemu-work/target-mips/helper.c	2006-11-15 22:41:04.000000000 +0000
@@ -46,7 +46,7 @@
     tlb_t *tlb;
     int i, n;
 
-    for (i = 0; i < MIPS_TLB_NB; i++) {
+    for (i = 0; i < env->tlb_in_use; i++) {
         tlb = &env->tlb[i];
         /* Check ASID, virtual page number & size */
         if ((tlb->G == 1 || tlb->ASID == ASID) &&
Index: qemu-work/target-mips/mips-defs.h
===================================================================
--- qemu-work.orig/target-mips/mips-defs.h	2006-11-15 15:12:16.000000000 +0000
+++ qemu-work/target-mips/mips-defs.h	2006-11-15 22:41:04.000000000 +0000
@@ -22,6 +22,7 @@
 /* Uses MIPS R4Kc TLB model */
 #define MIPS_USES_R4K_TLB
 #define MIPS_TLB_NB 16
+#define MIPS_TLB_MAX 128
 /* basic FPU register support */
 #define MIPS_USES_FPU 1
 /* Define a implementation number of 1.
Index: qemu-work/target-mips/op_helper.c
===================================================================
--- qemu-work.orig/target-mips/op_helper.c	2006-11-15 22:40:28.000000000 +0000
+++ qemu-work/target-mips/op_helper.c	2006-11-15 22:41:04.000000000 +0000
@@ -18,6 +18,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include "exec.h"
+#include <string.h>
 
 #define MIPS_DEBUG_DISAS
 
@@ -367,7 +368,7 @@
         env->CP0_EntryHi = val;
 	/* If the ASID changes, flush qemu's TLB.  */
 	if ((old & 0xFF) != (val & 0xFF))
-	  tlb_flush (env, 1);
+	  cpu_mips_tlb_flush (env, 1);
         rn = "EntryHi";
         break;
     case 11:
@@ -568,7 +569,14 @@
 
 /* TLB management */
 #if defined(MIPS_USES_R4K_TLB)
-static void invalidate_tlb (int idx)
+void cpu_mips_tlb_flush (CPUState *env, int flush_global)
+{
+    /* Flush qemu's TLB and discard all shadowed entries.  */
+    tlb_flush (env, flush_global);
+    env->tlb_in_use = MIPS_TLB_NB;
+}
+
+static void invalidate_tlb (int idx, int use_extra)
 {
     tlb_t *tlb;
     target_ulong addr;
@@ -583,6 +591,15 @@
         return;
     }
 
+    if (use_extra && env->tlb_in_use < MIPS_TLB_MAX) {
+        /* For tlbwr, we can shadow the discarded entry into
+	   a new (fake) TLB entry, as long as the guest can not
+	   tell that it's there.  */
+        memcpy (&env->tlb[env->tlb_in_use], tlb, sizeof (*tlb));
+        env->tlb_in_use++;
+        return;
+    }
+
     if (tlb->V0) {
         tb_invalidate_page_range(tlb->PFN[0], tlb->end - tlb->VPN);
         addr = tlb->VPN;
@@ -601,6 +618,13 @@
     }
 }
 
+static void mips_tlb_flush_extra (CPUState *env)
+{
+    while (env->tlb_in_use > MIPS_TLB_NB) {
+        invalidate_tlb(--env->tlb_in_use, 0);
+    }
+}
+
 static void fill_tlb (int idx)
 {
     tlb_t *tlb;
@@ -627,9 +651,14 @@
 
 void do_tlbwi (void)
 {
+    /* Discard cached TLB entries.  We could avoid doing this if the
+       tlbwi is just upgrading access permissions on the current entry;
+       that might be a further win.  */
+    mips_tlb_flush_extra (env);
+
     /* Wildly undefined effects for CP0_index containing a too high value and
        MIPS_TLB_NB not being a power of two.  But so does real silicon.  */
-    invalidate_tlb(env->CP0_index & (MIPS_TLB_NB - 1));
+    invalidate_tlb(env->CP0_index & (MIPS_TLB_NB - 1), 0);
     fill_tlb(env->CP0_index & (MIPS_TLB_NB - 1));
 }
 
@@ -637,7 +666,7 @@
 {
     int r = cpu_mips_get_random(env);
 
-    invalidate_tlb(r);
+    invalidate_tlb(r, 1);
     fill_tlb(r);
 }
 
@@ -674,8 +703,10 @@
     tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)];
 
     /* If this will change the current ASID, flush qemu's TLB.  */
-    if (ASID != tlb->ASID && tlb->G != 1)
-      tlb_flush (env, 1);
+    if (ASID != tlb->ASID)
+        cpu_mips_tlb_flush (env, 1);
+
+    mips_tlb_flush_extra(env);
 
     env->CP0_EntryHi = tlb->VPN | tlb->ASID;
     size = (tlb->end - tlb->VPN) >> 12;
Index: qemu-work/target-mips/translate.c
===================================================================
--- qemu-work.orig/target-mips/translate.c	2006-11-15 22:40:28.000000000 +0000
+++ qemu-work/target-mips/translate.c	2006-11-15 22:41:04.000000000 +0000
@@ -2430,6 +2430,7 @@
     env->PC = 0xBFC00000;
 #if defined (MIPS_USES_R4K_TLB)
     env->CP0_random = MIPS_TLB_NB - 1;
+    env->tlb_in_use = MIPS_TLB_NB;
 #endif
     env->CP0_Wired = 0;
     env->CP0_Config0 = MIPS_CONFIG0;

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Qemu-devel] [PATCH 1/6] A cumulative MIPS patchset
  2006-11-21 14:36 [Qemu-devel] [PATCH 1/6] A cumulative MIPS patchset Thiemo Seufer
@ 2006-11-21 14:42 ` Daniel Jacobowitz
  0 siblings, 0 replies; 2+ messages in thread
From: Daniel Jacobowitz @ 2006-11-21 14:42 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 252 bytes --]

On Tue, Nov 21, 2006 at 02:36:02PM +0000, Thiemo Seufer wrote:
> Hello All,
> 
> the attached patch is an update of Daniel's MIPS TLB improvements

FYI, I actually have a better version of this patch now.  Attached.

-- 
Daniel Jacobowitz
CodeSourcery

[-- Attachment #2: tlb-hidden-entries-2.patch --]
[-- Type: text/plain, Size: 6420 bytes --]

---
 target-mips/cpu.h       |    3 +-
 target-mips/exec.h      |    1 
 target-mips/helper.c    |    2 -
 target-mips/mips-defs.h |    1 
 target-mips/op_helper.c |   54 ++++++++++++++++++++++++++++++++++++++++++------
 target-mips/translate.c |    1 
 6 files changed, 54 insertions(+), 8 deletions(-)

Index: qemu/target-mips/cpu.h
===================================================================
--- qemu.orig/target-mips/cpu.h	2006-11-12 11:34:01.000000000 -0500
+++ qemu/target-mips/cpu.h	2006-11-12 11:34:24.000000000 -0500
@@ -94,7 +94,8 @@ struct CPUMIPSState {
 		
 #endif
 #if defined(MIPS_USES_R4K_TLB)
-    tlb_t tlb[MIPS_TLB_NB];
+    tlb_t tlb[MIPS_TLB_MAX];
+    uint32_t tlb_in_use;
 #endif
     uint32_t CP0_index;
     uint32_t CP0_random;
Index: qemu/target-mips/exec.h
===================================================================
--- qemu.orig/target-mips/exec.h	2006-11-12 11:34:01.000000000 -0500
+++ qemu/target-mips/exec.h	2006-11-12 11:34:24.000000000 -0500
@@ -115,5 +115,6 @@ uint32_t cpu_mips_get_count (CPUState *e
 void cpu_mips_store_count (CPUState *env, uint32_t value);
 void cpu_mips_store_compare (CPUState *env, uint32_t value);
 void cpu_mips_clock_init (CPUState *env);
+void cpu_mips_tlb_flush (CPUState *env, int flush_global);
 
 #endif /* !defined(__QEMU_MIPS_EXEC_H__) */
Index: qemu/target-mips/helper.c
===================================================================
--- qemu.orig/target-mips/helper.c	2006-11-12 11:34:01.000000000 -0500
+++ qemu/target-mips/helper.c	2006-11-12 11:34:24.000000000 -0500
@@ -46,7 +46,7 @@ static int map_address (CPUState *env, t
     tlb_t *tlb;
     int i, n;
 
-    for (i = 0; i < MIPS_TLB_NB; i++) {
+    for (i = 0; i < env->tlb_in_use; i++) {
         tlb = &env->tlb[i];
         /* Check ASID, virtual page number & size */
         if ((tlb->G == 1 || tlb->ASID == ASID) &&
Index: qemu/target-mips/mips-defs.h
===================================================================
--- qemu.orig/target-mips/mips-defs.h	2006-11-12 11:34:01.000000000 -0500
+++ qemu/target-mips/mips-defs.h	2006-11-12 13:38:02.000000000 -0500
@@ -22,6 +22,7 @@
 /* Uses MIPS R4Kc TLB model */
 #define MIPS_USES_R4K_TLB
 #define MIPS_TLB_NB 16
+#define MIPS_TLB_MAX 128
 /* basic FPU register support */
 #define MIPS_USES_FPU 1
 /* Define a implementation number of 1.
Index: qemu/target-mips/op_helper.c
===================================================================
--- qemu.orig/target-mips/op_helper.c	2006-11-12 11:34:02.000000000 -0500
+++ qemu/target-mips/op_helper.c	2006-11-12 13:17:53.000000000 -0500
@@ -367,7 +367,7 @@ void do_mtc0 (int reg, int sel)
         env->CP0_EntryHi = val;
 	/* If the ASID changes, flush qemu's TLB.  */
 	if ((old & 0xFF) != (val & 0xFF))
-	  tlb_flush (env, 1);
+	  cpu_mips_tlb_flush (env, 1);
         rn = "EntryHi";
         break;
     case 11:
@@ -569,7 +569,14 @@ void fpu_handle_exception(void)
 
 /* TLB management */
 #if defined(MIPS_USES_R4K_TLB)
-static void invalidate_tlb (int idx)
+void cpu_mips_tlb_flush (CPUState *env, int flush_global)
+{
+    /* Flush qemu's TLB and discard all shadowed entries.  */
+    tlb_flush (env, flush_global);
+    env->tlb_in_use = MIPS_TLB_NB;
+}
+
+static void invalidate_tlb (int idx, int use_extra)
 {
     tlb_t *tlb;
     target_ulong addr;
@@ -582,6 +589,15 @@ static void invalidate_tlb (int idx)
         return;
     }
 
+    if (use_extra && env->tlb_in_use < MIPS_TLB_MAX) {
+        /* For tlbwr, we can shadow the discarded entry into
+	   a new (fake) TLB entry, as long as the guest can not
+	   tell that it's there.  */
+        env->tlb[env->tlb_in_use] = *tlb;
+        env->tlb_in_use++;
+        return;
+    }
+
     if (tlb->V0) {
         tb_invalidate_page_range(tlb->PFN[0], tlb->end - tlb->VPN);
         addr = tlb->VPN;
@@ -600,6 +616,14 @@ static void invalidate_tlb (int idx)
     }
 }
 
+static void mips_tlb_flush_extra (CPUState *env, int first)
+{
+    /* Discard entries from env->tlb[first] onwards.  */
+    while (env->tlb_in_use > first) {
+        invalidate_tlb(--env->tlb_in_use, 0);
+    }
+}
+
 static void fill_tlb (int idx)
 {
     tlb_t *tlb;
@@ -626,9 +650,14 @@ static void fill_tlb (int idx)
 
 void do_tlbwi (void)
 {
+    /* Discard cached TLB entries.  We could avoid doing this if the
+       tlbwi is just upgrading access permissions on the current entry;
+       that might be a further win.  */
+    mips_tlb_flush_extra (env, MIPS_TLB_NB);
+
     /* Wildly undefined effects for CP0_index containing a too high value and
        MIPS_TLB_NB not being a power of two.  But so does real silicon.  */
-    invalidate_tlb(env->CP0_index & (MIPS_TLB_NB - 1));
+    invalidate_tlb(env->CP0_index & (MIPS_TLB_NB - 1), 0);
     fill_tlb(env->CP0_index & (MIPS_TLB_NB - 1));
 }
 
@@ -636,7 +665,7 @@ void do_tlbwr (void)
 {
     int r = cpu_mips_get_random(env);
 
-    invalidate_tlb(r);
+    invalidate_tlb(r, 1);
     fill_tlb(r);
 }
 
@@ -659,6 +688,17 @@ void do_tlbp (void)
         }
     }
     if (i == MIPS_TLB_NB) {
+        /* No match.  Discard any shadow entries, if any of them match.  */
+        for (i = MIPS_TLB_NB; i < env->tlb_in_use; i++) {
+	    tlb = &env->tlb[i];
+
+	    /* Check ASID, virtual page number & size */
+	    if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
+                mips_tlb_flush_extra (env, i);
+	        break;
+	    }
+	}
+
         env->CP0_index |= 0x80000000;
     }
 }
@@ -673,8 +713,10 @@ void do_tlbr (void)
     tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)];
 
     /* If this will change the current ASID, flush qemu's TLB.  */
-    if (ASID != tlb->ASID && tlb->G != 1)
-      tlb_flush (env, 1);
+    if (ASID != tlb->ASID)
+        cpu_mips_tlb_flush (env, 1);
+
+    mips_tlb_flush_extra(env, MIPS_TLB_NB);
 
     env->CP0_EntryHi = tlb->VPN | tlb->ASID;
     size = (tlb->end - tlb->VPN) >> 12;
Index: qemu/target-mips/translate.c
===================================================================
--- qemu.orig/target-mips/translate.c	2006-11-12 11:34:01.000000000 -0500
+++ qemu/target-mips/translate.c	2006-11-12 11:34:24.000000000 -0500
@@ -2450,6 +2450,7 @@ void cpu_reset (CPUMIPSState *env)
     env->PC = 0xBFC00000;
 #if defined (MIPS_USES_R4K_TLB)
     env->CP0_random = MIPS_TLB_NB - 1;
+    env->tlb_in_use = MIPS_TLB_NB;
 #endif
     env->CP0_Wired = 0;
     env->CP0_Config0 = MIPS_CONFIG0;

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2006-11-21 14:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-21 14:36 [Qemu-devel] [PATCH 1/6] A cumulative MIPS patchset Thiemo Seufer
2006-11-21 14:42 ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).