qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH][MIPS] Implement supervisor mode
@ 2007-09-27 16:21 Aurelien Jarno
  0 siblings, 0 replies; only message in thread
From: Aurelien Jarno @ 2007-09-27 16:21 UTC (permalink / raw)
  To: qemu-devel

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
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2007-09-27 16:22 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-27 16:21 [Qemu-devel] [PATCH][MIPS] Implement supervisor mode Aurelien Jarno

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).