qemu-commits
[Top][All Lists]
Advanced

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

[Qemu-commits] [COMMIT 5210977] sparc64: trap handling corrections


From: Anthony Liguori
Subject: [Qemu-commits] [COMMIT 5210977] sparc64: trap handling corrections
Date: Sun, 12 Jul 2009 08:55:57 -0000

From: Igor Kovalenko <address@hidden>

On Sun, Jul 12, 2009 at 12:09 PM, Blue Swirl<address@hidden> wrote:
> On 7/12/09, Igor Kovalenko <address@hidden> wrote:
>> Good trap handling is required to process interrupts.
>>  This patch fixes the following:
>>
>>  - sparc64 has no wim register
>>  - sparc64 has no psret register, use IE bit of pstate
>>   extract IE checking code to cpu_interrupts_enabled
>>  - alternate globals are not available if cpu has GL feature
>>   in this case bit AG of pstate is constant zero
>>  - write to pstate must actually write pstate
>>   even if cpu has GL feature
>>
>>  Also timer interrupt is handled using do_interrupt.
>
> A bit too much for one patch. Please also remove the code instead of
> commenting out.

I now excluded timer interrupt related part.
To my mind other changes are essentially tied together.

> PUT_PSR for Sparc64 needs CC_OP = CC_OP_FLAGS; like Sparc32.

Fixed, please find attached the updated version.

--
Kind regards,
Igor V. Kovalenko

diff --git a/cpu-exec.c b/cpu-exec.c
index 38335f8..9baa949 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -475,7 +475,7 @@ int cpu_exec(CPUState *env1)
                     }
 #elif defined(TARGET_SPARC)
                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
-                       (env->psret != 0)) {
+                       cpu_interrupts_enabled(env)) {
                        int pil = env->interrupt_index & 15;
                        int type = env->interrupt_index & 0xf0;
 
@@ -486,7 +486,7 @@ int cpu_exec(CPUState *env1)
                             env->exception_index = env->interrupt_index;
                             do_interrupt(env);
                            env->interrupt_index = 0;
-#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
                             cpu_check_irqs(env);
 #endif
                         next_tb = 0;
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index d592bea..76e1e79 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -115,15 +115,18 @@ enum {
 #define TBR_BASE_MASK 0xfffff000
 
 #if defined(TARGET_SPARC64)
-#define PS_IG    (1<<11)
-#define PS_MG    (1<<10)
+#define PS_TCT   (1<<12) /* UA2007, impl.dep. trap on control transfer */
+#define PS_IG    (1<<11) /* v9, zero on UA2007 */
+#define PS_MG    (1<<10) /* v9, zero on UA2007 */
+#define PS_CLE   (1<<9) /* UA2007 */
+#define PS_TLE   (1<<8) /* UA2007 */
 #define PS_RMO   (1<<7)
-#define PS_RED   (1<<5)
-#define PS_PEF   (1<<4)
-#define PS_AM    (1<<3)
+#define PS_RED   (1<<5) /* v9, zero on UA2007 */
+#define PS_PEF   (1<<4) /* enable fpu */
+#define PS_AM    (1<<3) /* address mask */
 #define PS_PRIV  (1<<2)
 #define PS_IE    (1<<1)
-#define PS_AG    (1<<0)
+#define PS_AG    (1<<0) /* v9, zero on UA2007 */
 
 #define FPRS_FEF (1<<2)
 
@@ -291,11 +294,15 @@ typedef struct CPUSPARCState {
     float32 fpr[TARGET_FPREGS];  /* floating point registers */
     uint32_t cwp;      /* index of current register window (extracted
                           from PSR) */
+#if !defined(TARGET_SPARC64) || defined(TARGET_ABI32)
     uint32_t wim;      /* window invalid mask */
+#endif
     target_ulong tbr;  /* trap base register */
     int      psrs;     /* supervisor mode (extracted from PSR) */
     int      psrps;    /* previous supervisor mode */
+#if !defined(TARGET_SPARC64)
     int      psret;    /* enable traps */
+#endif
     uint32_t psrpil;   /* interrupt blocking level */
     uint32_t pil_in;   /* incoming interrupt level bitmap */
     int      psref;    /* enable fpu */
@@ -378,12 +385,21 @@ void gen_intermediate_code_init(CPUSPARCState *env);
 /* cpu-exec.c */
 int cpu_sparc_exec(CPUSPARCState *s);
 
+#if !defined (TARGET_SPARC64)
 #define GET_PSR(env) (env->version | (env->psr & PSR_ICC) |             \
                       (env->psref? PSR_EF : 0) |                        \
                       (env->psrpil << 8) |                              \
                       (env->psrs? PSR_S : 0) |                          \
                       (env->psrps? PSR_PS : 0) |                        \
                       (env->psret? PSR_ET : 0) | env->cwp)
+#else
+#define GET_PSR(env) (env->version | (env->psr & PSR_ICC) |             \
+                      (env->psref? PSR_EF : 0) |                        \
+                      (env->psrpil << 8) |                              \
+                      (env->psrs? PSR_S : 0) |                          \
+                      (env->psrps? PSR_PS : 0) |                        \
+                      env->cwp)
+#endif
 
 #ifndef NO_CPU_IO_DEFS
 static inline void memcpy32(target_ulong *dst, const target_ulong *src)
@@ -425,6 +441,7 @@ static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp)
 }
 #endif
 
