qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH][MIPS] Implement supervisor mode


From: Aurelien Jarno
Subject: [Qemu-devel] [PATCH][MIPS] Implement supervisor mode
Date: Thu, 27 Sep 2007 18:21:58 +0200
User-agent: Mutt/1.5.13 (2006-08-11)

Hi all,

The patch below fully implements supervisor mode, and modify the
the corresponding bits in CP0_Status_rw_bitmask for the CPU which
support this mode.

Bye,
Aurelien


Index: target-mips/exec.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/exec.h,v
retrieving revision 1.34
diff -u -d -p -r1.34 exec.h
--- target-mips/exec.h  26 Sep 2007 23:52:06 -0000      1.34
+++ target-mips/exec.h  27 Sep 2007 16:18:19 -0000
@@ -261,16 +261,21 @@ static inline void compute_hflags(CPUSta
                      MIPS_HFLAG_FPU | MIPS_HFLAG_UM);
     if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
         !(env->CP0_Status & (1 << CP0St_ERL)) &&
-        !(env->hflags & MIPS_HFLAG_DM) &&
-        (env->CP0_Status & (1 << CP0St_UM)))
-        env->hflags |= MIPS_HFLAG_UM;
+        !(env->hflags & MIPS_HFLAG_DM)) {
+        if (env->CP0_Status & (1 << CP0St_UM))
+            env->hflags |= MIPS_HFLAG_UM;
+        if (env->CP0_Status & (1 << CP0St_R0))
+            env->hflags |= MIPS_HFLAG_SM;
+    }
 #ifdef TARGET_MIPS64
     if (!(env->hflags & MIPS_HFLAG_UM) ||
         (env->CP0_Status & (1 << CP0St_PX)) ||
         (env->CP0_Status & (1 << CP0St_UX)))
         env->hflags |= MIPS_HFLAG_64;
 #endif
-    if ((env->CP0_Status & (1 << CP0St_CU0)) || !(env->hflags & MIPS_HFLAG_UM))
+    if ((env->CP0_Status & (1 << CP0St_CU0)) || 
+        (!(env->hflags & MIPS_HFLAG_UM) && 
+         !(env->hflags & MIPS_HFLAG_SM)))
         env->hflags |= MIPS_HFLAG_CP0;
     if (env->CP0_Status & (1 << CP0St_CU1))
         env->hflags |= MIPS_HFLAG_FPU;
