On Sat, Jun 23, 2007 at 09:41:11AM +0100, Thiemo Seufer wrote:
> Aurelien Jarno wrote:
> > Hi!
> > 
> > The current MIPS64 implementation assumes SEGBITS = 40 for all CPU. This
> > is correct for most CPU, but wrong for example for the 5K one, which has
> > SEGBITS = 42.
> > 
> > This patch modifies the current code to use SEGBITS instead of an 
> > hardcoded value. Instead of recomputing the corresponding mask each time
> > the value is computed in translate_init and stored in env.
> 
> Looks good, except that it breaks for me mips64el-softmmu...
> It hangs at the startup of userland.
> 

The problem is due to the recent change that enables mips64(el)-softmmu
to emulate 32-bit CPU.

This updated patch set SEGBITS to 32 on 32-bits CPU.


Index: target-mips/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/cpu.h,v
retrieving revision 1.41
diff -u -d -p -r1.41 cpu.h
--- target-mips/cpu.h   3 Jun 2007 21:02:38 -0000       1.41
+++ target-mips/cpu.h   13 Jun 2007 12:51:01 -0000
@@ -102,6 +102,8 @@ struct CPUMIPSState {
 
     uint32_t nb_tlb;
     uint32_t tlb_in_use;
+    uint32_t SEGBITS;
+    target_ulong SEGMask;
     int (*map_address) (CPUMIPSState *env, target_ulong *physical, int *prot, 
target_ulong address, int rw, int access_type);
     void (*do_tlbwi) (void);
     void (*do_tlbwr) (void);
Index: target-mips/helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/helper.c,v
retrieving revision 1.42
diff -u -d -p -r1.42 helper.c
--- target-mips/helper.c        28 May 2007 20:36:48 -0000      1.42
+++ target-mips/helper.c        13 Jun 2007 12:51:01 -0000
@@ -77,7 +77,7 @@ int r4k_map_address (CPUState *env, targ
         target_ulong tag = address & ~mask;
         target_ulong VPN = tlb->VPN & ~mask;
 #ifdef TARGET_MIPS64
-        tag &= 0xC00000FFFFFFFFFFULL;
+        tag &= env->SEGMask;
 #endif
 
         /* Check ASID, virtual page number & size */
@@ -140,18 +140,17 @@ static int get_physical_address (CPUStat
 /*
    XXX: Assuming :
    - PABITS = 36 (correct for MIPS64R1)
-   - SEGBITS = 40
 */
     } else if (address < 0x3FFFFFFFFFFFFFFFULL) {
         /* xuseg */
-       if (UX && address < 0x000000FFFFFFFFFFULL) {
+       if (UX && address < (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) {
             ret = env->map_address(env, physical, prot, address, rw, 
access_type);
        } else {
            ret = TLBRET_BADADDR;
         }
     } else if (address < 0x7FFFFFFFFFFFFFFFULL) {
         /* xsseg */
-       if (SX && address < 0x400000FFFFFFFFFFULL) {
+       if (SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) {
             ret = env->map_address(env, physical, prot, address, rw, 
access_type);
        } else {
            ret = TLBRET_BADADDR;
@@ -159,9 +158,9 @@ static int get_physical_address (CPUStat
     } else if (address < 0xBFFFFFFFFFFFFFFFULL) {
         /* xkphys */
         /* XXX: check supervisor mode */
-        if (KX && (address & 0x03FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL)
+        if (KX && (address & 0x07FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL)
        {
-            *physical = address & 0X000000FFFFFFFFFFULL;
+            *physical = address & 0X0000000FFFFFFFFFULL;
             *prot = PAGE_READ | PAGE_WRITE;
        } else {
            ret = TLBRET_BADADDR;
@@ -169,7 +168,7 @@ static int get_physical_address (CPUStat
     } else if (address < 0xFFFFFFFF7FFFFFFFULL) {
         /* xkseg */
         /* XXX: check supervisor mode */
-       if (KX && address < 0xC00000FF7FFFFFFFULL) {
+       if (KX && address < (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) {
             ret = env->map_address(env, physical, prot, address, rw, 
access_type);
        } else {
            ret = TLBRET_BADADDR;
@@ -303,10 +302,10 @@ int cpu_mips_handle_mmu_fault (CPUState 
         env->CP0_EntryHi =
             (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1));
 #ifdef TARGET_MIPS64
-        env->CP0_EntryHi &= 0xc00000ffffffffffULL;
-        env->CP0_XContext = (env->CP0_XContext & 0xfffffffe00000000ULL) |
-                            ((address >> 31) & 0x0000000180000000ULL) |
-                            ((address >> 9) & 0x000000007ffffff0ULL);
+        env->CP0_EntryHi &= env->SEGMask;
+        env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 
7))) |
+                            ((address & 0xC00000000000ULL) >> (env->SEGBITS - 
9)) |
+                            ((address & ((1ULL << env->SEGBITS) - 1) & 
0xFFFFFFFFFFFFE000ULL) >> 9);
 #endif
         env->exception_index = exception;
         env->error_code = error_code;
@@ -555,7 +554,7 @@ void r4k_invalidate_tlb (CPUState *env, 
     if (tlb->V0) {
         addr = tlb->VPN & ~mask;
 #ifdef TARGET_MIPS64
-        if (addr >= 0xC00000FF80000000ULL) {
+        if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
             addr |= 0x3FFFFF0000000000ULL;
         }
 #endif
@@ -568,7 +567,7 @@ void r4k_invalidate_tlb (CPUState *env, 
     if (tlb->V1) {
         addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
 #ifdef TARGET_MIPS64
-        if (addr >= 0xC00000FF80000000ULL) {
+        if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {
             addr |= 0x3FFFFF0000000000ULL;
         }
 #endif
Index: target-mips/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op.c,v
retrieving revision 1.65
diff -u -d -p -r1.65 op.c
--- target-mips/op.c    29 May 2007 16:52:56 -0000      1.65
+++ target-mips/op.c    13 Jun 2007 12:51:01 -0000
@@ -1328,7 +1328,7 @@ void op_mtc0_entryhi (void)
     /* 1k pages not implemented */
     val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
 #ifdef TARGET_MIPS64
-    val = T0 & 0xC00000FFFFFFFFFFULL;
+    val &= env->SEGMask;
 #endif
     old = env->CP0_EntryHi;
     env->CP0_EntryHi = val;
@@ -1526,7 +1533,8 @@ void op_mtc0_desave (void)
 #ifdef TARGET_MIPS64
 void op_mtc0_xcontext (void)
 {
-    env->CP0_XContext = (env->CP0_XContext & 0x1ffffffffULL) | (T0 & 
~0x1ffffffffULL);
+    target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
+    env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
     RETURN();
 }
 
Index: target-mips/op_helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op_helper.c,v
retrieving revision 1.52
diff -u -d -p -r1.52 op_helper.c
--- target-mips/op_helper.c     3 Jun 2007 17:44:36 -0000       1.52
+++ target-mips/op_helper.c     13 Jun 2007 12:51:02 -0000
@@ -374,7 +389,7 @@ static void r4k_fill_tlb (int idx)
     tlb = &env->mmu.r4k.tlb[idx];
     tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
 #ifdef TARGET_MIPS64
-    tlb->VPN &= 0xC00000FFFFFFFFFFULL;
+    tlb->VPN &= env->SEGMask;
 #endif
     tlb->ASID = env->CP0_EntryHi & 0xFF;
     tlb->PageMask = env->CP0_PageMask;
Index: target-mips/translate_init.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/translate_init.c,v
retrieving revision 1.16
diff -u -d -p -r1.16 translate_init.c
--- target-mips/translate_init.c        22 Jun 2007 23:50:19 -0000      1.16
+++ target-mips/translate_init.c        23 Jun 2007 13:13:44 -0000
@@ -71,6 +71,7 @@ struct mips_def_t {
     int32_t CCRes;
     int32_t Status_rw_bitmask;
     int32_t CP1_fcr0;
+    int32_t SEGBITS;
 };
 
 /*****************************************************************************/
@@ -87,6 +88,7 @@ static mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         .Status_rw_bitmask = 0x3278FF17,
+        .SEGBITS = 32,
     },
     {
         .name = "4KEcR1",
@@ -98,6 +100,7 @@ static mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         .Status_rw_bitmask = 0x3278FF17,
+        .SEGBITS = 32,
     },
     {
         .name = "4KEc",
@@ -109,6 +112,7 @@ static mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         .Status_rw_bitmask = 0x3278FF17,
+        .SEGBITS = 32,
     },
     {
         .name = "24Kc",
@@ -120,6 +124,7 @@ static mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         .Status_rw_bitmask = 0x3278FF17,
+        .SEGBITS = 32,
     },
     {
         .name = "24Kf",
@@ -133,6 +138,7 @@ static mips_def_t mips_defs[] =
         .Status_rw_bitmask = 0x3678FF17,
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
                     (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
+        .SEGBITS = 32,
     },
 #ifdef TARGET_MIPS64
     {
@@ -147,6 +153,7 @@ static mips_def_t mips_defs[] =
         .Status_rw_bitmask = 0x3678FFFF,
        /* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */
         .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .SEGBITS = 40,
     },
     {
         .name = "5Kc",
@@ -161,6 +168,7 @@ static mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         .Status_rw_bitmask = 0x32F8FFFF,
+        .SEGBITS = 42,
     },
     {
         .name = "5Kf",
@@ -178,6 +186,7 @@ static mips_def_t mips_defs[] =
        /* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */
         .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .SEGBITS = 42,
     },
     {
         .name = "20Kc",
@@ -198,6 +207,7 @@ static mips_def_t mips_defs[] =
         .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) |
                     (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .SEGBITS = 40,
     },
 #endif
 };
@@ -274,6 +284,10 @@ int cpu_mips_register (CPUMIPSState *env
     env->CCRes = def->CCRes;
     env->Status_rw_bitmask = def->Status_rw_bitmask;
     env->fcr0 = def->CP1_fcr0;
+#ifdef TARGET_MIPS64
+    env->SEGBITS = def->SEGBITS;
+    env->SEGMask = (3ULL << 62) | ((1ULL << def->SEGBITS) - 1);
+#endif
 #ifdef CONFIG_USER_ONLY
     if (env->CP0_Config1 & (1 << CP0C1_FP))
         env->hflags |= MIPS_HFLAG_FPU;

-- 
  .''`.  Aurelien Jarno             | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   [EMAIL PROTECTED]         | [EMAIL PROTECTED]
   `-    people.debian.org/~aurel32 | www.aurel32.net


Reply via email to