+#if !defined (TARGET_SPARC64)
 #define PUT_PSR(env, val) do { int _tmp = val;                          \
         env->psr = _tmp & PSR_ICC;                                      \
         env->psref = (_tmp & PSR_EF)? 1 : 0;                            \
@@ -435,6 +452,17 @@ static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp)
         cpu_set_cwp(env, _tmp & PSR_CWP);                               \
         CC_OP = CC_OP_FLAGS;                                            \
     } while (0)
+#else
+#define PUT_PSR(env, val) do { int _tmp = val;                          \
+        env->psr = _tmp & PSR_ICC;                                      \
+        env->psref = (_tmp & PSR_EF)? 1 : 0;                            \
+        env->psrpil = (_tmp & PSR_PIL) >> 8;                            \
+        env->psrs = (_tmp & PSR_S)? 1 : 0;                              \
+        env->psrps = (_tmp & PSR_PS)? 1 : 0;                            \
+        cpu_set_cwp(env, _tmp & PSR_CWP);                               \
+        CC_OP = CC_OP_FLAGS;                                            \
+    } while (0)
+#endif
 
 #ifdef TARGET_SPARC64
 #define GET_CCR(env) (((env->xcc >> 20) << 4) | ((env->psr & PSR_ICC) >> 20))
diff --git a/target-sparc/exec.h b/target-sparc/exec.h
index f37c8ad..e120d6f 100644
--- a/target-sparc/exec.h
+++ b/target-sparc/exec.h
@@ -24,10 +24,23 @@ static inline void regs_to_env(void)
 /* op_helper.c */
 void do_interrupt(CPUState *env);
 
+static inline int cpu_interrupts_enabled(CPUState *env1)
+{
+#if !defined (TARGET_SPARC64)
+    if (env1->psret != 0)
+        return 1;
+#else
+    if (env1->pstate & PS_IE)
+        return 1;
+#endif
+
+    return 0;
+}
+
 static inline int cpu_has_work(CPUState *env1)
 {
     return (env1->interrupt_request & CPU_INTERRUPT_HARD) &&
-           (env1->psret != 0);
+           cpu_interrupts_enabled(env1);
 }
 
 
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index d133294..5f9ad40 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -667,7 +667,9 @@ void cpu_reset(CPUSPARCState *env)
 
     tlb_flush(env, 1);
     env->cwp = 0;
+#ifndef TARGET_SPARC64
     env->wim = 1;
+#endif
     env->regwptr = env->regbase + (env->cwp * 16);
 #if defined(CONFIG_USER_ONLY)
 #ifdef TARGET_SPARC64
@@ -677,7 +679,9 @@ void cpu_reset(CPUSPARCState *env)
     env->asi = 0x82; // Primary no-fault
 #endif
 #else
+#if !defined(TARGET_SPARC64)
     env->psret = 0;
+#endif
     env->psrs = 1;
     env->psrps = 1;
     CC_OP = CC_OP_FLAGS;
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 2449fc7..d25b642 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3225,8 +3225,14 @@ static inline void change_pstate(uint64_t new_pstate)
     uint64_t pstate_regs, new_pstate_regs;
     uint64_t *src, *dst;
 
+    if (env->def->features & CPU_FEATURE_GL) {
+        // PS_AG is not implemented in this case
+        new_pstate &= ~PS_AG;
+    }
+
     pstate_regs = env->pstate & 0xc01;
     new_pstate_regs = new_pstate & 0xc01;
+
     if (new_pstate_regs != pstate_regs) {
         // Switch global register bank
         src = get_gregset(new_pstate_regs);
@@ -3239,8 +3245,7 @@ static inline void change_pstate(uint64_t new_pstate)
 
 void helper_wrpstate(target_ulong new_state)
 {
-    if (!(env->def->features & CPU_FEATURE_GL))
-        change_pstate(new_state & 0xf3f);
+    change_pstate(new_state & 0xf3f);
 }
 
 void helper_done(void)
@@ -3392,23 +3397,23 @@ void do_interrupt(CPUState *env)
     env->tsptr->tpc = env->pc;
     env->tsptr->tnpc = env->npc;
     env->tsptr->tt = intno;
-    if (!(env->def->features & CPU_FEATURE_GL)) {
-        switch (intno) {
-        case TT_IVEC:
-            change_pstate(PS_PEF | PS_PRIV | PS_IG);
-            break;
-        case TT_TFAULT:
-        case TT_TMISS:
-        case TT_DFAULT:
-        case TT_DMISS:
-        case TT_DPROT:
-            change_pstate(PS_PEF | PS_PRIV | PS_MG);
-            break;
-        default:
-            change_pstate(PS_PEF | PS_PRIV | PS_AG);
-            break;
-        }
+
+    switch (intno) {
+    case TT_IVEC:
+        change_pstate(PS_PEF | PS_PRIV | PS_IG);
+        break;
+    case TT_TFAULT:
+    case TT_TMISS:
+    case TT_DFAULT:
+    case TT_DMISS:
+    case TT_DPROT:
+        change_pstate(PS_PEF | PS_PRIV | PS_MG);
+        break;
+    default:
+        change_pstate(PS_PEF | PS_PRIV | PS_AG);
+        break;
     }
+
     if (intno == TT_CLRWIN)
         cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
     else if ((intno & 0x1c0) == TT_SPILL)




reply via email to

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