qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH][MIPS] MMU code improvements


From: Aurelien Jarno
Subject: [Qemu-devel] [PATCH][MIPS] MMU code improvements
Date: Sat, 12 May 2007 16:45:02 +0200
User-agent: Mutt/1.5.13 (2006-08-11)

Hi all,

Please find below a patch to improve the MMU code on the MIPS target.

It fixes map_address() invalidate_tlb() and do_tlbp() for page sizes 
greater than 4kB. The VPN contained in a TLB should be masked with the
page mask of the same TLB as the VPN value may not be aligned. This is
explicitely required at least for tlbp in the MIPS64 PRA manual.

It also replace a few hardcoded values corresponding to the minimum
page size of 4kB by the size of a QEMU page (using TARGET_PAGE_MASK).
It should help to add 1kB pages support.

The other parts are cosmetic fixes.

Cheers,
Aurelien


Index: target-mips/helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/helper.c,v
retrieving revision 1.37
diff -u -d -p -r1.37 helper.c
--- target-mips/helper.c        9 May 2007 09:34:30 -0000       1.37
+++ target-mips/helper.c        12 May 2007 13:46:50 -0000
@@ -47,15 +47,14 @@ static int map_address (CPUState *env, t
     for (i = 0; i < env->tlb_in_use; i++) {
         tlb_t *tlb = &env->tlb[i];
         /* 1k pages are not supported. */
-        target_ulong mask = tlb->PageMask | 0x1FFF;
+        target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
         target_ulong tag = address & ~mask;
-        int n;
+        target_ulong VPN = tlb->VPN & ~mask;
 
         /* Check ASID, virtual page number & size */
-        if ((tlb->G == 1 || tlb->ASID == ASID) &&
-            tlb->VPN == tag) {
+        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
             /* TLB match */
-            n = !!(address & mask & ~(mask >> 1));
+            int n = !!(address & mask & ~(mask >> 1));
             /* Check access rights */
            if (!(n ? tlb->V1 : tlb->V0))
                 return TLBRET_INVALID;
@@ -492,7 +491,7 @@ void invalidate_tlb (CPUState *env, int 
     target_ulong mask;
 
     tlb = &env->tlb[idx];
-    /* The qemu TLB is flushed then the ASID changes, so no need to
+    /* The qemu TLB is flushed when the ASID changes, so no need to
        flush these entries again.  */
     if (tlb->G == 0 && tlb->ASID != ASID) {
         return;
@@ -508,9 +507,9 @@ void invalidate_tlb (CPUState *env, int 
     }
 
     /* 1k pages are not supported. */
-    mask = tlb->PageMask | 0x1FFF;
+    mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
     if (tlb->V0) {
-        addr = tlb->VPN;
+        addr = tlb->VPN & ~mask;
         end = addr | (mask >> 1);
         while (addr < end) {
             tlb_flush_page (env, addr);
@@ -518,8 +517,7 @@ void invalidate_tlb (CPUState *env, int 
         }
     }
     if (tlb->V1) {
-        addr = tlb->VPN | ((mask >> 1) + 1);
-        addr = tlb->VPN + TARGET_PAGE_SIZE;
+        addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
         end = addr | mask;
         while (addr < end) {
             tlb_flush_page (env, addr);
Index: target-mips/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op.c,v
retrieving revision 1.49
diff -u -d -p -r1.49 op.c
--- target-mips/op.c    11 May 2007 17:08:26 -0000      1.49
+++ target-mips/op.c    12 May 2007 13:46:50 -0000
@@ -1283,7 +1283,7 @@ void op_mtc0_context (void)
 void op_mtc0_pagemask (void)
 {
     /* 1k pages not implemented */
-    env->CP0_PageMask = T0 & 0x1FFFE000;
+    env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
     RETURN();
 }
 
Index: target-mips/op_helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op_helper.c,v
retrieving revision 1.42
diff -u -d -p -r1.42 op_helper.c
--- target-mips/op_helper.c     17 Apr 2007 15:26:47 -0000      1.42
+++ target-mips/op_helper.c     12 May 2007 13:46:50 -0000
@@ -411,7 +411,7 @@ static void fill_tlb (int idx)
 
     /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
     tlb = &env->tlb[idx];
-    tlb->VPN = env->CP0_EntryHi & ~(target_ulong)0x1FFF;
+    tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
     tlb->ASID = env->CP0_EntryHi & 0xFF;
     tlb->PageMask = env->CP0_PageMask;
     tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
@@ -447,16 +447,18 @@ void do_tlbwr (void)
 void do_tlbp (void)
 {
     tlb_t *tlb;
-    target_ulong tag;
     uint8_t ASID;
     int i;
 
-    tag = env->CP0_EntryHi & (int32_t)0xFFFFE000;
     ASID = env->CP0_EntryHi & 0xFF;
     for (i = 0; i < env->nb_tlb; i++) {
         tlb = &env->tlb[i];
+        /* 1k pages are not supported. */
+        target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
+        target_ulong tag = env->CP0_EntryHi & ~mask;
+        target_ulong VPN = tlb->VPN & ~mask;
         /* Check ASID, virtual page number & size */
-        if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
+        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
             /* TLB match */
             env->CP0_Index = i;
             break;
@@ -467,8 +469,12 @@ void do_tlbp (void)
         for (i = env->nb_tlb; i < env->tlb_in_use; i++) {
            tlb = &env->tlb[i];
 
+           /* 1k pages are not supported. */
+           target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
+           target_ulong tag = env->CP0_EntryHi & ~mask;
+           target_ulong VPN = tlb->VPN & ~mask;
            /* Check ASID, virtual page number & size */
-           if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
+           if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
                 mips_tlb_flush_extra (env, i);
                break;
            }

-- 
  .''`.  Aurelien Jarno             | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   address@hidden         | address@hidden
   `-    people.debian.org/~aurel32 | www.aurel32.net




reply via email to

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