Index: target-mips/helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/helper.c,v
retrieving revision 1.51
diff -u -d -p -r1.51 helper.c
--- target-mips/helper.c        26 Sep 2007 23:52:06 -0000      1.51
+++ target-mips/helper.c        27 Sep 2007 16:18:20 -0000
@@ -106,6 +106,8 @@ static int get_physical_address (CPUStat
 {
     /* User mode can only access useg/xuseg */
     int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM;
+    int supervisor_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_SM;
+    int kernel_mode = !user_mode && !supervisor_mode;
 #ifdef TARGET_MIPS64
     int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
     int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
@@ -120,14 +122,6 @@ static int get_physical_address (CPUStat
     }
 #endif
 
-#ifdef TARGET_MIPS64
-    if (user_mode && address > 0x3FFFFFFFFFFFFFFFULL)
-        return TLBRET_BADADDR;
-#else
-    if (user_mode && address > 0x7FFFFFFFUL)
-        return TLBRET_BADADDR;
-#endif
-
     if (address <= (int32_t)0x7FFFFFFFUL) {
         /* useg */
         if (env->CP0_Status & (1 << CP0St_ERL)) {
@@ -150,16 +144,16 @@ static int get_physical_address (CPUStat
         }
     } else if (address < 0x7FFFFFFFFFFFFFFFULL) {
         /* xsseg */
-       if (SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) {
+       if ((supervisor_mode || kernel_mode) &&
+           SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) {
             ret = env->tlb->map_address(env, physical, prot, address, rw, 
access_type);
        } else {
            ret = TLBRET_BADADDR;
         }
     } else if (address < 0xBFFFFFFFFFFFFFFFULL) {
         /* xkphys */
-        /* XXX: check supervisor mode */
-        if (KX && (address & 0x07FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL)
-       {
+        if (kernel_mode && KX &&
+            (address & 0x07FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL) {
             *physical = address & 0X0000000FFFFFFFFFULL;
             *prot = PAGE_READ | PAGE_WRITE;
        } else {
@@ -167,8 +161,8 @@ static int get_physical_address (CPUStat
        }
     } else if (address < 0xFFFFFFFF7FFFFFFFULL) {
         /* xkseg */
-        /* XXX: check supervisor mode */
-       if (KX && address < (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) {
+       if (kernel_mode && KX &&
+           address < (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) {
             ret = env->tlb->map_address(env, physical, prot, address, rw, 
access_type);
        } else {
            ret = TLBRET_BADADDR;
@@ -176,22 +170,35 @@ static int get_physical_address (CPUStat
 #endif
     } else if (address < (int32_t)0xA0000000UL) {
         /* kseg0 */
-        /* XXX: check supervisor mode */
-        *physical = address - (int32_t)0x80000000UL;
-        *prot = PAGE_READ | PAGE_WRITE;
+        if (kernel_mode) {
+            *physical = address - (int32_t)0x80000000UL;
+            *prot = PAGE_READ | PAGE_WRITE;
+        } else {
+            ret = TLBRET_BADADDR;
+        }
     } else if (address < (int32_t)0xC0000000UL) {
         /* kseg1 */
-        /* XXX: check supervisor mode */
-        *physical = address - (int32_t)0xA0000000UL;
-        *prot = PAGE_READ | PAGE_WRITE;
+        if (kernel_mode) {
+            *physical = address - (int32_t)0xA0000000UL;
+            *prot = PAGE_READ | PAGE_WRITE;
+        } else {
+            ret = TLBRET_BADADDR;
+        }
     } else if (address < (int32_t)0xE0000000UL) {
-        /* kseg2 */
-        ret = env->tlb->map_address(env, physical, prot, address, rw, 
access_type);
+        /* sseg */
+        if (supervisor_mode || kernel_mode) {
+            ret = env->tlb->map_address(env, physical, prot, address, rw, 
access_type);
+        } else {
+            ret = TLBRET_BADADDR;
+        }
     } else {
         /* kseg3 */
-        /* XXX: check supervisor mode */
         /* XXX: debug segment is not emulated */
-        ret = env->tlb->map_address(env, physical, prot, address, rw, 
access_type);
+        if (kernel_mode) {
+            ret = env->tlb->map_address(env, physical, prot, address, rw, 
access_type);
+        } else {
+            ret = TLBRET_BADADDR;
+        }
     }
 #if 0
     if (logfile) {
@@ -369,7 +376,7 @@ void do_interrupt (CPUState *env)
         }
     enter_debug_mode:
         env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
-        env->hflags &= ~MIPS_HFLAG_UM;
+        env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM);
         /* EJTAG probe trap enable is not implemented... */
         if (!(env->CP0_Status & (1 << CP0St_EXL)))
             env->CP0_Cause &= ~(1 << CP0Ca_BD);
@@ -395,7 +402,7 @@ void do_interrupt (CPUState *env)
         }
         env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
         env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
-        env->hflags &= ~MIPS_HFLAG_UM;
+        env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM);
         if (!(env->CP0_Status & (1 << CP0St_EXL)))
             env->CP0_Cause &= ~(1 << CP0Ca_BD);
         env->PC[env->current_tc] = (int32_t)0xBFC00000;
@@ -497,7 +504,7 @@ void do_interrupt (CPUState *env)
             }
             env->CP0_Status |= (1 << CP0St_EXL);
             env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
-            env->hflags &= ~MIPS_HFLAG_UM;
+            env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM);
         }
         env->hflags &= ~MIPS_HFLAG_BMASK;
         if (env->CP0_Status & (1 << CP0St_BEV)) {
Index: target-mips/translate_init.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/translate_init.c,v
retrieving revision 1.22
diff -u -d -p -r1.22 translate_init.c
--- target-mips/translate_init.c        24 Sep 2007 12:48:00 -0000      1.22
+++ target-mips/translate_init.c        27 Sep 2007 16:18:20 -0000
@@ -141,7 +141,7 @@ static mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         /* No DSP implemented. */
-        .CP0_Status_rw_bitmask = 0x1278FF17,
+        .CP0_Status_rw_bitmask = 0x1278FF1F,
         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP,
     },
     {
@@ -156,7 +156,7 @@ static mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         /* No DSP implemented. */
-        .CP0_Status_rw_bitmask = 0x3678FF17,
+        .CP0_Status_rw_bitmask = 0x3678FF1F,
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
                     (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP,
@@ -173,7 +173,7 @@ static mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         /* No DSP implemented. */
-        .CP0_Status_rw_bitmask = 0x3678FF17,
+        .CP0_Status_rw_bitmask = 0x3678FF1F,
         /* No DSP implemented. */
         .CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) |
                     (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) |

-- 
  .''`.  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]